diff --git a/.babelrc.js b/.babelrc.js index add243a5b5d..74d26caf0fd 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -1 +1,34 @@ -module.exports = require('./babelConfig.js')(); + +let path = require('path'); + +function useLocal(module) { + return require.resolve(module, { + paths: [ + __dirname + ] + }) +} + +module.exports = { + "presets": [ + [ + useLocal('@babel/preset-env'), + { + "targets": { + "browsers": [ + "chrome >= 75", + "safari >=10", + "edge >= 70", + "ff >= 70", + "ie >= 11", + "ios >= 11" + ] + } + } + ] + ], + "plugins": [ + path.resolve(__dirname, './plugins/pbjsGlobals.js'), + useLocal('babel-plugin-transform-object-assign') + ] +}; diff --git a/.circleci/config.yml b/.circleci/config.yml index c11f87b6f59..ea5fb916a91 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,11 +3,11 @@ # Check https://circleci.com/docs/2.0/language-javascript/ for more details # -aliases: +aliases: - &environment docker: # specify the version you desire here - - image: circleci/node:12.16.1-browsers + - image: circleci/node:12.16.1 resource_class: xlarge # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images @@ -36,7 +36,7 @@ aliases: - &run_endtoend_test name: BrowserStack End to end testing - command: gulp e2e-test + command: echo "127.0.0.1 test.localhost" | sudo tee -a /etc/hosts && gulp e2e-test --host=test.localhost # Download and run BrowserStack local - &setup_browserstack @@ -52,7 +52,7 @@ aliases: - &unit_test_steps - checkout - restore_cache: *restore_dep_cache - - run: npm ci + - run: npm install - save_cache: *save_dep_cache - run: *install - run: *setup_browserstack @@ -72,7 +72,7 @@ jobs: build: <<: *environment steps: *unit_test_steps - + e2etest: <<: *environment steps: *endtoend_test_steps @@ -82,6 +82,16 @@ workflows: commit: jobs: - build + nightly: + triggers: + - schedule: + cron: "0 0 * * *" + filters: + branches: + only: + - master + jobs: + - e2etest experimental: pipelines: true diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index cfb29ebdfa9..00000000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -ARG VARIANT="12" -FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:${VARIANT} - -# [Optional] Uncomment this section to install additional OS packages. -# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ -# && apt-get -y install --no-install-recommends - -RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - -RUN echo "deb http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list -RUN apt update -RUN apt install -y google-chrome-stable xvfb diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 0176b8317b3..00000000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,27 +0,0 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: -// https://github.com/microsoft/vscode-dev-containers/tree/main/containers/javascript-node -{ - "name": "Ubuntu", - - "build": { - "dockerfile": "Dockerfile", - "args": { "VARIANT": "12" } - }, - - "postCreateCommand": "bash .devcontainer/postCreate.sh", - - // Set *default* container specific settings.json values on container create. - "settings": {}, - - - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "nickdodd79.gulptasks" - ], - - // 9999 is web server, 9876 is karma - "forwardPorts": [9876, 9999], - - // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "node" -} diff --git a/.devcontainer/postCreate.sh b/.devcontainer/postCreate.sh deleted file mode 100644 index 7e14a2d200d..00000000000 --- a/.devcontainer/postCreate.sh +++ /dev/null @@ -1,6 +0,0 @@ -echo "Post Create Starting" - -nvm install -nvm use -npm install gulp-cli -g -npm ci diff --git a/.eslintrc.js b/.eslintrc.js index d3379d70919..78e4fb1bb33 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -23,13 +23,10 @@ module.exports = { 'BROWSERSTACK_USERNAME': false, 'BROWSERSTACK_KEY': false }, - // use babel as parser for fancy syntax - parser: '@babel/eslint-parser', parserOptions: { sourceType: 'module', ecmaVersion: 2018, }, - rules: { 'comma-dangle': 'off', semi: 'off', @@ -52,9 +49,5 @@ module.exports = { rules: { 'prebid/validate-imports': ['error', allowedModules[key]] } - })).concat([{ - // code in other packages (such as plugins/eslint) is not "seen" by babel and its parser will complain. - files: 'plugins/*/**/*.js', - parser: 'esprima' - }]) + })) }; diff --git a/.github/workflows/issue_tracker.yml b/.github/workflows/issue_tracker.yml deleted file mode 100644 index 4397337b4c7..00000000000 --- a/.github/workflows/issue_tracker.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: Issue tracking -on: - issues: - types: - - opened -jobs: - track_issue: - runs-on: ubuntu-latest - steps: - - name: Generate token - id: generate_token - uses: tibdex/github-app-token@36464acb844fc53b9b8b2401da68844f6b05ebb0 - with: - app_id: ${{ secrets.ISSUE_APP_ID }} - private_key: ${{ secrets.ISSUE_APP_PEM }} - - - name: Get project data - env: - GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} - ORGANIZATION: prebid - DATE_FIELD: Created on - PROJECT_NUMBER: 2 - run: | - gh api graphql -f query=' - query($org: String!, $number: Int!) { - organization(login: $org){ - projectNext(number: $number) { - id - fields(first:100) { - nodes { - id - name - settings - } - } - } - } - }' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json - - echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV - echo 'DATE_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "'"$DATE_FIELD"'") | .id' project_data.json) >> $GITHUB_ENV - - - name: Add issue to project - env: - GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} - ISSUE_ID: ${{ github.event.issue.node_id }} - run: | - gh api graphql -f query=' - mutation($project:ID!, $issue:ID!) { - addProjectNextItem(input: {projectId: $project, contentId: $issue}) { - projectNextItem { - id, - content { - ... on Issue { - createdAt - } - ... on PullRequest { - createdAt - } - } - } - } - }' -f project=$PROJECT_ID -f issue=$ISSUE_ID > issue_data.json - - echo 'ITEM_ID='$(jq '.data.addProjectNextItem.projectNextItem.id' issue_data.json) >> $GITHUB_ENV - echo 'ITEM_CREATION_DATE='$(jq '.data.addProjectNextItem.projectNextItem.content.createdAt' issue_data.json) >> $GITHUB_ENV - - - name: Set fields - env: - GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} - run: | - gh api graphql -f query=' - mutation ( - $project: ID! - $item: ID! - $date_field: ID! - $date_value: String! - ) { - set_creation_date: updateProjectNextItemField(input: { - projectId: $project - itemId: $item - fieldId: $date_field - value: $date_value - }) { - projectNextItem { - id - } - } - }' -f project=$PROJECT_ID -f item=$ITEM_ID -f date_field=$DATE_FIELD_ID -f date_value=$ITEM_CREATION_DATE --silent diff --git a/PR_REVIEW.md b/PR_REVIEW.md index 2934a30fb47..1152e2942bf 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -51,16 +51,11 @@ Follow steps above for general review process. In addition, please verify the fo - If the adapter being submitted is an alias type, check with the bidder contact that is being aliased to make sure it's allowed. - All bidder parameter conventions must be followed: - Video params must be read from AdUnit.mediaTypes.video when available; however bidder config can override the ad unit. - - First party data must be read from [getConfig('ortb2');](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd). + - First party data must be read from [`fpd.context` and `fpd.user`](https://docs.prebid.org/dev-docs/publisher-api-reference.html#setConfig-fpd). - Adapters that accept a floor parameter must also support the [floors module](https://docs.prebid.org/dev-docs/modules/floors.html) -- look for a call to the `getFloor()` function. - Adapters cannot accept an schain parameter. Rather, they must look for the schain parameter at bidRequest.schain. - - The bidderRequest.refererInfo.referer must be checked in addition to any bidder-specific parameter. + - The bidRequest page referrer must checked in addition to any bidder-specific parameter. - If they're getting the COPPA flag, it must come from config.getConfig('coppa'); - - Page position must come from bidrequest.mediaTypes.banner.pos or bidrequest.mediaTypes.video.pos - - Global OpenRTB fields should come from [getConfig('ortb2');](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd): - - bcat, battr, badv - - Impression-specific OpenRTB fields should come from bidrequest.ortb2imp - - instl - Below are some examples of bidder specific updates that should require docs update (in their dev-docs/bidders/BIDDER.md file): - If they support the GDPR consentManagement module and TCF1, add `gdpr_supported: true` - If they support the GDPR consentManagement module and TCF2, add `tcf2_supported: true` diff --git a/README.md b/README.md index 42d747b20b6..a220dd69f66 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ [![Build Status](https://circleci.com/gh/prebid/Prebid.js.svg?style=svg)](https://circleci.com/gh/prebid/Prebid.js) [![Percentage of issues still open](http://isitmaintained.com/badge/open/prebid/Prebid.js.svg)](http://isitmaintained.com/project/prebid/Prebid.js "Percentage of issues still open") +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/prebid/Prebid.js.svg)](http://isitmaintained.com/project/prebid/Prebid.js "Average time to resolve an issue") [![Code Climate](https://codeclimate.com/github/prebid/Prebid.js/badges/gpa.svg)](https://codeclimate.com/github/prebid/Prebid.js) [![Coverage Status](https://coveralls.io/repos/github/prebid/Prebid.js/badge.svg)](https://coveralls.io/github/prebid/Prebid.js) [![devDependencies Status](https://david-dm.org/prebid/Prebid.js/dev-status.svg)](https://david-dm.org/prebid/Prebid.js?type=dev) @@ -59,8 +60,6 @@ module.exports = { loader: 'babel-loader', // presets and plugins for Prebid.js must be manually specified separate from your other babel rule. // this can be accomplished by requiring prebid's .babelrc.js file (requires Babel 7 and Node v8.9.0+) - // as of Prebid 6, babelrc.js only targets modern browsers. One can change the targets and build for - // older browsers if they prefer, but integration tests on ie11 were removed in Prebid.js 6.0 options: require('prebid.js/.babelrc.js') } } @@ -130,22 +129,16 @@ Once setup, run the following command to globally install the `gulp-cli` package ## Build for Development -To build the project on your local machine we recommend, running: +To build the project on your local machine, run: - $ gulp serve-and-test --file + $ gulp serve -This will run testing but not linting. A web server will start at `http://localhost:9999` serving from the project root and generates the following files: +This runs some code quality checks, starts a web server at `http://localhost:9999` serving from the project root and generates the following files: + `./build/dev/prebid.js` - Full source code for dev and debug + `./build/dev/prebid.js.map` - Source map for dev and debug -+ `./build/dev/prebid-core.js` -+ `./build/dev/prebid-core.js.map` - - -Development may be a bit slower but if you prefer linting and additional watch files you can also still run just: - - $ gulp serve - ++ `./build/dist/prebid.js` - Minified production code ++ `./prebid.js_.zip` - Distributable zip archive ### Build Optimization @@ -159,7 +152,7 @@ Building with just these adapters will result in a smaller bundle which should a **Build standalone prebid.js** -- Clone the repo, run `npm ci` +- Clone the repo, run `npm install` - Then run the build: $ gulp build --modules=openxBidAdapter,rubiconBidAdapter,sovrnBidAdapter @@ -280,7 +273,7 @@ As you make code changes, the bundles will be rebuilt and the page reloaded auto ## Contribute -Many SSPs, bidders, and publishers have contributed to this project. [Hundreds of bidders](https://github.com/prebid/Prebid.js/tree/master/modules) are supported by Prebid.js. +Many SSPs, bidders, and publishers have contributed to this project. [Hundreds of bidders](https://github.com/prebid/Prebid.js/tree/master/src/adapters) are supported by Prebid.js. For guidelines, see [Contributing](./CONTRIBUTING.md). @@ -322,7 +315,7 @@ For instructions on writing tests for Prebid.js, see [Testing Prebid.js](http:// ### Supported Browsers -Prebid.js is supported on IE11 and modern browsers until 5.x. 6.x+ transpiles to target >0.25%; not Opera Mini; not IE11. +Prebid.js is supported on IE11 and modern browsers. ### Governance Review our governance model [here](https://github.com/prebid/Prebid.js/tree/master/governance.md). diff --git a/RELEASE_SCHEDULE.md b/RELEASE_SCHEDULE.md index b68495ed4ae..bfbd0772c3e 100644 --- a/RELEASE_SCHEDULE.md +++ b/RELEASE_SCHEDULE.md @@ -3,7 +3,12 @@ - [Release Process](#release-process) - [1. Make sure that all PRs have been named and labeled properly per the PR Process](#1-make-sure-that-all-prs-have-been-named-and-labeled-properly-per-the-pr-process) - [2. Make sure all browserstack tests are passing](#2-make-sure-all-browserstack-tests-are-passing) - - [3. Start the release](#3-start-the-release) + - [3. Prepare Prebid Code](#3-prepare-prebid-code) + - [4. Verify the Release](#4-verify-the-release) + - [5. Create a GitHub release](#5-create-a-github-release) + - [6. Update coveralls _(skip for legacy)_](#6-update-coveralls-skip-for-legacy) + - [7. Distribute the code](#7-distribute-the-code) + - [8. Increment Version for Next Release](#8-increment-version-for-next-release) - [Beta Releases](#beta-releases) - [FAQs](#faqs) @@ -16,10 +21,12 @@ it will be about a week before the Prebid Org [Download Page](http://prebid.org/ You can determine what is in a given build using the [releases page](https://github.com/prebid/Prebid.js/releases) -Announcements regarding releases will be made to the #prebid-js channel in prebid.slack.com. +Announcements regarding releases will be made to the #headerbidding-dev channel in subredditadops.slack.com. ## Release Process +_Note: If `github.com/prebid/Prebid.js` is not configured as the git origin for your repo, all of the following git commands will have to be modified to reference the proper remote (e.g. `upstream`)_ + ### 1. Make sure that all PRs have been named and labeled properly per the [PR Process](https://github.com/prebid/Prebid.js/blob/master/PR_REVIEW.md#general-pr-review-process) * Do this by checking the latest draft release from the [releases page](https://github.com/prebid/Prebid.js/releases) and make sure nothing appears in the first section called "In This Release". If they do, please open the PRs and add the appropriate labels. * Do a quick check that all the titles/descriptions look ok, and if not, adjust the PR title. @@ -50,10 +57,61 @@ Announcements regarding releases will be made to the #prebid-js channel in prebi ``` -### 3. Start the release +### 3. Prepare Prebid Code + + Update the package.json version to become the current release. Then commit your changes. + + ``` + git commit -m "Prebid 4.x.x Release" + git push + ``` + +### 4. Verify the Release + + Make sure your there are no more merges to master branch. Prebid code is clean and up to date. + +### 5. Create a GitHub release + + Edit the most recent [release notes](https://github.com/prebid/Prebid.js/releases) draft and make sure the correct version is set and the master branch is selected in the dropdown. Click `Publish release`. GitHub will create release tag. + + Pull these changes locally by running command + ``` + git pull + git fetch --tags + ``` + + and verify the tag. + +### 6. Update coveralls _(skip for legacy)_ + + We use https://coveralls.io/ to show parts of code covered by unit tests. + + Set the environment variables. You may want to add these to your `~/.bashrc` for convenience. + ``` + export COVERALLS_SERVICE_NAME="travis-ci" + export COVERALLS_REPO_TOKEN="talk to Matt Kendall" + ``` + + Run `gulp coveralls` to update code coverage history. + +### 7. Distribute the code + + _Note: do not go to step 8 until step 7 has been verified completed._ + + Reach out to any of the Appnexus folks to trigger the jenkins job. + + // TODO: + Jenkins job is moving files to appnexus cdn, pushing prebid.js to npm, purging cache and sending notification to slack. + Move all the files from Appnexus CDN to jsDelivr and create bash script to do above tasks. + +### 8. Increment Version for Next Release + + Update the version by manually editing Prebid's `package.json` to become "4.x.x-pre" (using the values for the next release). Then commit your changes. + ``` + git commit -m "Increment pre version" + git push + ``` -Follow the instructions at https://github.com/prebid/prebidjs-releaser. Note that you will need to be a member of the [https://github.com/orgs/prebid/teams/prebidjs-release](prebidjs-release) GitHub team. - ## Beta Releases Prebid.js features may be released as Beta or as Generally Available (GA). diff --git a/allowedModules.js b/allowedModules.js index be9a2dc2abf..2d23b35c501 100644 --- a/allowedModules.js +++ b/allowedModules.js @@ -1,5 +1,11 @@ const sharedWhiteList = [ + 'core-js-pure/features/array/find', // no ie11 + 'core-js-pure/features/array/includes', // no ie11 + 'core-js-pure/features/set', // ie11 supports Set but not Set#values + 'core-js-pure/features/string/includes', // no ie11 + 'core-js-pure/features/number/is-integer', // no ie11, + 'core-js-pure/features/array/from' // no ie11 ]; module.exports = { diff --git a/babelConfig.js b/babelConfig.js deleted file mode 100644 index c1ddc11b689..00000000000 --- a/babelConfig.js +++ /dev/null @@ -1,30 +0,0 @@ - -let path = require('path'); - -function useLocal(module) { - return require.resolve(module, { - paths: [ - __dirname - ] - }) -} - -module.exports = function (test = false) { - return { - 'presets': [ - [ - useLocal('@babel/preset-env'), - { - 'useBuiltIns': 'entry', - 'corejs': '3.13.0', - // a lot of tests use sinon.stub & others that stopped working on ES6 modules with webpack 5 - 'modules': test ? 'commonjs' : 'auto', - } - ] - ], - 'plugins': [ - path.resolve(__dirname, './plugins/pbjsGlobals.js'), - useLocal('babel-plugin-transform-object-assign'), - ], - } -} diff --git a/browsers.json b/browsers.json index bd6bd5772d6..4f2ea456f68 100644 --- a/browsers.json +++ b/browsers.json @@ -1,51 +1,74 @@ { - "bs_edge_latest_windows_10": { + "bs_edge_17_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "edge", - "browser_version": "latest", + "browser_version": "17.0", "device": null, "os": "Windows" }, - "bs_chrome_latest_windows_10": { + "bs_edge_90_windows_10": { + "base": "BrowserStack", + "os_version": "10", + "browser": "edge", + "browser_version": "90.0", + "device": null, + "os": "Windows" + }, + "bs_ie_11_windows_10": { + "base": "BrowserStack", + "os_version": "10", + "browser": "ie", + "browser_version": "11.0", + "device": null, + "os": "Windows" + }, + "bs_chrome_90_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "chrome", - "browser_version": "latest", + "browser_version": "90.0", "device": null, "os": "Windows" }, - "bs_chrome_87_windows_10": { + "bs_chrome_79_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "chrome", - "browser_version": "87.0", + "browser_version": "79.0", + "device": null, + "os": "Windows" + }, + "bs_firefox_88_windows_10": { + "base": "BrowserStack", + "os_version": "10", + "browser": "firefox", + "browser_version": "88.0", "device": null, "os": "Windows" }, - "bs_firefox_latest_windows_10": { + "bs_firefox_72_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "firefox", - "browser_version": "latest", + "browser_version": "72.0", "device": null, "os": "Windows" }, - "bs_safari_latest_mac_bigsur": { + "bs_safari_14_mac_bigsur": { "base": "BrowserStack", "os_version": "Big Sur", "browser": "safari", - "browser_version": "latest", + "browser_version": "14.0", "device": null, "os": "OS X" }, - "bs_safari_15_catalina": { + "bs_safari_12_mac_mojave": { "base": "BrowserStack", - "os_version": "Catalina", + "os_version": "Mojave", "browser": "safari", - "browser_version": "13.1", + "browser_version": "12.0", "device": null, "os": "OS X" } - } diff --git a/gulpfile.js b/gulpfile.js index ff49436384b..8609177a8b9 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -8,6 +8,7 @@ var gutil = require('gulp-util'); var connect = require('gulp-connect'); var webpack = require('webpack'); var webpackStream = require('webpack-stream'); +var terser = require('gulp-terser'); var gulpClean = require('gulp-clean'); var KarmaServer = require('karma').Server; var karmaConfMaker = require('./karma.conf.maker.js'); @@ -32,8 +33,8 @@ var prebid = require('./package.json'); var dateString = 'Updated : ' + (new Date()).toISOString().substring(0, 10); var banner = '/* <%= prebid.name %> v<%= prebid.version %>\n' + dateString + '*/\n'; var port = 9999; -const INTEG_SERVER_HOST = argv.host ? argv.host : 'localhost'; -const INTEG_SERVER_PORT = 4444; +const FAKE_SERVER_HOST = argv.host ? argv.host : 'localhost'; +const FAKE_SERVER_PORT = 4444; const { spawn } = require('child_process'); // these modules must be explicitly listed in --modules to be included in the build, won't be part of "all" modules @@ -75,7 +76,6 @@ function lint(done) { 'modules/**/*.js', 'test/**/*.js', 'plugins/**/*.js', - '!plugins/**/node_modules/**', './*.js' ], { base: './' }) .pipe(gulpif(argv.nolintfix, eslint(), eslint({ fix: true }))) @@ -114,12 +114,41 @@ function viewReview(done) { viewReview.displayName = 'view-review'; +// Watch Task with Live Reload +function watch(done) { + var mainWatcher = gulp.watch([ + 'src/**/*.js', + 'modules/**/*.js', + 'test/spec/**/*.js', + '!test/spec/loaders/**/*.js' + ]); + var loaderWatcher = gulp.watch([ + 'loaders/**/*.js', + 'test/spec/loaders/**/*.js' + ]); + + connect.server({ + https: argv.https, + port: port, + host: FAKE_SERVER_HOST, + root: './', + livereload: true + }); + + mainWatcher.on('all', gulp.series(clean, gulp.parallel(lint, 'build-bundle-dev', test))); + loaderWatcher.on('all', gulp.series(lint)); + done(); +}; + +function makeModuleList(modules) { + return modules.map(module => { + return '"' + module + '"' + }); +} + function makeDevpackPkg() { var cloned = _.cloneDeep(webpackConfig); - Object.assign(cloned, { - devtool: 'source-map', - mode: 'development' - }) + cloned.devtool = 'source-map'; var externalModules = helpers.getArgModules(); const analyticsSources = helpers.getAnalyticsSources(); @@ -128,15 +157,14 @@ function makeDevpackPkg() { return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) .pipe(helpers.nameModules(externalModules)) .pipe(webpackStream(cloned, webpack)) + .pipe(replace(/('|")v\$prebid\.modulesList\$('|")/g, makeModuleList(externalModules))) .pipe(gulp.dest('build/dev')) .pipe(connect.reload()); } function makeWebpackPkg() { var cloned = _.cloneDeep(webpackConfig); - if (!argv.sourceMaps) { - delete cloned.devtool; - } + delete cloned.devtool; var externalModules = helpers.getArgModules(); @@ -146,19 +174,12 @@ function makeWebpackPkg() { return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) .pipe(helpers.nameModules(externalModules)) .pipe(webpackStream(cloned, webpack)) + .pipe(terser()) + .pipe(replace(/('|")v\$prebid\.modulesList\$('|")/g, makeModuleList(externalModules))) + .pipe(gulpif(file => file.basename === 'prebid-core.js', header(banner, { prebid: prebid }))) .pipe(gulp.dest('build/dist')); } -function addBanner() { - const sm = argv.sourceMaps; - - return gulp.src(['build/dist/prebid-core.js']) - .pipe(gulpif(sm, sourcemaps.init({loadMaps: true}))) - .pipe(header(banner, {prebid})) - .pipe(gulpif(sm, sourcemaps.write('.'))) - .pipe(gulp.dest('build/dist')) -} - function getModulesListToAddInBanner(modules) { return (modules.length > 0) ? modules.join(', ') : 'All available modules in current version.'; } @@ -167,9 +188,9 @@ function gulpBundle(dev) { return bundle(dev).pipe(gulp.dest('build/' + (dev ? 'dev' : 'dist'))); } -function nodeBundle(modules, dev = false) { +function nodeBundle(modules) { return new Promise((resolve, reject) => { - bundle(dev, modules) + bundle(false, modules) .on('error', (err) => { reject(err); }) @@ -183,7 +204,6 @@ function nodeBundle(modules, dev = false) { function bundle(dev, moduleArr) { var modules = moduleArr || helpers.getArgModules(); var allModules = helpers.getModuleNames(modules); - const sm = dev || argv.sourceMaps; if (modules.length === 0) { modules = allModules.filter(module => explicitModules.indexOf(module) === -1); @@ -215,13 +235,13 @@ function bundle(dev, moduleArr) { ) // Need to uodate the "Modules: ..." section in comment with the current modules list .pipe(replace(/(Modules: )(.*?)(\*\/)/, ('$1' + getModulesListToAddInBanner(helpers.getArgModules()) + ' $3'))) - .pipe(gulpif(sm, sourcemaps.init({ loadMaps: true }))) + .pipe(gulpif(dev, sourcemaps.init({ loadMaps: true }))) .pipe(concat(outputFileName)) .pipe(gulpif(!argv.manualEnable, footer('\n<%= global %>.processQueue();', { global: prebid.globalVarName } ))) - .pipe(gulpif(sm, sourcemaps.write('.'))); + .pipe(gulpif(dev, sourcemaps.write('.'))); } // Run the unit tests. @@ -234,63 +254,58 @@ function bundle(dev, moduleArr) { // If --browsers is given, browsers can be chosen explicitly. e.g. --browsers=chrome,firefox,ie9 // If --notest is given, it will immediately skip the test task (useful for developing changes with `gulp serve --notest`) -function testTaskMaker(options = {}) { - ['watch', 'e2e', 'file', 'browserstack', 'notest'].forEach(opt => { - options[opt] = options[opt] || argv[opt]; - }) - - return function test(done) { - if (options.notest) { - done(); - } else if (options.e2e) { - const integ = startIntegServer(); - startLocalServer(); - runWebdriver(options) - .then(stdout => { - // kill fake server - integ.kill('SIGINT'); - done(); - process.exit(0); - }) - .catch(err => { - // kill fake server - integ.kill('SIGINT'); - done(new Error(`Tests failed with error: ${err}`)); - process.exit(1); - }); +function test(done) { + if (argv.notest) { + done(); + } else if (argv.e2e) { + let wdioCmd = path.join(__dirname, 'node_modules/.bin/wdio'); + let wdioConf = path.join(__dirname, 'wdio.conf.js'); + let wdioOpts; + + if (argv.file) { + wdioOpts = [ + wdioConf, + `--spec`, + `${argv.file}` + ] } else { - var karmaConf = karmaConfMaker(false, options.browserstack, options.watch, options.file); - - var browserOverride = helpers.parseBrowserArgs(argv); - if (browserOverride.length > 0) { - karmaConf.browsers = browserOverride; - } - - new KarmaServer(karmaConf, newKarmaCallback(done)).start(); + wdioOpts = [ + wdioConf + ]; } - } -} -const test = testTaskMaker(); + // run fake-server + const fakeServer = spawn('node', ['./test/fake-server/index.js', `--port=${FAKE_SERVER_PORT}`]); + fakeServer.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + fakeServer.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + }); + + execa(wdioCmd, wdioOpts, { stdio: 'inherit' }) + .then(stdout => { + // kill fake server + fakeServer.kill('SIGINT'); + done(); + process.exit(0); + }) + .catch(err => { + // kill fake server + fakeServer.kill('SIGINT'); + done(new Error(`Tests failed with error: ${err}`)); + process.exit(1); + }); + } else { + var karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch, argv.file); -function runWebdriver({file}) { - process.env.TEST_SERVER_HOST = argv.host || 'localhost'; - let wdioCmd = path.join(__dirname, 'node_modules/.bin/wdio'); - let wdioConf = path.join(__dirname, 'wdio.conf.js'); - let wdioOpts; + var browserOverride = helpers.parseBrowserArgs(argv); + if (browserOverride.length > 0) { + karmaConf.browsers = browserOverride; + } - if (file) { - wdioOpts = [ - wdioConf, - `--spec`, - `${file}` - ] - } else { - wdioOpts = [ - wdioConf - ]; + new KarmaServer(karmaConf, newKarmaCallback(done)).start(); } - return execa(wdioCmd, wdioOpts, { stdio: 'inherit' }); } function newKarmaCallback(done) { @@ -332,53 +347,42 @@ function buildPostbid() { .pipe(gulp.dest('build/postbid/')); } -function startIntegServer(dev = false) { - const args = ['./test/fake-server/index.js', `--port=${INTEG_SERVER_PORT}`, `--host=${INTEG_SERVER_HOST}`]; - if (dev) { - args.push('--dev=true') +function setupE2e(done) { + if (!argv.host) { + throw new gutil.PluginError({ + plugin: 'E2E test', + message: gutil.colors.red('Host should be defined e.g. ap.localhost, anlocalhost. localhost cannot be used as safari browserstack is not able to connect to localhost') + }); } - const srv = spawn('node', args); - srv.stdout.on('data', (data) => { - console.log(`stdout: ${data}`); - }); - srv.stderr.on('data', (data) => { - console.log(`stderr: ${data}`); - }); - return srv; + process.env.TEST_SERVER_HOST = argv.host; + if (argv.https) { + process.env.TEST_SERVER_PROTOCOL = argv.https; + } + argv.e2e = true; + done(); } -function startLocalServer(options = {}) { - connect.server({ - https: argv.https, - port: port, - host: INTEG_SERVER_HOST, - root: './', - livereload: options.livereload - }); +function injectFakeServerEndpoint() { + return gulp.src(['build/dist/*.js']) + .pipe(replace('https://ib.adnxs.com/ut/v3/prebid', `http://${FAKE_SERVER_HOST}:${FAKE_SERVER_PORT}`)) + .pipe(gulp.dest('build/dist')); } -// Watch Task with Live Reload -function watchTaskMaker(options = {}) { - if (options.livereload == null) { - options.livereload = true; - } - options.alsoWatch = options.alsoWatch || []; - - return function watch(done) { - var mainWatcher = gulp.watch([ - 'src/**/*.js', - 'modules/**/*.js', - ].concat(options.alsoWatch)); - - startLocalServer(options); - - mainWatcher.on('all', options.task()); - done(); - } +function injectFakeServerEndpointDev() { + return gulp.src(['build/dev/*.js']) + .pipe(replace('https://ib.adnxs.com/ut/v3/prebid', `http://${FAKE_SERVER_HOST}:${FAKE_SERVER_PORT}`)) + .pipe(gulp.dest('build/dev')); } -const watch = watchTaskMaker({alsoWatch: ['test/**/*.js'], task: () => gulp.series(clean, gulp.parallel(lint, 'build-bundle-dev', test))}); -const watchFast = watchTaskMaker({livereload: false, task: () => gulp.series('build-bundle-dev')}); +function startFakeServer() { + const fakeServer = spawn('node', ['./test/fake-server/index.js', `--port=${FAKE_SERVER_PORT}`]); + fakeServer.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + fakeServer.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + }); +} // support tasks gulp.task(lint); @@ -389,11 +393,10 @@ gulp.task(clean); gulp.task(escapePostbidConfig); gulp.task('build-bundle-dev', gulp.series(makeDevpackPkg, gulpBundle.bind(null, true))); -gulp.task('build-bundle-prod', gulp.series(makeWebpackPkg, addBanner, gulpBundle.bind(null, false))); +gulp.task('build-bundle-prod', gulp.series(makeWebpackPkg, gulpBundle.bind(null, false))); // public tasks (dependencies are needed for each task since they can be ran on their own) -gulp.task('test-only', test); -gulp.task('test', gulp.series(clean, lint, 'test-only')); +gulp.task('test', gulp.series(clean, lint, test)); gulp.task('test-coverage', gulp.series(clean, testCoverage)); gulp.task(viewCoverage); @@ -404,15 +407,12 @@ gulp.task('build', gulp.series(clean, 'build-bundle-prod')); gulp.task('build-postbid', gulp.series(escapePostbidConfig, buildPostbid)); gulp.task('serve', gulp.series(clean, lint, gulp.parallel('build-bundle-dev', watch, test))); -gulp.task('serve-fast', gulp.series(clean, gulp.parallel('build-bundle-dev', watchFast))); -gulp.task('serve-and-test', gulp.series(clean, gulp.parallel('build-bundle-dev', watchFast, testTaskMaker({watch: true})))); -gulp.task('serve-e2e', gulp.series(clean, 'build-bundle-prod', gulp.parallel(() => startIntegServer(), startLocalServer))) -gulp.task('serve-e2e-dev', gulp.series(clean, 'build-bundle-dev', gulp.parallel(() => startIntegServer(true), startLocalServer))) +gulp.task('serve-fast', gulp.series(clean, gulp.parallel('build-bundle-dev', watch))); +gulp.task('serve-fake', gulp.series(clean, gulp.parallel('build-bundle-dev', watch), injectFakeServerEndpointDev, test, startFakeServer)); -gulp.task('default', gulp.series(clean, 'build-bundle-prod')); +gulp.task('default', gulp.series(clean, makeWebpackPkg)); -gulp.task('e2e-test-only', () => runWebdriver({file: argv.file})) -gulp.task('e2e-test', gulp.series(clean, 'build-bundle-prod', testTaskMaker({e2e: true}))); +gulp.task('e2e-test', gulp.series(clean, setupE2e, gulp.parallel('build-bundle-prod', watch), injectFakeServerEndpoint, test)); // other tasks gulp.task(bundleToStdout); gulp.task('bundle', gulpBundle.bind(null, false)); // used for just concatenating pre-built files with no build step diff --git a/integrationExamples/gpt/adloox.html b/integrationExamples/gpt/adloox.html index fd61267479d..2a772bb7ce2 100644 --- a/integrationExamples/gpt/adloox.html +++ b/integrationExamples/gpt/adloox.html @@ -64,11 +64,9 @@ playerSize: [ 640, 480 ] } }, - ortb2Imp: { - ext: { - data: { - pbadslot: '/19968336/prebid_cache_video_adunit' - } + fpd: { + context: { + pbAdSlot: '/19968336/prebid_cache_video_adunit' } }, bids: [ @@ -108,8 +106,7 @@ pbjs.initAdserverSet = true; googletag.cmd.push(function() { - const adUnitCodes = adUnits.map(adUnit => adUnit.code); - pbjs.setTargetingForGPTAsync(adUnitCodes); + pbjs.setTargetingForGPTAsync && pbjs.setTargetingForGPTAsync(adUnits); googletag.pubads().refresh(); }); @@ -138,34 +135,18 @@ } // optionally wrap with googletag to have gpt-pre-auction - // automatically populate Prebid Ad Slot (pbadslot) + // automatically populate Prebid Ad Slot (pbAdSlot) // https://docs.prebid.org/dev-docs/modules/gpt-pre-auction.html - // alternatively remove wrapping and set AdUnit.ortb2Imp.ext.data.pbadslot + // alternatively remove wrapping and set AdUnit.fpd.context.pbAdSlot googletag.cmd.push(function() { pbjs.que.push(function() { pbjs.setConfig({ - realTimeData: { - auctionDelay: AUCTION_DELAY, - dataProviders: [ - { - name: 'adloox', - params: { // optional, defaults shown - thresholds: [ 50, 60, 70, 80, 90 ], - slotinpath: false - } - } - ] - }, instreamTracking: { enabled: true }, rubicon: { singleRequest: true - }, - // RTD module honors pageUrl for referrer detection and - // the analytics module uses this for the 'pageurl' macro - // N.B. set this to a non-example.com URL to see the video - //pageUrl: 'https://yourdomain.com/some/path/to/content.html' + } }); pbjs.enableAnalytics({ provider: 'adloox', diff --git a/integrationExamples/gpt/afpExample.html b/integrationExamples/gpt/afpExample.html deleted file mode 100644 index a1e6e800d69..00000000000 --- a/integrationExamples/gpt/afpExample.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - Prebid.js Banner Example - - - - -

In-image

-
-
- -
- -
- -

In-image Max

-
-
- -
- -
- -

In-content Banner

-
-
- -
- -

In-content Stories

-
-
- -
- -

Action Scroller

-
-
- -
- -

Action Scroller Light

-
-
- -
- -

Just Banner

-
-
- -
- -

In-content Video

-
-
- -
- - - - - diff --git a/integrationExamples/gpt/afpGamExample.html b/integrationExamples/gpt/afpGamExample.html deleted file mode 100644 index 64cb169893c..00000000000 --- a/integrationExamples/gpt/afpGamExample.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - - Prebid.js Banner Example - - - - - -

In-image

-
-
- -
-
- -
-
- -

In-content Video

-
-
-
- -
-
- -

Action Scroller

-
-
-
- -
-
- - diff --git a/integrationExamples/gpt/akamaidap_segments_example.html b/integrationExamples/gpt/akamaidap_segments_example.html deleted file mode 100644 index e85ac8e1337..00000000000 --- a/integrationExamples/gpt/akamaidap_segments_example.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - -

Prebid.js Test

-
Div-1
-
- -
-
Segments Sent to Bidding Adapter
-
- - diff --git a/integrationExamples/gpt/amp/creative.html b/integrationExamples/gpt/amp/creative.html index 384b81107cc..86f669dd6b5 100644 --- a/integrationExamples/gpt/amp/creative.html +++ b/integrationExamples/gpt/amp/creative.html @@ -1,16 +1,38 @@ - diff --git a/integrationExamples/gpt/esp_example.html b/integrationExamples/gpt/esp_example.html deleted file mode 100644 index c39a67243cc..00000000000 --- a/integrationExamples/gpt/esp_example.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - - - - - - - -

Basic Prebid.js Example

- -
Div-1
-
- -
- -
- -
Div-2
-
- -
- - - - \ No newline at end of file diff --git a/integrationExamples/gpt/hadronRtdProvider_example.html b/integrationExamples/gpt/haloRtdProvider_example.html similarity index 87% rename from integrationExamples/gpt/hadronRtdProvider_example.html rename to integrationExamples/gpt/haloRtdProvider_example.html index 065c8379956..14debbd2698 100644 --- a/integrationExamples/gpt/hadronRtdProvider_example.html +++ b/integrationExamples/gpt/haloRtdProvider_example.html @@ -1,8 +1,8 @@ -Hadron Id: -
+Halo Id: +
-Hadron Real-Time Data: +Halo Real-Time Data:
diff --git a/integrationExamples/gpt/idImportLibrary_example.html b/integrationExamples/gpt/idImportLibrary_example.html index 363e8015f53..07a4f0fe1c5 100644 --- a/integrationExamples/gpt/idImportLibrary_example.html +++ b/integrationExamples/gpt/idImportLibrary_example.html @@ -69,10 +69,10 @@ name: "zeotapIdPlus" }, { - name: 'hadronId', + name: 'haloId', storage: { type: "html5", - name: "hadronId", + name: "haloId", expires: 28 } }, { diff --git a/integrationExamples/gpt/idward_segments_example.html b/integrationExamples/gpt/idward_segments_example.html deleted file mode 100644 index 9bc06124c77..00000000000 --- a/integrationExamples/gpt/idward_segments_example.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - -

Prebid.js Test

-
Div-1
-
- -
-
First Party Data (ortb2) Sent to Bidding Adapter
-
- - diff --git a/integrationExamples/gpt/imRtdProvider_example.html b/integrationExamples/gpt/imRtdProvider_example.html deleted file mode 100644 index b98f053047b..00000000000 --- a/integrationExamples/gpt/imRtdProvider_example.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - -

IM RTD Prebid

- -
- -
- -Intimate Merger Universal Identifier: -
- -Intimate Merger Real-Time Data: -
- - diff --git a/integrationExamples/gpt/permutiveRtdProvider_example.html b/integrationExamples/gpt/permutiveRtdProvider_example.html index dbb4d2af0d6..b6a22096c90 100644 --- a/integrationExamples/gpt/permutiveRtdProvider_example.html +++ b/integrationExamples/gpt/permutiveRtdProvider_example.html @@ -45,12 +45,6 @@ } }, bids: [ - { - bidder: 'ix', - params: { - siteId: '123456', - } - }, { bidder: 'appnexus', params: { @@ -141,7 +135,6 @@ pbjs.que.push(function() { pbjs.setConfig({ debug: true, - pageUrl: 'http://www.test.com/test.html', realTimeData: { auctionDelay: 80, // maximum time for RTD modules to respond dataProviders: [ @@ -149,20 +142,8 @@ name: 'permutive', waitForIt: true, params: { - acBidders: ['appnexus', 'rubicon', 'ozone', 'trustx', 'ix'], + acBidders: ['appnexus', 'rubicon', 'ozone', 'trustx'], maxSegs: 500, - transformations: [ - { - id: 'iab', - config: { - segtax: 4, - iabIds: { - 1000001: '777777', - 1000002: '888888' - } - } - } - ], overwrites: { rubicon: function (bid, data, acEnabled, utils, defaultFn) { if (defaultFn){ @@ -179,7 +160,7 @@ } }); pbjs.setBidderConfig({ - bidders: ['appnexus', 'rubicon', 'ix'], + bidders: ['appnexus', 'rubicon'], config: { ortb2: { site: { @@ -199,9 +180,13 @@ gender: 'm', keywords: 'a,b', data: [ + { + name: 'www.dataprovider1.com', + ext: { taxonomyname: 'iab_audience_taxonomy' }, + segment: [{ id: '687' }, { id: '123' }] + }, { name: 'permutive.com', - ext: { segtax: 6 }, segment: [{ id: '1' }] } ] diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 52578ebcada..dfea06d17d0 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -77,7 +77,6 @@ "301": true, // zeotapIdPlus "91": true, // criteo "737": true, // amxId - "58": true, // 33acrossId } } } @@ -129,17 +128,6 @@ "expires": 30 } }, - { - "name": "33acrossId", - "params": { - "pid": '0' - }, - "storage": { - "type": 'html5', - "name": '33acrossId', - "expires": 90 - } - }, { "name": "intentIqId", "params": { @@ -166,7 +154,6 @@ { "name": "merkleId", "params": { - "endpoint": "https://test_endpoint/", "vendor": "sdfg", "sv_cid": "dfg", "sv_pubid": "xcv", @@ -227,10 +214,10 @@ "name": "zeotapIdPlus" }, { - "name": "hadronId", + "name": "haloId", "storage": { "type": "cookie", - "name": "hadronId", + "name": "haloId", "expires": 28 } }, @@ -264,9 +251,6 @@ "params": { "cid": 5126 // Set your Intimate Merger Customer ID here for production } - }, - { - "name": "dacId" } ], "syncDelay": 5000, diff --git a/integrationExamples/gpt/weboramaRtdProvider_example.html b/integrationExamples/gpt/weboramaRtdProvider_example.html deleted file mode 100644 index b81ec52b2c4..00000000000 --- a/integrationExamples/gpt/weboramaRtdProvider_example.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - -
-

- test webo ctx using prebid.js -

-
-

Basic Prebid.js Example

-
Div-1
-
- -
- - - - \ No newline at end of file diff --git a/integrationExamples/gpt/x-domain/creative.html b/integrationExamples/gpt/x-domain/creative.html index bea8b70b4fe..fce46bb380f 100644 --- a/integrationExamples/gpt/x-domain/creative.html +++ b/integrationExamples/gpt/x-domain/creative.html @@ -2,45 +2,37 @@ // this script can be returned by an ad server delivering a cross domain iframe, into which the // creative will be rendered, e.g. DFP delivering a SafeFrame -const windowLocation = window.location; -const urlParser = document.createElement('a'); +let windowLocation = window.location; +var urlParser = document.createElement('a'); urlParser.href = '%%PATTERN:url%%'; -const publisherDomain = urlParser.protocol + '//' + urlParser.hostname; -const adId = '%%PATTERN:hb_adid%%'; - -function receiveMessage(ev) { - const origin = ev.origin || ev.originalEvent.origin; - if (origin === publisherDomain) { - renderAd(ev); - } -} +var publisherDomain = urlParser.protocol + '//' + urlParser.hostname; function renderAd(ev) { - const key = ev.message ? 'message' : 'data'; - let adObject = {}; - try { - adObject = JSON.parse(ev[key]); - } catch (e) { - return; - } - - if (adObject.message && adObject.message === 'Prebid Response' && - adObject.adId === adId) { + var key = ev.message ? 'message' : 'data'; + var adObject = {}; try { - const body = window.document.body; - const ad = adObject.ad; - const url = adObject.adUrl; - const width = adObject.width; - const height = adObject.height; + adObject = JSON.parse(ev[key]); + } catch (e) { + return; + } + + var origin = ev.origin || ev.originalEvent.origin; + if (adObject.message && adObject.message === 'Prebid Response' && + publisherDomain === origin && + adObject.adId === '%%PATTERN:hb_adid%%' && + (adObject.ad || adObject.adUrl)) { + var body = window.document.body; + var ad = adObject.ad; + var url = adObject.adUrl; + var width = adObject.width; + var height = adObject.height; if (adObject.mediaType === 'video') { - signalRenderResult(false, { - reason: 'preventWritingOnMainDocument', - message: `Cannot render video ad ${adId}` - }); console.log('Error trying to write ad.'); - } else if (ad) { - const frame = document.createElement('iframe'); + } else + + if (ad) { + var frame = document.createElement('iframe'); frame.setAttribute('FRAMEBORDER', 0); frame.setAttribute('SCROLLING', 'no'); frame.setAttribute('MARGINHEIGHT', 0); @@ -54,50 +46,24 @@ frame.contentDocument.open(); frame.contentDocument.write(ad); frame.contentDocument.close(); - signalRenderResult(true); } else if (url) { body.insertAdjacentHTML('beforeend', ''); - signalRenderResult(true); } else { - signalRenderResult(false, { - reason: 'noAd', - message: `No ad for ${adId}` - }); - console.log(`Error trying to write ad. No ad markup or adUrl for ${adId}`); + console.log('Error trying to write ad. No ad for bid response id: ' + id); } - } catch (e) { - signalRenderResult(false, {reason: 'exception', message: e.message}); - console.log(`Error in rendering ad`, e); - } - } - - function signalRenderResult(success, {reason, message} = {}) { - const payload = { - message: 'Prebid Event', - adId, - event: success ? 'adRenderSucceeded' : 'adRenderFailed', } - if (!success) { - payload.info = {reason, message}; - } - window.parent.postMessage(JSON.stringify(payload), publisherDomain); } -} - - function requestAdFromPrebid() { - const message = JSON.stringify({ + var message = JSON.stringify({ message: 'Prebid Request', - adId + adId: '%%PATTERN:hb_adid%%' }); - const channel = new MessageChannel(); - channel.port1.onmessage = renderAd; - window.parent.postMessage(message, publisherDomain, [channel.port2]); + window.parent.postMessage(message, publisherDomain); } function listenAdFromPrebid() { - window.addEventListener('message', receiveMessage, false); + window.addEventListener('message', renderAd, false); } listenAdFromPrebid(); diff --git a/integrationExamples/noadserver/basic_noadserver.html b/integrationExamples/noadserver/basic_noadserver.html deleted file mode 100755 index ebc0e842775..00000000000 --- a/integrationExamples/noadserver/basic_noadserver.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - -

Ad Serverless Test Page

- -
-
-
- - diff --git a/karma.conf.maker.js b/karma.conf.maker.js index b5c6b44e4fd..cf5999ba85e 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -2,7 +2,6 @@ // // For more information, see http://karma-runner.github.io/1.0/config/configuration-file.html -const babelConfig = require('./babelConfig.js'); var _ = require('lodash'); var webpackConf = require('./webpack.conf.js'); var karmaConstants = require('karma').constants; @@ -11,19 +10,10 @@ function newWebpackConfig(codeCoverage) { // Make a clone here because we plan on mutating this object, and don't want parallel tasks to trample each other. var webpackConfig = _.cloneDeep(webpackConf); - Object.assign(webpackConfig, { - mode: 'development', - devtool: 'inline-source-map', - }); + // remove optimize plugin for tests + webpackConfig.plugins.pop() - delete webpackConfig.entry; - - webpackConfig.module.rules - .flatMap((r) => r.use) - .filter((use) => use.loader === 'babel-loader') - .forEach((use) => { - use.options = babelConfig(true); - }); + webpackConfig.devtool = 'inline-source-map'; if (codeCoverage) { webpackConfig.module.rules.push({ @@ -121,7 +111,7 @@ module.exports = function(codeCoverage, browserstack, watchMode, file) { var webpackConfig = newWebpackConfig(codeCoverage); var plugins = newPluginsArray(browserstack); - var files = file ? ['test/test_deps.js', file] : ['test/test_index.js']; + var files = file ? ['test/helpers/prebidGlobal.js', file] : ['test/test_index.js']; // This file opens the /debug.html tab automatically. // It has no real value unless you're running --watch, and intend to do some debugging in the browser. if (watchMode) { @@ -176,7 +166,7 @@ module.exports = function(codeCoverage, browserstack, watchMode, file) { browserNoActivityTimeout: 3e5, // default 10000 captureTimeout: 3e5, // default 60000, browserDisconnectTolerance: 3, - concurrency: 6, + concurrency: 5, plugins: plugins } diff --git a/modules/.submodules.json b/modules/.submodules.json index b0f19aa0bae..1e52b02a358 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -1,48 +1,37 @@ { "userId": [ - "33acrossIdSystem", - "admixerIdSystem", - "adtelligentIdSystem", - "akamaiDAPIdSystem", - "amxIdSystem", - "britepoolIdSystem", - "connectIdSystem", - "criteoIdSystem", - "dacIdSystem", - "deepintentDpesIdSystem", - "dmdIdSystem", - "fabrickIdSystem", - "flocIdSystem", - "hadronIdSystem", - "haloIdSystem", + "unifiedIdSystem", + "pubCommonIdSystem", "id5IdSystem", - "ftrackIdSystem", - "identityLinkIdSystem", - "idxIdSystem", - "imuIdSystem", - "intentIqIdSystem", - "justIdSystem", - "kinessoIdSystem", + "parrableIdSystem", + "britepoolIdSystem", "liveIntentIdSystem", - "lotamePanoramaIdSystem", + "lotamePanoramaId", "merkleIdSystem", - "mwOpenLinkIdSystem", - "naveggIdSystem", + "criteoIdSystem", "netIdSystem", + "identityLinkIdSystem", + "sharedIdSystem", + "intentIqIdSystem", + "zeotapIdPlusIdSystem", + "haloIdSystem", + "quantcastIdSystem", + "deepintentDpesIdSystem", "nextrollIdSystem", - "novatiqIdSystem", - "parrableIdSystem", + "idxIdSystem", + "fabrickIdSystem", + "verizonMediaIdSystem", "pubProvidedIdSystem", - "publinkIdSystem", - "quantcastIdSystem", - "sharedIdSystem", + "mwOpenLinkIdSystem", "tapadIdSystem", - "trustpidSystem", + "novatiqIdSystem", "uid2IdSystem", - "unifiedIdSystem", - "verizonMediaIdSystem", - "zeotapIdPlusIdSystem", - "adqueryIdSystem" + "admixerIdSystem", + "dmdIdSystem", + "akamaiDAPId", + "flocIdSystem", + "amxIdSystem", + "imuIdSystem" ], "adpod": [ "freeWheelAdserverVideo", @@ -52,7 +41,6 @@ "browsiRtdProvider", "dgkeywordRtdProvider", "geoedgeRtdProvider", - "hadronRtdProvider", "haloRtdProvider", "iasRtdProvider", "jwplayerRtdProvider", @@ -60,9 +48,7 @@ "optimeraRtdProvider", "permutiveRtdProvider", "reconciliationRtdProvider", - "sirdataRtdProvider", - "timeoutRtdProvider", - "weboramaRtdProvider" + "sirdataRtdProvider" ], "fpdModule": [ "enrichmentFpdModule", diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 498e6cf8634..4b8028d97fd 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -1,26 +1,13 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; -import { - deepAccess, - uniques, - isArray, - getWindowTop, - isGptPubadsDefined, - isSlotMatchingAdUnitCode, - logInfo, - logWarn, - getWindowSelf, - mergeDeep, -} from '../src/utils.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; - -// **************************** UTILS *************************** // +import * as utils from '../src/utils.js'; +import {BANNER, VIDEO} from '../src/mediaTypes.js'; + const BIDDER_CODE = '33across'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; const SYNC_ENDPOINT = 'https://ssc-cms.33across.com/ps/?m=xch&rt=html&ru=deb'; const CURRENCY = 'USD'; -const GVLID = 58; const GUID_PATTERN = /^[a-zA-Z0-9_-]{22}$/; const PRODUCT = { @@ -52,14 +39,6 @@ const adapterState = { const NON_MEASURABLE = 'nm'; -function getTTXConfig() { - const ttxSettings = Object.assign({}, - config.getConfig('ttxSettings') - ); - - return ttxSettings; -} - // **************************** VALIDATION *************************** // function isBidRequestValid(bid) { return ( @@ -82,7 +61,7 @@ function _validateBasic(bid) { } function _validateGUID(bid) { - const siteID = deepAccess(bid, 'params.siteId', '') || ''; + const siteID = utils.deepAccess(bid, 'params.siteId', '') || ''; if (siteID.trim().match(GUID_PATTERN) === null) { return false; } @@ -91,8 +70,7 @@ function _validateGUID(bid) { } function _validateBanner(bid) { - const banner = deepAccess(bid, 'mediaTypes.banner'); - + const banner = utils.deepAccess(bid, 'mediaTypes.banner'); // If there's no banner no need to validate against banner rules if (banner === undefined) { return true; @@ -106,8 +84,8 @@ function _validateBanner(bid) { } function _validateVideo(bid) { - const videoAdUnit = deepAccess(bid, 'mediaTypes.video'); - const videoBidderParams = deepAccess(bid, 'params.video', {}); + const videoAdUnit = utils.deepAccess(bid, 'mediaTypes.video'); + const videoBidderParams = utils.deepAccess(bid, 'params.video', {}); // If there's no video no need to validate against video rules if (videoAdUnit === undefined) { @@ -159,125 +137,91 @@ function _validateVideo(bid) { // NOTE: With regards to gdrp consent data, the server will independently // infer the gdpr applicability therefore, setting the default value to false function buildRequests(bidRequests, bidderRequest) { - const { - ttxSettings, - gdprConsent, - uspConsent, - pageUrl - } = _buildRequestParams(bidRequests, bidderRequest); - - const groupedRequests = _buildRequestGroups(ttxSettings, bidRequests); - - const serverRequests = []; - - for (const key in groupedRequests) { - serverRequests.push( - _createServerRequest({ - bidRequests: groupedRequests[key], - gdprConsent, - uspConsent, - pageUrl, - ttxSettings - }) - ) - } - - return serverRequests; -} - -function _buildRequestParams(bidRequests, bidderRequest) { - const ttxSettings = getTTXConfig(); - const gdprConsent = Object.assign({ consentString: undefined, gdprApplies: false }, bidderRequest && bidderRequest.gdprConsent); const uspConsent = bidderRequest && bidderRequest.uspConsent; - const pageUrl = (bidderRequest && bidderRequest.refererInfo) ? (bidderRequest.refererInfo.referer) : (undefined); - adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(uniques); - - return { - ttxSettings, - gdprConsent, - uspConsent, - pageUrl - } -} - -function _buildRequestGroups(ttxSettings, bidRequests) { - const bidRequestsComplete = bidRequests.map(_inferProduct); - const enableSRAMode = ttxSettings && ttxSettings.enableSRAMode; - const keyFunc = (enableSRAMode === true) ? _getSRAKey : _getMRAKey; + adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(utils.uniques); - return _groupBidRequests(bidRequestsComplete, keyFunc); -} - -function _groupBidRequests(bidRequests, keyFunc) { - const groupedRequests = {}; - - bidRequests.forEach((req) => { - const key = keyFunc(req); - - groupedRequests[key] = groupedRequests[key] || []; - groupedRequests[key].push(req); - }); - - return groupedRequests; -} - -function _getSRAKey(bidRequest) { - return `${bidRequest.params.siteId}:${bidRequest.params.productId}`; -} - -function _getMRAKey(bidRequest) { - return `${bidRequest.bidId}`; + return bidRequests.map(bidRequest => _createServerRequest( + { + bidRequest, + gdprConsent, + uspConsent, + pageUrl + }) + ); } // Infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request -function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, pageUrl, ttxSettings }) { +// NOTE: At this point, TTX only accepts request for a single impression +function _createServerRequest({bidRequest, gdprConsent = {}, uspConsent, pageUrl}) { const ttxRequest = {}; - const { siteId, test } = bidRequests[0].params; + const params = bidRequest.params; /* * Infer data for the request payload */ - ttxRequest.imp = []; + ttxRequest.imp = [{}]; - bidRequests.forEach((req) => { - ttxRequest.imp.push(_buildImpORTB(req)); - }); + if (utils.deepAccess(bidRequest, 'mediaTypes.banner')) { + ttxRequest.imp[0].banner = { + ..._buildBannerORTB(bidRequest) + } + } + + if (utils.deepAccess(bidRequest, 'mediaTypes.video')) { + ttxRequest.imp[0].video = _buildVideoORTB(bidRequest); + } + + ttxRequest.imp[0].ext = { + ttx: { + prod: _getProduct(bidRequest) + } + }; - ttxRequest.site = { id: siteId }; + ttxRequest.site = { id: params.siteId }; if (pageUrl) { ttxRequest.site.page = pageUrl; } - ttxRequest.id = bidRequests[0].auctionId; + // Go ahead send the bidId in request to 33exchange so it's kept track of in the bid response and + // therefore in ad targetting process + ttxRequest.id = bidRequest.bidId; if (gdprConsent.consentString) { - ttxRequest.user = setExtensions(ttxRequest.user, { - 'consent': gdprConsent.consentString - }); + ttxRequest.user = setExtension( + ttxRequest.user, + 'consent', + gdprConsent.consentString + ) } - if (Array.isArray(bidRequests[0].userIdAsEids) && bidRequests[0].userIdAsEids.length > 0) { - ttxRequest.user = setExtensions(ttxRequest.user, { - 'eids': bidRequests[0].userIdAsEids - }); + if (Array.isArray(bidRequest.userIdAsEids) && bidRequest.userIdAsEids.length > 0) { + ttxRequest.user = setExtension( + ttxRequest.user, + 'eids', + bidRequest.userIdAsEids + ) } - ttxRequest.regs = setExtensions(ttxRequest.regs, { - 'gdpr': Number(gdprConsent.gdprApplies) - }); + ttxRequest.regs = setExtension( + ttxRequest.regs, + 'gdpr', + Number(gdprConsent.gdprApplies) + ); if (uspConsent) { - ttxRequest.regs = setExtensions(ttxRequest.regs, { - 'us_privacy': uspConsent - }); + ttxRequest.regs = setExtension( + ttxRequest.regs, + 'us_privacy', + uspConsent + ) } ttxRequest.ext = { @@ -290,14 +234,16 @@ function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, pageU } }; - if (bidRequests[0].schain) { - ttxRequest.source = setExtensions(ttxRequest.source, { - 'schain': bidRequests[0].schain - }); + if (bidRequest.schain) { + ttxRequest.source = setExtension( + ttxRequest.source, + 'schain', + bidRequest.schain + ) } // Finally, set the openRTB 'test' param if this is to be a test bid - if (test === 1) { + if (params.test === 1) { ttxRequest.test = 1; } @@ -310,7 +256,8 @@ function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, pageU }; // Allow the ability to configure the HB endpoint for testing purposes. - const url = (ttxSettings && ttxSettings.url) || `${END_POINT}?guid=${siteId}`; + const ttxSettings = config.getConfig('ttxSettings'); + const url = (ttxSettings && ttxSettings.url) || `${END_POINT}?guid=${params.siteId}`; // Return the server request return { @@ -322,39 +269,17 @@ function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, pageU } // BUILD REQUESTS: SET EXTENSIONS -function setExtensions(obj = {}, extFields) { - return mergeDeep({}, obj, { - 'ext': extFields +function setExtension(obj = {}, key, value) { + return Object.assign({}, obj, { + ext: Object.assign({}, obj.ext, { + [key]: value + }) }); } -// BUILD REQUESTS: IMP -function _buildImpORTB(bidRequest) { - const imp = { - id: bidRequest.bidId, - ext: { - ttx: { - prod: deepAccess(bidRequest, 'params.productId') - } - } - }; - - if (deepAccess(bidRequest, 'mediaTypes.banner')) { - imp.banner = { - ..._buildBannerORTB(bidRequest) - } - } - - if (deepAccess(bidRequest, 'mediaTypes.video')) { - imp.video = _buildVideoORTB(bidRequest); - } - - return imp; -} - // BUILD REQUESTS: SIZE INFERENCE function _transformSizes(sizes) { - if (isArray(sizes) && sizes.length === 2 && !isArray(sizes[0])) { + if (utils.isArray(sizes) && sizes.length === 2 && !utils.isArray(sizes[0])) { return [ _getSize(sizes) ]; } @@ -369,14 +294,6 @@ function _getSize(size) { } // BUILD REQUESTS: PRODUCT INFERENCE -function _inferProduct(bidRequest) { - return mergeDeep({}, bidRequest, { - params: { - productId: _getProduct(bidRequest) - } - }); -} - function _getProduct(bidRequest) { const { params, mediaTypes } = bidRequest; @@ -391,7 +308,7 @@ function _getProduct(bidRequest) { // BUILD REQUESTS: BANNER function _buildBannerORTB(bidRequest) { - const bannerAdUnit = deepAccess(bidRequest, 'mediaTypes.banner', {}); + const bannerAdUnit = utils.deepAccess(bidRequest, 'mediaTypes.banner', {}); const element = _getAdSlotHTMLElement(bidRequest.adUnitCode); const sizes = _transformSizes(bannerAdUnit.sizes); @@ -423,7 +340,7 @@ function _buildBannerORTB(bidRequest) { const minSize = _getMinSize(sizes); const viewabilityAmount = _isViewabilityMeasurable(element) - ? _getViewability(element, getWindowTop(), minSize) + ? _getViewability(element, utils.getWindowTop(), minSize) : NON_MEASURABLE; const ext = contributeViewability(viewabilityAmount); @@ -437,8 +354,8 @@ function _buildBannerORTB(bidRequest) { // BUILD REQUESTS: VIDEO // eslint-disable-next-line no-unused-vars function _buildVideoORTB(bidRequest) { - const videoAdUnit = deepAccess(bidRequest, 'mediaTypes.video', {}); - const videoBidderParams = deepAccess(bidRequest, 'params.video', {}); + const videoAdUnit = utils.deepAccess(bidRequest, 'mediaTypes.video', {}); + const videoBidderParams = utils.deepAccess(bidRequest, 'params.video', {}); const videoParams = { ...videoAdUnit, @@ -447,7 +364,7 @@ function _buildVideoORTB(bidRequest) { const video = {} - const { w, h } = _getSize(videoParams.playerSize[0]); + const {w, h} = _getSize(videoParams.playerSize[0]); video.w = w; video.h = h; @@ -468,11 +385,11 @@ function _buildVideoORTB(bidRequest) { if (product === PRODUCT.INSTREAM) { video.startdelay = video.startdelay || 0; video.placement = 1; - } + }; // bidfloors if (typeof bidRequest.getFloor === 'function') { - const bidfloors = _getBidFloors(bidRequest, { w: video.w, h: video.h }, VIDEO); + const bidfloors = _getBidFloors(bidRequest, {w: video.w, h: video.h}, VIDEO); if (bidfloors) { Object.assign(video, { @@ -484,7 +401,6 @@ function _buildVideoORTB(bidRequest) { }); } } - return video; } @@ -513,23 +429,23 @@ function _getViewability(element, topWin, { w, h } = {}) { } function _mapAdUnitPathToElementId(adUnitCode) { - if (isGptPubadsDefined()) { + if (utils.isGptPubadsDefined()) { // eslint-disable-next-line no-undef const adSlots = googletag.pubads().getSlots(); - const isMatchingAdSlot = isSlotMatchingAdUnitCode(adUnitCode); + const isMatchingAdSlot = utils.isSlotMatchingAdUnitCode(adUnitCode); for (let i = 0; i < adSlots.length; i++) { if (isMatchingAdSlot(adSlots[i])) { const id = adSlots[i].getSlotElementId(); - logInfo(`[33Across Adapter] Map ad unit path to HTML element id: '${adUnitCode}' -> ${id}`); + utils.logInfo(`[33Across Adapter] Map ad unit path to HTML element id: '${adUnitCode}' -> ${id}`); return id; } } } - logWarn(`[33Across Adapter] Unable to locate element for ad unit code: '${adUnitCode}'`); + utils.logWarn(`[33Across Adapter] Unable to locate element for ad unit code: '${adUnitCode}'`); return null; } @@ -630,68 +546,61 @@ function contributeViewability(viewabilityAmount) { function _isIframe() { try { - return getWindowSelf() !== getWindowTop(); + return utils.getWindowSelf() !== utils.getWindowTop(); } catch (e) { return true; } } // **************************** INTERPRET RESPONSE ******************************** // +// NOTE: At this point, the response from 33exchange will only ever contain one bid +// i.e. the highest bid function interpretResponse(serverResponse, bidRequest) { - const { seatbid, cur = 'USD' } = serverResponse.body; - - if (!isArray(seatbid)) { - return []; - } - - // Pick seats with valid bids and convert them into an Array of responses - // in format expected by Prebid Core - return seatbid - .filter((seat) => ( - isArray(seat.bid) && - seat.bid.length > 0 - )) - .reduce((acc, seat) => { - return acc.concat( - seat.bid.map((bid) => _createBidResponse(bid, cur)) - ); - }, []); + const bidResponses = []; + + // If there are bids, look at the first bid of the first seatbid (see NOTE above for assumption about ttx) + if (serverResponse.body.seatbid.length > 0 && serverResponse.body.seatbid[0].bid.length > 0) { + bidResponses.push(_createBidResponse(serverResponse.body)); + } + + return bidResponses; } -function _createBidResponse(bid, cur) { +// All this assumes that only one bid is ever returned by ttx +function _createBidResponse(response) { const isADomainPresent = - bid.adomain && bid.adomain.length; - const bidResponse = { - requestId: bid.impid, + response.seatbid[0].bid[0].adomain && response.seatbid[0].bid[0].adomain.length; + const bid = { + requestId: response.id, bidderCode: BIDDER_CODE, - cpm: bid.price, - width: bid.w, - height: bid.h, - ad: bid.adm, - ttl: bid.ttl || 60, - creativeId: bid.crid, - mediaType: deepAccess(bid, 'ext.ttx.mediaType', BANNER), - currency: cur, + cpm: response.seatbid[0].bid[0].price, + width: response.seatbid[0].bid[0].w, + height: response.seatbid[0].bid[0].h, + ad: response.seatbid[0].bid[0].adm, + ttl: response.seatbid[0].bid[0].ttl || 60, + creativeId: response.seatbid[0].bid[0].crid, + mediaType: utils.deepAccess(response.seatbid[0].bid[0], 'ext.ttx.mediaType', BANNER), + currency: response.cur, netRevenue: true } if (isADomainPresent) { - bidResponse.meta = { - advertiserDomains: bid.adomain + bid.meta = { + advertiserDomains: response.seatbid[0].bid[0].adomain }; } - if (bidResponse.mediaType === VIDEO) { - const vastType = deepAccess(bid, 'ext.ttx.vastType', 'xml'); + if (bid.mediaType === VIDEO) { + const vastType = utils.deepAccess(response.seatbid[0].bid[0], 'ext.ttx.vastType', 'xml'); if (vastType === 'xml') { - bidResponse.vastXml = bidResponse.ad; + bid.vastXml = bid.ad; } else { - bidResponse.vastUrl = bidResponse.ad; + bid.vastUrl = bid.ad; } } - return bidResponse; + return bid; } // **************************** USER SYNC *************************** // @@ -736,7 +645,6 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: [ BANNER, VIDEO ], - gvlid: GVLID, isBidRequestValid, buildRequests, interpretResponse, diff --git a/modules/33acrossIdSystem.js b/modules/33acrossIdSystem.js deleted file mode 100644 index 3763fee5124..00000000000 --- a/modules/33acrossIdSystem.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * This module adds 33acrossId to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/33acrossIdSystem - * @requires module:modules/userId - */ - -import { logMessage, logError } from '../src/utils.js'; -import { ajaxBuilder } from '../src/ajax.js'; -import { submodule } from '../src/hook.js'; -import { uspDataHandler } from '../src/adapterManager.js'; - -const MODULE_NAME = '33acrossId'; -const API_URL = 'https://lexicon.33across.com/v1/envelope'; -const AJAX_TIMEOUT = 10000; - -function getEnvelope(response) { - if (!response.succeeded) { - logError(`${MODULE_NAME}: Unsuccessful response`); - - return; - } - - if (!response.data.envelope) { - logMessage(`${MODULE_NAME}: No envelope was received`); - - return; - } - - return response.data.envelope; -} - -function calculateQueryStringParams(pid, gdprConsentData) { - const uspString = uspDataHandler.getConsentData(); - const gdprApplies = Boolean(gdprConsentData?.gdprApplies); - const params = { - pid, - gdpr: Number(gdprApplies), - }; - - if (uspString) { - params.us_privacy = uspString; - } - - if (gdprApplies) { - params.gdpr_consent = gdprConsentData.consentString || ''; - } - - return params; -} - -/** @type {Submodule} */ -export const thirthyThreeAcrossIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - - gvlid: 58, - - /** - * decode the stored id value for passing to bid requests - * @function - * @param {string} id - * @returns {{'33acrossId':{ envelope: string}}} - */ - decode(id) { - return { - [MODULE_NAME]: { - envelope: id - } - }; - }, - - /** - * performs action to obtain id and return a value in the callback's response argument - * @function - * @param {SubmoduleConfig} [config] - * @returns {IdResponse|undefined} - */ - getId({ params = { } }, gdprConsentData) { - if (typeof params.pid !== 'string') { - logError(`${MODULE_NAME}: Submodule requires a partner ID to be defined`); - - return; - } - - const { pid, apiUrl = API_URL } = params; - - return { - callback(cb) { - ajaxBuilder(AJAX_TIMEOUT)(apiUrl, { - success(response) { - let envelope; - - try { - envelope = getEnvelope(JSON.parse(response)) - } catch (err) { - logError(`${MODULE_NAME}: ID reading error:`, err); - } - cb(envelope); - }, - error(err) { - logError(`${MODULE_NAME}: ID error response`, err); - - cb(); - } - }, calculateQueryStringParams(pid, gdprConsentData), { method: 'GET', withCredentials: true }); - } - }; - } -}; - -submodule('userId', thirthyThreeAcrossIdSubmodule); diff --git a/modules/33acrossIdSystem.md b/modules/33acrossIdSystem.md deleted file mode 100644 index 1e4af89344f..00000000000 --- a/modules/33acrossIdSystem.md +++ /dev/null @@ -1,53 +0,0 @@ -# 33ACROSS ID - -For help adding this submodule, please contact [PrebidUIM@33across.com](PrebidUIM@33across.com). - -### Prebid Configuration - -You can configure this submodule in your `userSync.userIds[]` configuration: - -```javascript -pbjs.setConfig({ - userSync: { - userIds: [ - { - name: "33acrossId", - storage: { - name: "33acrossId", - type: "html5", - expires: 90, - refreshInSeconds: 8*3600 - }, - params: { - pid: "0010b00002GYU4eBAH", - }, - }, - ], - }, -}); -``` - -| Parameters under `userSync.userIds[]` | Scope | Type | Description | Example | -| ---| --- | --- | --- | --- | -| name | Required | String | Name for the 33Across ID submodule | `"33acrossId"` | | -| storage | Required | Object | Configures how to cache User IDs locally in the browser | See [storage settings](#storage-settings) | -| params | Required | Object | Parameters for 33Across ID submodule | See [params](#params) | - -### Storage Settings - -The following settings are available for the `storage` property in the `userSync.userIds[]` object: - -| Param name | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String| Name of the cookie or HTML5 local storage where the user ID will be stored | `"33acrossId"` | -| type | Required | String | `"html5"` (preferred) or `"cookie"` | `"html5"` | -| expires | Strongly Recommended | Number | How long (in days) the user ID information will be stored. 33Across recommends `90`. | `90` | -| refreshInSeconds | Strongly Recommended | Number | The interval (in seconds) for refreshing the user ID. 33Across recommends no more than 8 hours between refreshes. | `8*3600` | - -### Params - -The following settings are available in the `params` property in `userSync.userIds[]` object: - -| Param name | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| pid | Required | String | Partner ID provided by 33Across | `"0010b00002GYU4eBAH"` | diff --git a/modules/a4gBidAdapter.js b/modules/a4gBidAdapter.js index 03f9d6fd726..01c59616dc0 100644 --- a/modules/a4gBidAdapter.js +++ b/modules/a4gBidAdapter.js @@ -1,5 +1,5 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; -import { _each } from '../src/utils.js'; +import * as utils from '../src/utils.js'; const A4G_BIDDER_CODE = 'a4g'; const A4G_CURRENCY = 'USD'; @@ -28,7 +28,7 @@ export const spec = { const sizeParams = []; const zoneIds = []; - _each(validBidRequests, function(bid) { + utils._each(validBidRequests, function(bid) { if (!deliveryUrl && typeof bid.params.deliveryUrl === 'string') { deliveryUrl = bid.params.deliveryUrl; } @@ -66,7 +66,7 @@ export const spec = { interpretResponse: function(serverResponses, request) { const bidResponses = []; - _each(serverResponses.body, function(response) { + utils._each(serverResponses.body, function(response) { if (response.cpm > 0) { const bidResponse = { requestId: response.id, diff --git a/modules/ablidaBidAdapter.js b/modules/ablidaBidAdapter.js index cb4f4ef2724..2400952367f 100644 --- a/modules/ablidaBidAdapter.js +++ b/modules/ablidaBidAdapter.js @@ -1,4 +1,4 @@ -import { triggerPixel } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; @@ -79,7 +79,7 @@ export const spec = { }, onBidWon: function (bid) { if (!bid['nurl']) { return; } - triggerPixel(bid['nurl']); + utils.triggerPixel(bid['nurl']); } }; diff --git a/modules/adWMGBidAdapter.js b/modules/adWMGBidAdapter.js index 7bf6c703a55..a3d78a69d91 100644 --- a/modules/adWMGBidAdapter.js +++ b/modules/adWMGBidAdapter.js @@ -1,6 +1,6 @@ 'use strict'; -import { tryAppendQueryString } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER } from '../src/mediaTypes.js'; @@ -128,11 +128,11 @@ export const spec = { }, getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { if (gdprConsent && SYNC_ENDPOINT.indexOf('gdpr') === -1) { - SYNC_ENDPOINT = tryAppendQueryString(SYNC_ENDPOINT, 'gdpr', (gdprConsent.gdprApplies ? 1 : 0)); + SYNC_ENDPOINT = utils.tryAppendQueryString(SYNC_ENDPOINT, 'gdpr', (gdprConsent.gdprApplies ? 1 : 0)); } if (gdprConsent && typeof gdprConsent.consentString === 'string' && SYNC_ENDPOINT.indexOf('gdpr_consent') === -1) { - SYNC_ENDPOINT = tryAppendQueryString(SYNC_ENDPOINT, 'gdpr_consent', gdprConsent.consentString); + SYNC_ENDPOINT = utils.tryAppendQueryString(SYNC_ENDPOINT, 'gdpr_consent', gdprConsent.consentString); } if (SYNC_ENDPOINT.slice(-1) === '&') { @@ -140,7 +140,7 @@ export const spec = { } /* if (uspConsent) { - SYNC_ENDPOINT = tryAppendQueryString(SYNC_ENDPOINT, 'us_privacy', uspConsent); + SYNC_ENDPOINT = utils.tryAppendQueryString(SYNC_ENDPOINT, 'us_privacy', uspConsent); } */ let syncs = []; if (syncOptions.iframeEnabled) { diff --git a/modules/adagioAnalyticsAdapter.js b/modules/adagioAnalyticsAdapter.js index f929f7e660b..fd7a742d9e7 100644 --- a/modules/adagioAnalyticsAdapter.js +++ b/modules/adagioAnalyticsAdapter.js @@ -5,7 +5,7 @@ import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; -import { getWindowTop } from '../src/utils.js'; +import * as utils from '../src/utils.js'; const emptyUrl = ''; const analyticsType = 'endpoint'; @@ -13,12 +13,12 @@ const events = Object.keys(CONSTANTS.EVENTS).map(key => CONSTANTS.EVENTS[key]); const VERSION = '2.0.0'; const adagioEnqueue = function adagioEnqueue(action, data) { - getWindowTop().ADAGIO.queue.push({ action, data, ts: Date.now() }); + utils.getWindowTop().ADAGIO.queue.push({ action, data, ts: Date.now() }); } function canAccessTopWindow() { try { - if (getWindowTop().location.href) { + if (utils.getWindowTop().location.href) { return true; } } catch (error) { @@ -41,7 +41,7 @@ adagioAdapter.enableAnalytics = config => { return; } - const w = getWindowTop(); + const w = utils.getWindowTop(); w.ADAGIO = w.ADAGIO || {}; w.ADAGIO.queue = w.ADAGIO.queue || []; diff --git a/modules/adagioBidAdapter.js b/modules/adagioBidAdapter.js index f3060c5598b..ffa955290be 100644 --- a/modules/adagioBidAdapter.js +++ b/modules/adagioBidAdapter.js @@ -1,38 +1,15 @@ -import {find} from '../src/polyfill.js'; -import { - _map, - cleanObj, - deepAccess, - deepClone, - generateUUID, - getDNT, - getGptSlotInfoForAdUnitCode, - getUniqueIdentifierStr, - getWindowSelf, - getWindowTop, - inIframe, - isArray, - isFn, - isInteger, - isNumber, - logError, - logInfo, - logWarn, - mergeDeep, - parseUrl -} from '../src/utils.js'; -import {config} from '../src/config.js'; +import find from 'core-js-pure/features/array/find.js'; +import * as utils from '../src/utils.js'; +import { config } from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {loadExternalScript} from '../src/adloader.js'; -import {verify} from 'criteo-direct-rsa-validate/build/verify.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import {createEidsArray} from './userId/eids.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {Renderer} from '../src/Renderer.js'; -import {OUTSTREAM} from '../src/video.js'; -import { getGlobal } from '../src/prebidGlobal.js'; - +import { loadExternalScript } from '../src/adloader.js'; +import { verify } from 'criteo-direct-rsa-validate/build/verify.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { getRefererInfo } from '../src/refererDetection.js'; +import { createEidsArray } from './userId/eids.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { Renderer } from '../src/Renderer.js'; +import { OUTSTREAM } from '../src/video.js'; const BIDDER_CODE = 'adagio'; const LOG_PREFIX = 'Adagio:'; const FEATURES_VERSION = '1'; @@ -41,34 +18,35 @@ const SUPPORTED_MEDIA_TYPES = [BANNER, NATIVE, VIDEO]; const ADAGIO_TAG_URL = 'https://script.4dex.io/localstore.js'; const ADAGIO_LOCALSTORAGE_KEY = 'adagioScript'; const GVLID = 617; -export const storage = getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE}); +export const storage = getStorageManager(GVLID, 'adagio'); export const RENDERER_URL = 'https://script.4dex.io/outstream-player.js'; const MAX_SESS_DURATION = 30 * 60 * 1000; const ADAGIO_PUBKEY = 'AL16XT44Sfp+8SHVF1UdC7hydPSMVLMhsYknKDdwqq+0ToDSJrP0+Qh0ki9JJI2uYm/6VEYo8TJED9WfMkiJ4vf02CW3RvSWwc35bif2SK1L8Nn/GfFYr/2/GG/Rm0vUsv+vBHky6nuuYls20Og0HDhMgaOlXoQ/cxMuiy5QSktp'; const ADAGIO_PUBKEY_E = 65537; const CURRENCY = 'USD'; +const DEFAULT_FLOOR = 0.1; // This provide a whitelist and a basic validation // of OpenRTB 2.5 options used by the Adagio SSP. // https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf export const ORTB_VIDEO_PARAMS = { 'mimes': (value) => Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string'), - 'minduration': (value) => isInteger(value), - 'maxduration': (value) => isInteger(value), + 'minduration': (value) => utils.isInteger(value), + 'maxduration': (value) => utils.isInteger(value), 'protocols': (value) => Array.isArray(value) && value.every(v => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].indexOf(v) !== -1), - 'w': (value) => isInteger(value), - 'h': (value) => isInteger(value), - 'startdelay': (value) => isInteger(value), + 'w': (value) => utils.isInteger(value), + 'h': (value) => utils.isInteger(value), + 'startdelay': (value) => utils.isInteger(value), 'placement': (value) => Array.isArray(value) && value.every(v => [1, 2, 3, 4, 5].indexOf(v) !== -1), 'linearity': (value) => [1, 2].indexOf(value) !== -1, 'skip': (value) => [0, 1].indexOf(value) !== -1, - 'skipmin': (value) => isInteger(value), - 'skipafter': (value) => isInteger(value), - 'sequence': (value) => isInteger(value), + 'skipmin': (value) => utils.isInteger(value), + 'skipafter': (value) => utils.isInteger(value), + 'sequence': (value) => utils.isInteger(value), 'battr': (value) => Array.isArray(value) && value.every(v => Array.from({length: 17}, (_, i) => i + 1).indexOf(v) !== -1), - 'maxextended': (value) => isInteger(value), - 'minbitrate': (value) => isInteger(value), - 'maxbitrate': (value) => isInteger(value), + 'maxextended': (value) => utils.isInteger(value), + 'minbitrate': (value) => utils.isInteger(value), + 'maxbitrate': (value) => utils.isInteger(value), 'boxingallowed': (value) => [0, 1].indexOf(value) !== -1, 'playbackmethod': (value) => Array.isArray(value) && value.every(v => [1, 2, 3, 4, 5, 6].indexOf(v) !== -1), 'playbackend': (value) => [1, 2, 3].indexOf(value) !== -1, @@ -110,7 +88,7 @@ export const GlobalExchange = (function() { return value; } }); - let random = deepAccess(adagioStorage, 'session.rnd'); + let random = utils.deepAccess(adagioStorage, 'session.rnd'); let newSession = false; if (internal.isNewSession(adagioStorage)) { @@ -125,7 +103,7 @@ export const GlobalExchange = (function() { } } - mergeDeep(exchangeData, adagioStorage, data); + utils.mergeDeep(exchangeData, adagioStorage, data); internal.enqueue({ action: 'session', @@ -143,14 +121,14 @@ export const GlobalExchange = (function() { export function adagioScriptFromLocalStorageCb(ls) { try { if (!ls) { - logWarn(`${LOG_PREFIX} script not found.`); + utils.logWarn(`${LOG_PREFIX} script not found.`); return; } const hashRgx = /^(\/\/ hash: (.+)\n)(.+\n)$/; if (!hashRgx.test(ls)) { - logWarn(`${LOG_PREFIX} no hash found.`); + utils.logWarn(`${LOG_PREFIX} no hash found.`); storage.removeDataFromLocalStorage(ADAGIO_LOCALSTORAGE_KEY); } else { const r = ls.match(hashRgx); @@ -158,15 +136,15 @@ export function adagioScriptFromLocalStorageCb(ls) { const content = r[3]; if (verify(content, hash, ADAGIO_PUBKEY, ADAGIO_PUBKEY_E)) { - logInfo(`${LOG_PREFIX} start script.`); + utils.logInfo(`${LOG_PREFIX} start script.`); Function(ls)(); // eslint-disable-line no-new-func } else { - logWarn(`${LOG_PREFIX} invalid script found.`); + utils.logWarn(`${LOG_PREFIX} invalid script found.`); storage.removeDataFromLocalStorage(ADAGIO_LOCALSTORAGE_KEY); } } } catch (err) { - logError(LOG_PREFIX, err); + utils.logError(LOG_PREFIX, err); } } @@ -189,7 +167,7 @@ export function getAdagioScript() { // This key is removed only if localStorage is not accessible. window.localStorage.removeItem('adagio'); } catch (e) { - logInfo(`${LOG_PREFIX} unable to clear Adagio scripts from localstorage.`); + utils.logInfo(`${LOG_PREFIX} unable to clear Adagio scripts from localstorage.`); } } }); @@ -197,7 +175,7 @@ export function getAdagioScript() { function canAccessTopWindow() { try { - if (getWindowTop().location.href) { + if (utils.getWindowTop().location.href) { return true; } } catch (error) { @@ -206,17 +184,17 @@ function canAccessTopWindow() { } function getCurrentWindow() { - return currentWindow || getWindowSelf(); + return currentWindow || utils.getWindowSelf(); } function isSafeFrameWindow() { - const ws = getWindowSelf(); + const ws = utils.getWindowSelf(); return !!(ws.$sf && ws.$sf.ext); } function initAdagio() { if (canAccessTopWindow()) { - currentWindow = (canAccessTopWindow()) ? getWindowTop() : getWindowSelf(); + currentWindow = (canAccessTopWindow()) ? utils.getWindowTop() : utils.getWindowSelf(); } const w = internal.getCurrentWindow(); @@ -233,7 +211,7 @@ function initAdagio() { try { GlobalExchange.prepareExchangeData(storageData); } catch (e) { - logError(LOG_PREFIX, e); + utils.logError(LOG_PREFIX, e); } }); @@ -252,7 +230,7 @@ function getPageviewId() { const w = internal.getCurrentWindow(); w.ADAGIO = w.ADAGIO || {}; - w.ADAGIO.pageviewId = w.ADAGIO.pageviewId || generateUUID(); + w.ADAGIO.pageviewId = w.ADAGIO.pageviewId || utils.generateUUID(); return w.ADAGIO.pageviewId; }; @@ -262,7 +240,7 @@ function getDevice() { return { userAgent: navigator.userAgent, language: navigator[language], - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, geo: {}, js: 1 }; @@ -276,18 +254,20 @@ function getSite(bidderRequest) { const { refererInfo } = bidderRequest; if (canAccessTopWindow()) { - const wt = getWindowTop(); + const wt = utils.getWindowTop(); domain = wt.location.hostname; page = wt.location.href; referrer = wt.document.referrer || ''; } else if (refererInfo.reachedTop) { - const url = parseUrl(refererInfo.referer); + const url = utils.parseUrl(refererInfo.referer); domain = url.hostname; page = refererInfo.referer; } else if (refererInfo.stack && refererInfo.stack.length && refererInfo.stack[0]) { // important note check if refererInfo.stack[0] is 'thruly' because a `null` value // will be considered as "localhost" by the parseUrl function. - const url = parseUrl(refererInfo.stack[0]); + // As the isBidRequestValid returns false when it does not reach the referer + // this should never called. + const url = utils.parseUrl(refererInfo.stack[0]); domain = url.hostname; } @@ -300,9 +280,9 @@ function getSite(bidderRequest) { function getElementFromTopWindow(element, currentWindow) { try { - if (getWindowTop() === currentWindow) { + if (utils.getWindowTop() === currentWindow) { if (!element.getAttribute('id')) { - element.setAttribute('id', `adg-${getUniqueIdentifierStr()}`); + element.setAttribute('id', `adg-${utils.getUniqueIdentifierStr()}`); } return element; } else { @@ -317,26 +297,26 @@ function getElementFromTopWindow(element, currentWindow) { return getElementFromTopWindow(frame, currentWindow.parent); } } catch (err) { - logWarn(`${LOG_PREFIX}`, err); + utils.logWarn(`${LOG_PREFIX}`, err); return false; } }; function autoDetectAdUnitElementIdFromGpt(adUnitCode) { - const autoDetectedAdUnit = getGptSlotInfoForAdUnitCode(adUnitCode); + const autoDetectedAdUnit = utils.getGptSlotInfoForAdUnitCode(adUnitCode); - if (autoDetectedAdUnit.divId) { + if (autoDetectedAdUnit && autoDetectedAdUnit.divId) { return autoDetectedAdUnit.divId; } }; function isRendererPreferredFromPublisher(bidRequest) { // renderer defined at adUnit level - const adUnitRenderer = deepAccess(bidRequest, 'renderer'); + const adUnitRenderer = utils.deepAccess(bidRequest, 'renderer'); const hasValidAdUnitRenderer = !!(adUnitRenderer && adUnitRenderer.url && adUnitRenderer.render); // renderer defined at adUnit.mediaTypes level - const mediaTypeRenderer = deepAccess(bidRequest, 'mediaTypes.video.renderer'); + const mediaTypeRenderer = utils.deepAccess(bidRequest, 'mediaTypes.video.renderer'); const hasValidMediaTypeRenderer = !!(mediaTypeRenderer && mediaTypeRenderer.url && mediaTypeRenderer.render); return !!( @@ -352,10 +332,10 @@ function isRendererPreferredFromPublisher(bidRequest) { */ function isNewSession(adagioStorage) { const now = Date.now(); - const { lastActivityTime, vwSmplg } = deepAccess(adagioStorage, 'session', {}); + const { lastActivityTime, vwSmplg } = utils.deepAccess(adagioStorage, 'session', {}); return ( - !isNumber(lastActivityTime) || - !isNumber(vwSmplg) || + !utils.isNumber(lastActivityTime) || + !utils.isNumber(vwSmplg) || (now - lastActivityTime) > MAX_SESS_DURATION ) } @@ -364,7 +344,7 @@ function setPlayerName(bidRequest) { const playerName = (internal.isRendererPreferredFromPublisher(bidRequest)) ? 'other' : 'adagio'; if (playerName === 'other') { - logWarn(`${LOG_PREFIX} renderer.backupOnly has not been set. Adagio recommends to use its own player to get expected behavior.`); + utils.logWarn(`${LOG_PREFIX} renderer.backupOnly has not been set. Adagio recommends to use its own player to get expected behavior.`); } return playerName; @@ -385,7 +365,7 @@ export const internal = { }; function _getGdprConsent(bidderRequest) { - if (!deepAccess(bidderRequest, 'gdprConsent')) { + if (!utils.deepAccess(bidderRequest, 'gdprConsent')) { return false; } @@ -396,7 +376,7 @@ function _getGdprConsent(bidderRequest) { allowAuctionWithoutConsent } = bidderRequest.gdprConsent; - return cleanObj({ + return utils.cleanObj({ apiVersion, consentString, consentRequired: gdprApplies ? 1 : 0, @@ -411,22 +391,22 @@ function _getCoppa() { } function _getUspConsent(bidderRequest) { - return (deepAccess(bidderRequest, 'uspConsent')) ? { uspConsent: bidderRequest.uspConsent } : false; + return (utils.deepAccess(bidderRequest, 'uspConsent')) ? { uspConsent: bidderRequest.uspConsent } : false; } function _getSchain(bidRequest) { - return deepAccess(bidRequest, 'schain'); + return utils.deepAccess(bidRequest, 'schain'); } function _getEids(bidRequest) { - if (deepAccess(bidRequest, 'userId')) { + if (utils.deepAccess(bidRequest, 'userId')) { return createEidsArray(bidRequest.userId); } } function _buildVideoBidRequest(bidRequest) { - const videoAdUnitParams = deepAccess(bidRequest, 'mediaTypes.video', {}); - const videoBidderParams = deepAccess(bidRequest, 'params.video', {}); + const videoAdUnitParams = utils.deepAccess(bidRequest, 'mediaTypes.video', {}); + const videoBidderParams = utils.deepAccess(bidRequest, 'params.video', {}); const computedParams = {}; // Special case for playerSize. @@ -456,7 +436,7 @@ function _buildVideoBidRequest(bidRequest) { bidRequest.mediaTypes.video[paramName] = videoParams[paramName]; } else { delete bidRequest.mediaTypes.video[paramName]; - logWarn(`${LOG_PREFIX} The OpenRTB video param ${paramName} has been skipped due to misformating. Please refer to OpenRTB 2.5 spec.`); + utils.logWarn(`${LOG_PREFIX} The OpenRTB video param ${paramName} has been skipped due to misformating. Please refer to OpenRTB 2.5 spec.`); } } }); @@ -467,14 +447,14 @@ function _renderer(bid) { if (typeof window.ADAGIO.outstreamPlayer === 'function') { window.ADAGIO.outstreamPlayer(bid); } else { - logError(`${LOG_PREFIX} Adagio outstream player is not defined`); + utils.logError(`${LOG_PREFIX} Adagio outstream player is not defined`); } }); } function _parseNativeBidResponse(bid) { if (!bid.admNative || !Array.isArray(bid.admNative.assets)) { - logError(`${LOG_PREFIX} Invalid native response`); + utils.logError(`${LOG_PREFIX} Invalid native response`); return; } @@ -579,7 +559,7 @@ function _parseNativeBidResponse(bid) { } function _getFloors(bidRequest) { - if (!isFn(bidRequest.getFloor)) { + if (!utils.isFn(bidRequest.getFloor)) { return false; } @@ -589,13 +569,13 @@ function _getFloors(bidRequest) { const info = bidRequest.getFloor({ currency: CURRENCY, mediaType, - size + size: [] }); - floors.push(cleanObj({ + floors.push(utils.cleanObj({ mt: mediaType, - s: isArray(size) ? `${size[0]}x${size[1]}` : undefined, - f: (!isNaN(info.floor) && info.currency === CURRENCY) ? info.floor : undefined + s: utils.isArray(size) ? `${size[0]}x${size[1]}` : undefined, + f: (!isNaN(info.floor) && info.currency === CURRENCY) ? info.floor : DEFAULT_FLOOR })); } @@ -604,7 +584,7 @@ function _getFloors(bidRequest) { const sizeProp = mediaType === VIDEO ? 'playerSize' : 'sizes'; if (bidRequest.mediaTypes[mediaType][sizeProp] && bidRequest.mediaTypes[mediaType][sizeProp].length) { - if (isArray(bidRequest.mediaTypes[mediaType][sizeProp][0])) { + if (utils.isArray(bidRequest.mediaTypes[mediaType][sizeProp][0])) { bidRequest.mediaTypes[mediaType][sizeProp].forEach(size => { getAndPush(mediaType, [size[0], size[1]]); }); @@ -641,7 +621,7 @@ export function setExtraParam(bid, paramName) { const adgGlobalConf = config.getConfig('adagio') || {}; const ortb2Conf = config.getConfig('ortb2'); - const detected = adgGlobalConf[paramName] || deepAccess(ortb2Conf, `site.ext.data.${paramName}`, null); + const detected = adgGlobalConf[paramName] || utils.deepAccess(ortb2Conf, `site.ext.data.${paramName}`, null); if (detected) { bid.params[paramName] = detected; } @@ -664,7 +644,7 @@ function autoFillParams(bid) { bid.params.placement = bid.adUnitCode; } - bid.params.adUnitElementId = deepAccess(bid, 'ortb2Imp.ext.data.elementId', null) || bid.params.adUnitElementId; + bid.params.adUnitElementId = utils.deepAccess(bid, 'ortb2Imp.ext.data.elementId', null) || bid.params.adUnitElementId; if (!bid.params.adUnitElementId) { if (adgGlobalConf.useAdUnitCodeAsAdUnitElementId === true || bid.params.useAdUnitCodeAsAdUnitElementId === true) { @@ -687,7 +667,7 @@ function getPageDimensions() { } // the page dimension can be computed on window.top only. - const wt = getWindowTop(); + const wt = utils.getWindowTop(); const body = wt.document.querySelector('body'); if (!body) { @@ -712,17 +692,17 @@ function getViewPortDimensions() { const viewportDims = { w: 0, h: 0 }; if (isSafeFrameWindow()) { - const ws = getWindowSelf(); + const ws = utils.getWindowSelf(); if (typeof ws.$sf.ext.geom !== 'function') { - logWarn(LOG_PREFIX, 'Unable to compute from safeframe api.'); + utils.logWarn(LOG_PREFIX, 'Unable to compute from safeframe api.'); return ''; } const sfGeom = ws.$sf.ext.geom(); if (!sfGeom || !sfGeom.win) { - logWarn(LOG_PREFIX, 'Unable to compute from safeframe api. Missing `geom().win` property'); + utils.logWarn(LOG_PREFIX, 'Unable to compute from safeframe api. Missing `geom().win` property'); return ''; } @@ -730,7 +710,7 @@ function getViewPortDimensions() { viewportDims.h = Math.round(sfGeom.h); } else { // window.top based computing - const wt = getWindowTop(); + const wt = utils.getWindowTop(); viewportDims.w = wt.innerWidth; viewportDims.h = wt.innerHeight; } @@ -750,17 +730,17 @@ function getSlotPosition(adUnitElementId) { const position = { x: 0, y: 0 }; if (isSafeFrameWindow()) { - const ws = getWindowSelf(); + const ws = utils.getWindowSelf(); if (typeof ws.$sf.ext.geom !== 'function') { - logWarn(LOG_PREFIX, 'Unable to compute from safeframe api.'); + utils.logWarn(LOG_PREFIX, 'Unable to compute from safeframe api.'); return ''; } const sfGeom = ws.$sf.ext.geom(); if (!sfGeom || !sfGeom.self) { - logWarn(LOG_PREFIX, 'Unable to compute from safeframe api. Missing `geom().self` property'); + utils.logWarn(LOG_PREFIX, 'Unable to compute from safeframe api. Missing `geom().self` property'); return ''; } @@ -768,13 +748,13 @@ function getSlotPosition(adUnitElementId) { position.y = Math.round(sfGeom.l); } else if (canAccessTopWindow()) { // window.top based computing - const wt = getWindowTop(); + const wt = utils.getWindowTop(); const d = wt.document; let domElement; - if (inIframe() === true) { - const ws = getWindowSelf(); + if (utils.inIframe() === true) { + const ws = utils.getWindowSelf(); const currentElement = ws.document.getElementById(adUnitElementId); domElement = internal.getElementFromTopWindow(currentElement, ws); } else { @@ -823,7 +803,7 @@ function getPrintNumber(adUnitCode, bidderRequest) { return 1; } const adagioBid = find(bidderRequest.bids, bid => bid.adUnitCode === adUnitCode); - return adagioBid.bidderRequestsCount || 1; + return adagioBid.bidRequestsCount || 1; } /** @@ -833,7 +813,7 @@ function getDomLoadingDuration() { let domLoadingDuration = -1; let performance; - performance = (canAccessTopWindow()) ? getWindowTop().performance : getWindowSelf().performance; + performance = (canAccessTopWindow()) ? utils.getWindowTop().performance : utils.getWindowSelf().performance; if (performance && performance.timing && performance.timing.navigationStart > 0) { const val = performance.timing.domLoading - performance.timing.navigationStart; @@ -869,9 +849,7 @@ function storeRequestInAdagioNS(bidRequest) { }], auctionId: bidRequest.auctionId, pageviewId: internal.getPageviewId(), - printNumber, - localPbjs: '$$PREBID_GLOBAL$$', - localPbjsRef: getGlobal() + printNumber }); // (legacy) Store internal adUnit information @@ -892,8 +870,14 @@ export const spec = { autoFillParams(bid); + if (!internal.getRefererInfo().reachedTop) { + utils.logWarn(`${LOG_PREFIX} the main page url is unreachabled.`); + // internal.enqueue(debugData()); + return false; + } + if (!(bid.params.organizationId && bid.params.site && bid.params.placement)) { - logWarn(`${LOG_PREFIX} at least one required param is missing.`); + utils.logWarn(`${LOG_PREFIX} at least one required param is missing.`); // internal.enqueue(debugData()); return false; } @@ -912,7 +896,7 @@ export const spec = { const schain = _getSchain(validBidRequests[0]); const eids = _getEids(validBidRequests[0]) || []; - const adUnits = _map(validBidRequests, (bidRequest) => { + const adUnits = utils._map(validBidRequests, (bidRequest) => { const globalFeatures = GlobalExchange.getOrSetGlobalFeatures(); const features = { ...globalFeatures, @@ -939,47 +923,9 @@ export const spec = { }); // Handle priceFloors module - const computedFloors = _getFloors(bidRequest); - if (isArray(computedFloors) && computedFloors.length) { - bidRequest.floors = computedFloors - - if (deepAccess(bidRequest, 'mediaTypes.banner')) { - const bannerObj = bidRequest.mediaTypes.banner - - const computeNewSizeArray = (sizeArr = []) => { - const size = { size: sizeArr, floor: null } - const bannerFloors = bidRequest.floors.filter(floor => floor.mt === BANNER) - const BannerSizeFloor = bannerFloors.find(floor => floor.s === sizeArr.join('x')) - size.floor = (bannerFloors) ? (BannerSizeFloor) ? BannerSizeFloor.f : bannerFloors[0].f : null - return size - } - - // `bannerSizes`, internal property name - bidRequest.mediaTypes.banner.bannerSizes = (isArray(bannerObj.sizes[0])) - ? bannerObj.sizes.map(sizeArr => { - return computeNewSizeArray(sizeArr) - }) - : computeNewSizeArray(bannerObj.sizes) - } - - if (deepAccess(bidRequest, 'mediaTypes.video')) { - const videoObj = bidRequest.mediaTypes.video - const videoFloors = bidRequest.floors.filter(floor => floor.mt === VIDEO); - const playerSize = (videoObj.playerSize && isArray(videoObj.playerSize[0])) ? videoObj.playerSize[0] : videoObj.playerSize - const videoSizeFloor = (playerSize) ? videoFloors.find(floor => floor.s === playerSize.join('x')) : undefined - - bidRequest.mediaTypes.video.floor = (videoFloors) ? videoSizeFloor ? videoSizeFloor.f : videoFloors[0].f : null - } - - if (deepAccess(bidRequest, 'mediaTypes.native')) { - const nativeFloors = bidRequest.floors.filter(floor => floor.mt === NATIVE); - if (nativeFloors.length) { - bidRequest.mediaTypes.native.floor = nativeFloors[0].f - } - } - } + bidRequest.floors = _getFloors(bidRequest); - if (deepAccess(bidRequest, 'mediaTypes.video')) { + if (utils.deepAccess(bidRequest, 'mediaTypes.video')) { _buildVideoBidRequest(bidRequest); } @@ -990,7 +936,7 @@ export const spec = { // Group ad units by organizationId const groupedAdUnits = adUnits.reduce((groupedAdUnits, adUnit) => { - const adUnitCopy = deepClone(adUnit); + const adUnitCopy = utils.deepClone(adUnit); adUnitCopy.params.organizationId = adUnitCopy.params.organizationId.toString(); // remove useless props @@ -1004,12 +950,12 @@ export const spec = { }, {}); // Build one request per organizationId - const requests = _map(Object.keys(groupedAdUnits), organizationId => { + const requests = utils._map(Object.keys(groupedAdUnits), organizationId => { return { method: 'POST', url: ENDPOINT, data: { - id: generateUUID(), + id: utils.generateUUID(), organizationId: organizationId, secure: secure, device: device, @@ -1055,12 +1001,12 @@ export const spec = { const bidReq = (find(bidRequest.data.adUnits, bid => bid.bidId === bidObj.requestId)); if (bidReq) { - bidObj.meta = deepAccess(bidObj, 'meta', {}); + bidObj.meta = utils.deepAccess(bidObj, 'meta', {}); bidObj.meta.mediaType = bidObj.mediaType; bidObj.meta.advertiserDomains = (Array.isArray(bidObj.aDomain) && bidObj.aDomain.length) ? bidObj.aDomain : []; if (bidObj.mediaType === VIDEO) { - const mediaTypeContext = deepAccess(bidReq, 'mediaTypes.video.context'); + const mediaTypeContext = utils.deepAccess(bidReq, 'mediaTypes.video.context'); // Adagio SSP returns a `vastXml` only. No `vastUrl` nor `videoCacheKey`. if (!bidObj.vastUrl && bidObj.vastXml) { bidObj.vastUrl = 'data:text/xml;charset=utf-8;base64,' + btoa(bidObj.vastXml.replace(/\\"/g, '"')); @@ -1072,8 +1018,8 @@ export const spec = { adUnitCode: bidObj.adUnitCode, url: bidObj.urlRenderer || RENDERER_URL, config: { - ...deepAccess(bidReq, 'mediaTypes.video'), - ...deepAccess(bidObj, 'outstream', {}) + ...utils.deepAccess(bidReq, 'mediaTypes.video'), + ...utils.deepAccess(bidObj, 'outstream', {}) } }); @@ -1097,7 +1043,7 @@ export const spec = { } } } catch (err) { - logError(err); + utils.logError(err); } return bidResponses; }, @@ -1131,7 +1077,7 @@ export const spec = { if (isOrtb) { autoFillParams(adagioBid); - adagioBid.params.auctionId = deepAccess(adagioBidderRequest, 'auctionId'); + adagioBid.params.auctionId = utils.deepAccess(adagioBidderRequest, 'auctionId'); const globalFeatures = GlobalExchange.getOrSetGlobalFeatures(); adagioBid.params.features = { @@ -1144,7 +1090,7 @@ export const spec = { adagioBid.params.prebidVersion = '$prebid.version$'; adagioBid.params.data = GlobalExchange.getExchangeData(); - if (deepAccess(adagioBid, 'mediaTypes.video.context') === OUTSTREAM) { + if (utils.deepAccess(adagioBid, 'mediaTypes.video.context') === OUTSTREAM) { adagioBid.params.playerName = setPlayerName(adagioBid); } diff --git a/modules/adagioBidAdapter.md b/modules/adagioBidAdapter.md index 889822d9bd4..2779ced8cea 100644 --- a/modules/adagioBidAdapter.md +++ b/modules/adagioBidAdapter.md @@ -18,7 +18,7 @@ Below, the list of Adagio params and where they can be set. | ---------- | ------------- | ------------- | | siteId | x | | organizationId (obsolete) | | x -| site (obsolete) | | x +| site (obsolete) | | x | pagetype | x | x | environment | x | x | category | x | x diff --git a/modules/adbookpspBidAdapter.js b/modules/adbookpspBidAdapter.js index de8a3598be1..d3f3ba295b9 100644 --- a/modules/adbookpspBidAdapter.js +++ b/modules/adbookpspBidAdapter.js @@ -1,24 +1,10 @@ -import {find, includes} from '../src/polyfill.js'; -import {config} from '../src/config.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {getStorageManager} from '../src/storageManager.js'; -import { - deepAccess, - deepSetValue, - flatten, - generateUUID, - inIframe, - isArray, - isEmptyStr, - isNumber, - isPlainObject, - isStr, - logError, - logWarn, - triggerPixel, - uniques -} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import find from 'core-js-pure/features/array/find'; +import { config } from '../src/config.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { getStorageManager } from '../src/storageManager.js'; +import * as utils from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; /** * CONSTANTS @@ -164,7 +150,7 @@ function buildDevice() { const deviceConfig = common.getConfig('device'); - if (isPlainObject(deviceConfig)) { + if (utils.isPlainObject(deviceConfig)) { return { ...device, ...deviceConfig }; } @@ -177,12 +163,12 @@ function buildRegs(bidderRequest) { }; if (bidderRequest.gdprConsent) { - deepSetValue( + utils.deepSetValue( regs, 'ext.gdpr', bidderRequest.gdprConsent.gdprApplies ? 1 : 0 ); - deepSetValue( + utils.deepSetValue( regs, 'ext.gdprConsentString', bidderRequest.gdprConsent.consentString || '' @@ -190,7 +176,7 @@ function buildRegs(bidderRequest) { } if (bidderRequest.uspConsent) { - deepSetValue(regs, 'ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(regs, 'ext.us_privacy', bidderRequest.uspConsent); } return regs; @@ -201,10 +187,10 @@ function buildSource(bidRequests, bidderRequest) { fd: 1, tid: bidderRequest.auctionId, }; - const schain = deepAccess(bidRequests, '0.schain'); + const schain = utils.deepAccess(bidRequests, '0.schain'); if (schain) { - deepSetValue(source, 'ext.schain', schain); + utils.deepSetValue(source, 'ext.schain', schain); } return source; @@ -246,7 +232,7 @@ function buildMediaTypeObject(mediaType, bidRequest) { case VIDEO: return buildVideoObject(bidRequest); default: - logWarn(`${BIDDER_CODE}: Unsupported media type ${mediaType}!`); + utils.logWarn(`${BIDDER_CODE}: Unsupported media type ${mediaType}!`); } } @@ -260,7 +246,7 @@ function buildBannerObject(bidRequest) { return { pos: 0, - topframe: inIframe() ? 0 : 1, + topframe: utils.inIframe() ? 0 : 1, format, w, h, @@ -275,8 +261,8 @@ function buildVideoObject(bidRequest) { }; for (const param of VIDEO_PARAMS) { - const paramsValue = deepAccess(bidRequest, `params.video.${param}`); - const mediaTypeValue = deepAccess( + const paramsValue = utils.deepAccess(bidRequest, `params.video.${param}`); + const mediaTypeValue = utils.deepAccess( bidRequest, `mediaTypes.video.${param}` ); @@ -290,10 +276,10 @@ function buildVideoObject(bidRequest) { } function getVideoSize(bidRequest) { - const playerSize = deepAccess(bidRequest, 'mediaTypes.video.playerSize', [[]]); - const { w, h } = deepAccess(bidRequest, 'mediaTypes.video', {}); + const playerSize = utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize', [[]]); + const { w, h } = utils.deepAccess(bidRequest, 'mediaTypes.video', {}); - if (isNumber(w) && isNumber(h)) { + if (utils.isNumber(w) && utils.isNumber(h)) { return { w, h }; } @@ -310,11 +296,11 @@ function buildImpExt(validBidRequest) { const ext = {}; if (placementId) { - deepSetValue(ext, 'adbook.placementId', placementId); + utils.deepSetValue(ext, 'adbook.placementId', placementId); } if (effectiverOrgId) { - deepSetValue(ext, 'adbook.orgId', effectiverOrgId); + utils.deepSetValue(ext, 'adbook.orgId', effectiverOrgId); } return ext; @@ -328,19 +314,20 @@ function interpretResponse(bidResponse, bidderRequest) { const bidderRequestBody = safeJSONparse(bidderRequest.data); if ( - deepAccess(bidderRequestBody, 'id') != - deepAccess(bidResponse, 'body.id') + utils.deepAccess(bidderRequestBody, 'id') != + utils.deepAccess(bidResponse, 'body.id') ) { - logError( + utils.logError( `${BIDDER_CODE}: Bid response id does not match bidder request id` ); return []; } - const referrer = deepAccess(bidderRequestBody, 'site.ref', ''); - const incomingBids = deepAccess(bidResponse, 'body.seatbid', []) - .filter((seat) => isArray(seat.bid)) + const referrer = utils.deepAccess(bidderRequestBody, 'site.ref', ''); + const incomingBids = utils + .deepAccess(bidResponse, 'body.seatbid', []) + .filter((seat) => utils.isArray(seat.bid)) .reduce((bids, seat) => bids.concat(seat.bid), []) .filter(validateBid(bidderRequestBody)); const targetingMap = buildTargetingMap(incomingBids); @@ -374,21 +361,21 @@ function impBidsToPrebidBids( } const impToPrebidBid = - (bidderRequestBody, bidResponseCurrency, referrer, targetingMap) => (bid, bidIndex) => { + (bidderRequestBody, bidResponseCurrency, referrer, targetingMap) => (bid) => { try { const bidRequest = findBidRequest(bidderRequestBody, bid); if (!bidRequest) { - logError(`${BIDDER_CODE}: Could not match bid to bid request`); + utils.logError(`${BIDDER_CODE}: Could not match bid to bid request`); return null; } - const categories = deepAccess(bid, 'cat', []); + const categories = utils.deepAccess(bid, 'cat', []); const mediaType = getMediaType(bid.adm); let prebidBid = { ad: bid.adm, adId: bid.adid, - adserverTargeting: targetingMap[bidIndex], + adserverTargeting: targetingMap[bid.impid], adUnitCode: bidRequest.tagid, bidderRequestId: bidderRequestBody.id, bidId: bid.id, @@ -396,7 +383,7 @@ const impToPrebidBid = creativeId: bid.crid || bid.id, currency: bidResponseCurrency || getBidderConfig('defaultCurrency'), height: bid.h, - lineItemId: deepAccess(bid, 'ext.liid'), + lineItemId: utils.deepAccess(bid, 'ext.liid'), mediaType, meta: { advertiserDomains: bid.adomain, @@ -419,12 +406,9 @@ const impToPrebidBid = }; } - if (deepAccess(bid, 'ext.pa_win') === true) { - prebidBid.auctionWinner = true; - } return prebidBid; } catch (error) { - logError(`${BIDDER_CODE}: Error while building bid`, error); + utils.logError(`${BIDDER_CODE}: Error while building bid`, error); return null; } @@ -439,47 +423,33 @@ function getVideoSpecificParams(bidRequest, bid) { } function buildTargetingMap(bids) { - const impIds = bids.map(({ impid }) => impid).filter(uniques); + const impIds = bids.map(({ impid }) => impid).filter(utils.uniques); const values = impIds.reduce((result, id) => { result[id] = { lineItemIds: [], - orderIds: [], dealIds: [], adIds: [], - adAndOrderIndexes: [] }; return result; }, {}); - bids.forEach((bid, bidIndex) => { - let impId = bid.impid; - values[impId].lineItemIds.push(bid.ext.liid); - values[impId].dealIds.push(bid.dealid); - values[impId].adIds.push(bid.adid); - - if (deepAccess(bid, 'ext.ordid')) { - values[impId].orderIds.push(bid.ext.ordid); - bid.ext.ordid.split(TARGETING_VALUE_SEPARATOR).forEach((ordid, ordIndex) => { - let adIdIndex = values[impId].adIds.indexOf(bid.adid); - values[impId].adAndOrderIndexes.push(adIdIndex + '_' + ordIndex) - }) - } + bids.forEach((bid) => { + values[bid.impid].lineItemIds.push(bid.ext.liid); + values[bid.impid].dealIds.push(bid.dealid); + values[bid.impid].adIds.push(bid.adid); }); const targetingMap = {}; - bids.forEach((bid, bidIndex) => { - let id = bid.impid; - - targetingMap[bidIndex] = { + for (const id of impIds) { + targetingMap[id] = { hb_liid_adbookpsp: values[id].lineItemIds.join(TARGETING_VALUE_SEPARATOR), hb_deal_adbookpsp: values[id].dealIds.join(TARGETING_VALUE_SEPARATOR), - hb_ad_ord_adbookpsp: values[id].adAndOrderIndexes.join(TARGETING_VALUE_SEPARATOR), hb_adid_c_adbookpsp: values[id].adIds.join(TARGETING_VALUE_SEPARATOR), - hb_ordid_adbookpsp: values[id].orderIds.join(TARGETING_VALUE_SEPARATOR), }; - }) + } + return targetingMap; } @@ -489,12 +459,12 @@ function buildTargetingMap(bids) { function hasRequiredParams(bidRequest) { const value = - deepAccess(bidRequest, 'params.placementId') != null || - deepAccess(bidRequest, 'params.orgId') != null || + utils.deepAccess(bidRequest, 'params.placementId') != null || + utils.deepAccess(bidRequest, 'params.orgId') != null || getBidderConfig('orgId') != null; if (!value) { - logError(`${BIDDER_CODE}: missing orgId and placementId parameter`); + utils.logError(`${BIDDER_CODE}: missing orgId and placementId parameter`); } return value; @@ -502,7 +472,7 @@ function hasRequiredParams(bidRequest) { function isValidBannerRequest(bidRequest) { const value = validateSizes( - deepAccess(bidRequest, 'mediaTypes.banner.sizes', []) + utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes', []) ); return value; @@ -510,28 +480,28 @@ function isValidBannerRequest(bidRequest) { function isValidVideoRequest(bidRequest) { const value = - isArray(deepAccess(bidRequest, 'mediaTypes.video.mimes')) && + utils.isArray(utils.deepAccess(bidRequest, 'mediaTypes.video.mimes')) && validateVideoSizes(bidRequest); return value; } function validateSize(size) { - return isArray(size) && size.length === 2 && size.every(isNumber); + return utils.isArray(size) && size.length === 2 && size.every(utils.isNumber); } function validateSizes(sizes) { - return isArray(sizes) && sizes.length > 0 && sizes.every(validateSize); + return utils.isArray(sizes) && sizes.length > 0 && sizes.every(validateSize); } function validateVideoSizes(bidRequest) { - const { w, h } = deepAccess(bidRequest, 'mediaTypes.video', {}); + const { w, h } = utils.deepAccess(bidRequest, 'mediaTypes.video', {}); return ( validateSizes( - deepAccess(bidRequest, 'mediaTypes.video.playerSize') + utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize') ) || - (isNumber(w) && isNumber(h)) + (utils.isNumber(w) && utils.isNumber(h)) ); } @@ -548,7 +518,7 @@ function validateBid(bidderRequestBody) { const value = validators.every((validator) => validator(bid, bidRequest)); if (!value) { - logWarn(`${BIDDER_CODE}: Invalid bid`, bid); + utils.logWarn(`${BIDDER_CODE}: Invalid bid`, bid); } return value; @@ -556,13 +526,13 @@ function validateBid(bidderRequestBody) { } const commonBidValidators = [ - (bid) => isPlainObject(bid), + (bid) => utils.isPlainObject(bid), (bid) => isNonEmptyStr(bid.adid), (bid) => isNonEmptyStr(bid.adm), (bid) => isNonEmptyStr(bid.id), (bid) => isNonEmptyStr(bid.impid), - (bid) => isNonEmptyStr(deepAccess(bid, 'ext.liid')), - (bid) => isNumber(bid.price), + (bid) => isNonEmptyStr(utils.deepAccess(bid, 'ext.liid')), + (bid) => utils.isNumber(bid.price), ]; const bannerBidValidators = [ @@ -576,25 +546,25 @@ function validateBannerDimension(dimension) { return bannerHasSingleSize(bidRequest); } - return isNumber(bid[dimension]); + return utils.isNumber(bid[dimension]); }; } function bannerHasSingleSize(bidRequest) { - return deepAccess(bidRequest, 'banner.format', []).length === 1; + return utils.deepAccess(bidRequest, 'banner.format', []).length === 1; } /** * USER SYNC */ -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); +export const storage = getStorageManager(); function getUserSyncs(syncOptions, responses, gdprConsent, uspConsent) { return responses - .map((response) => deepAccess(response, 'body.ext.sync')) - .filter(isArray) - .reduce(flatten, []) + .map((response) => utils.deepAccess(response, 'body.ext.sync')) + .filter(utils.isArray) + .reduce(utils.flatten, []) .filter(validateSync(syncOptions)) .map(applyConsents(gdprConsent, uspConsent)); } @@ -674,11 +644,11 @@ function onBidWon(bid) { const wurl = buildWinUrl(bid); if (wurl !== null) { - triggerPixel(wurl); + utils.triggerPixel(wurl); } - if (isStr(bid.nurl)) { - triggerPixel(bid.nurl); + if (utils.isStr(bid.nurl)) { + utils.triggerPixel(bid.nurl); } } @@ -692,7 +662,7 @@ function buildWinUrl(bid) { return url.toString(); } catch (_) { - logError( + utils.logError( `${BIDDER_CODE}: Could not build win tracking URL with %s`, getBidderConfig('winTrackingUrl') ); @@ -716,7 +686,7 @@ function getMediaType(adm) { const markup = safeJSONparse(adm.replace(/\\/g, '')); - if (markup && isPlainObject(markup.native)) { + if (markup && utils.isPlainObject(markup.native)) { return NATIVE; } @@ -732,7 +702,7 @@ function safeJSONparse(...args) { } function isNonEmptyStr(value) { - return isStr(value) && !isEmptyStr(value); + return utils.isStr(value) && !utils.isEmptyStr(value); } function findBidRequest(bidderRequest, bid) { @@ -812,7 +782,7 @@ const getUrlBuilder = function (url) { export const common = { generateUUID: function () { - return generateUUID(); + return utils.generateUUID(); }, getConfig: function (property) { return config.getConfig(property); diff --git a/modules/addefendBidAdapter.js b/modules/addefendBidAdapter.js index dcc453ef35a..18cafe829b5 100644 --- a/modules/addefendBidAdapter.js +++ b/modules/addefendBidAdapter.js @@ -19,7 +19,6 @@ export const spec = { v: $$PREBID_GLOBAL$$.version, auctionId: false, pageId: false, - gdpr_applies: bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies ? bidderRequest.gdprConsent.gdprApplies : 'true', gdpr_consent: bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString ? bidderRequest.gdprConsent.consentString : '', referer: bidderRequest.refererInfo.referer, bids: [], diff --git a/modules/adfBidAdapter.js b/modules/adfBidAdapter.js index 0b9c72a2cee..43dcdcd1604 100644 --- a/modules/adfBidAdapter.js +++ b/modules/adfBidAdapter.js @@ -7,7 +7,7 @@ import { import { NATIVE, BANNER, VIDEO } from '../src/mediaTypes.js'; -import { mergeDeep, _map, deepAccess, parseSizesInput, deepSetValue } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { Renderer } from '../src/Renderer.js'; @@ -58,11 +58,7 @@ export const spec = { aliases: BIDDER_ALIAS, gvlid: GVLID, supportedMediaTypes: [ NATIVE, BANNER, VIDEO ], - isBidRequestValid: (bid) => { - const params = bid.params || {}; - const { mid, inv, mname } = params; - return !!(mid || (inv && mname)); - }, + isBidRequestValid: bid => !!bid.params.mid, buildRequests: (validBidRequests, bidderRequest) => { let app, site; @@ -72,12 +68,12 @@ export const spec = { if (typeof getConfig('app') === 'object') { app = getConfig('app') || {}; if (commonFpd.app) { - mergeDeep(app, commonFpd.app); + utils.mergeDeep(app, commonFpd.app); } } else { site = getConfig('site') || {}; if (commonFpd.site) { - mergeDeep(site, commonFpd.site); + utils.mergeDeep(site, commonFpd.site); } if (!site.page) { @@ -103,27 +99,12 @@ export const spec = { const imp = validBidRequests.map((bid, id) => { bid.netRevenue = pt; - const floorInfo = bid.getFloor ? bid.getFloor({ - currency: currency || 'USD' - }) : {}; - const bidfloor = floorInfo.floor; - const bidfloorcur = floorInfo.currency; - const { mid, inv, mname } = bid.params; - const imp = { id: id + 1, - tagid: mid, - bidfloor, - bidfloorcur, - ext: { - bidder: { - inv, - mname - } - } + tagid: bid.params.mid }; - const assets = _map(bid.nativeParams, (bidParams, key) => { + const assets = utils._map(bid.nativeParams, (bidParams, key) => { const props = NATIVE_PARAMS[key]; const asset = { required: bidParams.required & 1, @@ -164,12 +145,15 @@ export const spec = { assets } }; + + bid.mediaType = NATIVE; + return imp; } - const bannerParams = deepAccess(bid, 'mediaTypes.banner'); + const bannerParams = utils.deepAccess(bid, 'mediaTypes.banner'); if (bannerParams && bannerParams.sizes) { - const sizes = parseSizesInput(bannerParams.sizes); + const sizes = utils.parseSizesInput(bannerParams.sizes); const format = sizes.map(size => { const [ width, height ] = size.split('x'); const w = parseInt(width, 10); @@ -180,14 +164,18 @@ export const spec = { imp.banner = { format }; + bid.mediaType = BANNER; + + return imp; } - const videoParams = deepAccess(bid, 'mediaTypes.video'); + const videoParams = utils.deepAccess(bid, 'mediaTypes.video'); if (videoParams) { imp.video = videoParams; - } + bid.mediaType = VIDEO; - return imp; + return imp; + } }); const request = { @@ -206,26 +194,21 @@ export const spec = { request.is_debug = !!test; request.test = 1; } - - if (config.getConfig('coppa')) { - deepSetValue(request, 'regs.coppa', 1); - } - - if (deepAccess(bidderRequest, 'gdprConsent.gdprApplies') !== undefined) { - deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(request, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies & 1); + if (utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies') !== undefined) { + utils.deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(request, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies & 1); } if (bidderRequest.uspConsent) { - deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent); } if (eids) { - deepSetValue(request, 'user.ext.eids', eids); + utils.deepSetValue(request, 'user.ext.eids', eids); } if (schain) { - deepSetValue(request, 'source.ext.schain', schain); + utils.deepSetValue(request, 'source.ext.schain', schain); } return { @@ -252,7 +235,6 @@ export const spec = { return bids.map((bid, id) => { const bidResponse = bidResponses[id]; if (bidResponse) { - const mediaType = deepAccess(bidResponse, 'ext.prebid.type'); const result = { requestId: bid.bidId, cpm: bidResponse.price, @@ -260,12 +242,12 @@ export const spec = { ttl: 360, netRevenue: bid.netRevenue === 'net', currency: cur, - mediaType, + mediaType: bid.mediaType, width: bidResponse.w, height: bidResponse.h, dealId: bidResponse.dealid, meta: { - mediaType, + mediaType: bid.mediaType, advertiserDomains: bidResponse.adomain } }; @@ -273,10 +255,10 @@ export const spec = { if (bidResponse.native) { result.native = parseNative(bidResponse); } else { - result[ mediaType === VIDEO ? 'vastXml' : 'ad' ] = bidResponse.adm; + result[ bid.mediaType === VIDEO ? 'vastXml' : 'ad' ] = bidResponse.adm; } - if (!bid.renderer && mediaType === VIDEO && deepAccess(bid, 'mediaTypes.video.context') === 'outstream') { + if (!bid.renderer && bid.mediaType === VIDEO && utils.deepAccess(bid, 'mediaTypes.video.context') === 'outstream') { result.renderer = Renderer.install({id: bid.bidId, url: OUTSTREAM_RENDERER_URL, adUnitCode: bid.adUnitCode}); result.renderer.setRender(renderer); } @@ -310,7 +292,7 @@ function parseNative(bid) { function setOnAny(collection, key) { for (let i = 0, result; i < collection.length; i++) { - result = deepAccess(collection[i], key); + result = utils.deepAccess(collection[i], key); if (result) { return result; } diff --git a/modules/adgenerationBidAdapter.js b/modules/adgenerationBidAdapter.js index e0d3a881cad..f43fd284bad 100644 --- a/modules/adgenerationBidAdapter.js +++ b/modules/adgenerationBidAdapter.js @@ -1,4 +1,4 @@ -import {tryAppendQueryString, getBidIdParameter} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; @@ -25,7 +25,7 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function (validBidRequests, bidderRequest) { - const ADGENE_PREBID_VERSION = '1.3.0'; + const ADGENE_PREBID_VERSION = '1.1.0'; let serverRequests = []; for (let i = 0, len = validBidRequests.length; i < len; i++) { const validReq = validBidRequests[i]; @@ -33,29 +33,23 @@ export const spec = { const URL = 'https://d.socdm.com/adsv/v1'; const url = validReq.params.debug ? DEBUG_URL : URL; let data = ``; - data = tryAppendQueryString(data, 'posall', 'SSPLOC'); - const id = getBidIdParameter('id', validReq.params); - data = tryAppendQueryString(data, 'id', id); - data = tryAppendQueryString(data, 'sdktype', '0'); - data = tryAppendQueryString(data, 'hb', 'true'); - data = tryAppendQueryString(data, 't', 'json3'); - data = tryAppendQueryString(data, 'transactionid', validReq.transactionId); - data = tryAppendQueryString(data, 'sizes', getSizes(validReq)); - data = tryAppendQueryString(data, 'currency', getCurrencyType()); - data = tryAppendQueryString(data, 'pbver', '$prebid.version$'); - data = tryAppendQueryString(data, 'sdkname', 'prebidjs'); - data = tryAppendQueryString(data, 'adapterver', ADGENE_PREBID_VERSION); + data = utils.tryAppendQueryString(data, 'posall', 'SSPLOC'); + const id = utils.getBidIdParameter('id', validReq.params); + data = utils.tryAppendQueryString(data, 'id', id); + data = utils.tryAppendQueryString(data, 'sdktype', '0'); + data = utils.tryAppendQueryString(data, 'hb', 'true'); + data = utils.tryAppendQueryString(data, 't', 'json3'); + data = utils.tryAppendQueryString(data, 'transactionid', validReq.transactionId); + data = utils.tryAppendQueryString(data, 'sizes', getSizes(validReq)); + data = utils.tryAppendQueryString(data, 'currency', getCurrencyType()); + data = utils.tryAppendQueryString(data, 'pbver', '$prebid.version$'); + data = utils.tryAppendQueryString(data, 'sdkname', 'prebidjs'); + data = utils.tryAppendQueryString(data, 'adapterver', ADGENE_PREBID_VERSION); // native以外にvideo等の対応が入った場合は要修正 if (!validReq.mediaTypes || !validReq.mediaTypes.native) { - data = tryAppendQueryString(data, 'imark', '1'); - } - data = tryAppendQueryString(data, 'tp', bidderRequest.refererInfo.referer); - if (isIos()) { - const hyperId = getHyperId(validReq); - if (hyperId != null) { - data = tryAppendQueryString(data, 'hyper_id', hyperId); - } + data = utils.tryAppendQueryString(data, 'imark', '1'); } + data = utils.tryAppendQueryString(data, 'tp', bidderRequest.refererInfo.referer); // remove the trailing "&" if (data.lastIndexOf('&') === data.length - 1) { data = data.substring(0, data.length - 1); @@ -124,25 +118,13 @@ export const spec = { function createAd(body, bidRequest) { let ad = body.ad; if (body.vastxml && body.vastxml.length > 0) { - if (isUpperBillboard(body)) { - const marginTop = bidRequest.params.marginTop ? bidRequest.params.marginTop : '0'; - ad = `${createADGBrowserMTag()}${insertVASTMethodForADGBrowserM(body.vastxml, marginTop)}`; - } else { - ad = `
${createAPVTag()}${insertVASTMethodForAPV(bidRequest.bidId, body.vastxml)}`; - } + ad = `
${createAPVTag()}${insertVASTMethod(bidRequest.bidId, body.vastxml)}`; } ad = appendChildToBody(ad, body.beacon); if (removeWrapper(ad)) return removeWrapper(ad); return ad; } -function isUpperBillboard(body) { - if (body.location_params && body.location_params.option && body.location_params.option.ad_type) { - return body.location_params.option.ad_type === 'upper_billboard'; - } - return false; -} - function isNative(body) { if (!body) return false; return body.native_ad && body.native_ad.assets.length > 0; @@ -208,12 +190,7 @@ function createAPVTag() { return apvScript.outerHTML; } -function createADGBrowserMTag() { - const ADGBrowserMURL = 'https://i.socdm.com/sdk/js/adg-browser-m.js'; - return ``; -} - -function insertVASTMethodForAPV(targetId, vastXml) { +function insertVASTMethod(targetId, vastXml) { let apvVideoAdParam = { s: targetId }; @@ -223,13 +200,6 @@ function insertVASTMethodForAPV(targetId, vastXml) { return script.outerHTML; } -function insertVASTMethodForADGBrowserM(vastXml, marginTop) { - const script = document.createElement(`script`); - script.type = 'text/javascript'; - script.innerHTML = `window.ADGBrowserM.init({vastXml: '${vastXml.replace(/\r?\n/g, '')}', marginTop: '${marginTop}'});`; - return script.outerHTML; -} - /** * * @param ad @@ -269,20 +239,4 @@ function getCurrencyType() { return 'JPY'; } -/** - * - * @param validReq request - * @return {null|string} - */ -function getHyperId(validReq) { - if (validReq.userId && validReq.userId.novatiq && validReq.userId.novatiq.snowflake.syncResponse === 1) { - return validReq.userId.novatiq.snowflake.id; - } - return null; -} - -function isIos() { - return (/(ios|ipod|ipad|iphone)/i).test(window.navigator.userAgent); -} - registerBidder(spec); diff --git a/modules/adhashBidAdapter.js b/modules/adhashBidAdapter.js deleted file mode 100644 index 7f5af047993..00000000000 --- a/modules/adhashBidAdapter.js +++ /dev/null @@ -1,183 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {includes} from '../src/polyfill.js'; -import {BANNER} from '../src/mediaTypes.js'; - -const VERSION = '1.0'; -const BAD_WORD_STEP = 0.1; -const BAD_WORD_MIN = 0.2; - -/** - * Function that checks the page where the ads are being served for brand safety. - * If unsafe words are found the scoring of that page increases. - * If it becomes greater than the maximum allowed score false is returned. - * The rules may vary based on the website language or the publisher. - * The AdHash bidder will not bid on unsafe pages (according to 4A's). - * @param badWords list of scoring rules to chech against - * @param maxScore maximum allowed score for that bidding - * @returns boolean flag is the page safe - */ -function brandSafety(badWords, maxScore) { - /** - * Performs the ROT13 encoding on the string argument and returns the resulting string. - * The Adhash bidder uses ROT13 so that the response is not blocked by: - * - ad blocking software - * - parental control software - * - corporate firewalls - * due to the bad words contained in the response. - * @param value The input string. - * @returns string Returns the ROT13 version of the given string. - */ - const rot13 = value => { - const input = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - const output = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'; - const index = x => input.indexOf(x); - const translate = x => index(x) > -1 ? output[index(x)] : x; - return value.split('').map(translate).join(''); - }; - - /** - * Calculates the scoring for each bad word with dimishing returns - * @param {integer} points points that this word costs - * @param {integer} occurances number of occurances - * @returns {float} final score - */ - const scoreCalculator = (points, occurances) => { - let positive = true; - if (points < 0) { - points *= -1; - positive = false; - } - let result = 0; - for (let i = 0; i < occurances; i++) { - result += Math.max(points - i * BAD_WORD_STEP, BAD_WORD_MIN); - } - return positive ? result : -result; - }; - - // Default parameters if the bidder is unable to send some of them - badWords = badWords || []; - maxScore = parseInt(maxScore) || 10; - - try { - let score = 0; - const content = window.top.document.body.innerText.toLowerCase(); - const words = content.trim().split(/\s+/).length; - for (const [word, rule, points] of badWords) { - if (rule === 'full' && new RegExp('\\b' + rot13(word) + '\\b', 'i').test(content)) { - const occurances = content.match(new RegExp('\\b' + rot13(word) + '\\b', 'g')).length; - score += scoreCalculator(points, occurances); - } else if (rule === 'partial' && content.indexOf(rot13(word.toLowerCase())) > -1) { - const occurances = content.match(new RegExp(rot13(word), 'g')).length; - score += scoreCalculator(points, occurances); - } - } - return score < maxScore * words / 500; - } catch (e) { - return true; - } -} - -export const spec = { - code: 'adhash', - url: 'https://bidder.adhash.com/rtb?version=' + VERSION + '&prebid=true', - supportedMediaTypes: [ BANNER ], - - isBidRequestValid: (bid) => { - try { - const { publisherId, platformURL } = bid.params; - return ( - includes(Object.keys(bid.mediaTypes), BANNER) && - typeof publisherId === 'string' && - publisherId.length === 42 && - typeof platformURL === 'string' && - platformURL.length >= 13 - ); - } catch (error) { - return false; - } - }, - - buildRequests: (validBidRequests, bidderRequest) => { - const { gdprConsent } = bidderRequest; - const { url } = spec; - const bidRequests = []; - let referrer = ''; - if (bidderRequest && bidderRequest.refererInfo) { - referrer = bidderRequest.refererInfo.referer; - } - for (var i = 0; i < validBidRequests.length; i++) { - var index = Math.floor(Math.random() * validBidRequests[i].sizes.length); - var size = validBidRequests[i].sizes[index].join('x'); - bidRequests.push({ - method: 'POST', - url: url + '&publisher=' + validBidRequests[i].params.publisherId, - bidRequest: validBidRequests[i], - data: { - timezone: new Date().getTimezoneOffset() / 60, - location: referrer, - publisherId: validBidRequests[i].params.publisherId, - size: { - screenWidth: window.screen.width, - screenHeight: window.screen.height - }, - navigator: { - platform: window.navigator.platform, - language: window.navigator.language, - userAgent: window.navigator.userAgent - }, - creatives: [{ - size: size, - position: validBidRequests[i].adUnitCode - }], - blockedCreatives: [], - currentTimestamp: new Date().getTime(), - recentAds: [], - GDPRApplies: gdprConsent ? gdprConsent.gdprApplies : null, - GDPR: gdprConsent ? gdprConsent.consentString : null - }, - options: { - withCredentials: false, - crossOrigin: true - }, - }); - } - return bidRequests; - }, - - interpretResponse: (serverResponse, request) => { - const responseBody = serverResponse ? serverResponse.body : {}; - - if ( - !responseBody.creatives || - responseBody.creatives.length === 0 || - !brandSafety(responseBody.badWords, responseBody.maxScore) - ) { - return []; - } - - const publisherURL = JSON.stringify(request.bidRequest.params.platformURL); - const oneTimeId = request.bidRequest.adUnitCode + Math.random().toFixed(16).replace('0.', '.'); - const bidderResponse = JSON.stringify({ responseText: JSON.stringify(responseBody) }); - const requestData = JSON.stringify(request.data); - - return [{ - requestId: request.bidRequest.bidId, - cpm: responseBody.creatives[0].costEUR, - ad: - `
- - `, - width: request.bidRequest.sizes[0][0], - height: request.bidRequest.sizes[0][1], - creativeId: request.bidRequest.adUnitCode, - netRevenue: true, - currency: 'EUR', - ttl: 60, - meta: { - advertiserDomains: responseBody.advertiserDomains ? [responseBody.advertiserDomains] : [] - } - }]; - } -}; - -registerBidder(spec); diff --git a/modules/adhashBidAdapter.md b/modules/adhashBidAdapter.md index 4ee6ed3dc83..c1093e0ccd7 100644 --- a/modules/adhashBidAdapter.md +++ b/modules/adhashBidAdapter.md @@ -34,7 +34,7 @@ Please note that a number of AdHash functionalities are not supported in the Pre bidder: 'adhash', params: { publisherId: '0x1234567890123456789012345678901234567890', - platformURL: 'https://adhash.org/p/example/' + platformURL: 'https://adhash.org/p/struma/' } } ] diff --git a/modules/adheseBidAdapter.js b/modules/adheseBidAdapter.js index 145b5605bc2..88f3e0e0e4f 100644 --- a/modules/adheseBidAdapter.js +++ b/modules/adheseBidAdapter.js @@ -2,7 +2,6 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; const BIDDER_CODE = 'adhese'; const GVLID = 553; @@ -21,15 +20,11 @@ export const spec = { if (validBidRequests.length === 0) { return null; } - const { gdprConsent, refererInfo } = bidderRequest; - const adheseConfig = config.getConfig('adhese'); const gdprParams = (gdprConsent && gdprConsent.consentString) ? { xt: [gdprConsent.consentString] } : {}; const refererParams = (refererInfo && refererInfo.referer) ? { xf: [base64urlEncode(refererInfo.referer)] } : {}; - const globalCustomParams = (adheseConfig && adheseConfig.globalTargets) ? cleanTargets(adheseConfig.globalTargets) : {}; - const commonParams = { ...globalCustomParams, ...gdprParams, ...refererParams }; - const vastContentAsUrl = !(adheseConfig && adheseConfig.vastContentAsUrl == false); + const commonParams = { ...gdprParams, ...refererParams }; const slots = validBidRequests.map(bid => ({ slotname: bidToSlotName(bid), @@ -39,7 +34,7 @@ export const spec = { const payload = { slots: slots, parameters: commonParams, - vastContentAsUrl: vastContentAsUrl, + vastContentAsUrl: true, user: { ext: { eids: getEids(validBidRequests), diff --git a/modules/adkernelAdnAnalyticsAdapter.js b/modules/adkernelAdnAnalyticsAdapter.js index de5d59ca6f8..23501f7dd63 100644 --- a/modules/adkernelAdnAnalyticsAdapter.js +++ b/modules/adkernelAdnAnalyticsAdapter.js @@ -1,7 +1,7 @@ import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; -import { logError, parseUrl, _each } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import {getStorageManager} from '../src/storageManager.js'; import {config} from '../src/config.js'; @@ -10,7 +10,7 @@ const GVLID = 14; const ANALYTICS_VERSION = '1.0.2'; const DEFAULT_QUEUE_TIMEOUT = 4000; const DEFAULT_HOST = 'tag.adkernel.com'; -const storageObj = getStorageManager({gvlid: GVLID}); +const storageObj = getStorageManager(GVLID); const ADK_HB_EVENTS = { AUCTION_INIT: 'auctionInit', @@ -90,7 +90,7 @@ analyticsAdapter.originEnableAnalytics = analyticsAdapter.enableAnalytics; analyticsAdapter.enableAnalytics = (config) => { if (!config.options.pubId) { - logError('PubId is not defined. Analytics won\'t work'); + utils.logError('PubId is not defined. Analytics won\'t work'); return; } analyticsAdapter.context = { @@ -215,7 +215,7 @@ export function getUmtSource(pageUrl, referrer) { if (se) { return asUtm(se, ORGANIC, ORGANIC); } - let parsedUrl = parseUrl(pageUrl); + let parsedUrl = utils.parseUrl(pageUrl); let [refHost, refPath] = getReferrer(referrer); if (refHost && refHost !== parsedUrl.hostname) { return asUtm(refHost, REFERRAL, REFERRAL, '', refPath); @@ -242,17 +242,17 @@ export function getUmtSource(pageUrl, referrer) { } function getReferrer(referrer) { - let ref = parseUrl(referrer); + let ref = utils.parseUrl(referrer); return [ref.hostname, ref.pathname]; } function getUTM(pageUrl) { - let urlParameters = parseUrl(pageUrl).search; + let urlParameters = utils.parseUrl(pageUrl).search; if (!urlParameters['utm_campaign'] || !urlParameters['utm_source']) { return; } let utmArgs = []; - _each(UTM_TAGS, (utmTagName) => { + utils._each(UTM_TAGS, (utmTagName) => { let utmValue = urlParameters[utmTagName] || ''; utmArgs.push(utmValue); }); diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index 39f7b9fd2b2..dc56ed6abbb 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, parseSizesInput, isArray, deepSetValue, parseUrl, isStr, isNumber, logInfo } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; @@ -19,12 +19,12 @@ function buildImp(bidRequest) { tagid: bidRequest.adUnitCode }; let mediaType; - let bannerReq = deepAccess(bidRequest, `mediaTypes.banner`); - let videoReq = deepAccess(bidRequest, `mediaTypes.video`); + let bannerReq = utils.deepAccess(bidRequest, `mediaTypes.banner`); + let videoReq = utils.deepAccess(bidRequest, `mediaTypes.video`); if (bannerReq) { let sizes = canonicalizeSizesArray(bannerReq.sizes); imp.banner = { - format: parseSizesInput(sizes) + format: utils.parseSizesInput(sizes) }; mediaType = BANNER; } else if (videoReq) { @@ -51,7 +51,7 @@ function buildImp(bidRequest) { * @return Array[Array[Number]] */ function canonicalizeSizesArray(sizes) { - if (sizes.length === 2 && !isArray(sizes[0])) { + if (sizes.length === 2 && !utils.isArray(sizes[0])) { return [sizes]; } return sizes; @@ -67,23 +67,23 @@ function buildRequestParams(tags, bidderRequest) { }; if (gdprConsent) { if (gdprConsent.gdprApplies !== undefined) { - deepSetValue(req, 'user.gdpr', ~~gdprConsent.gdprApplies); + utils.deepSetValue(req, 'user.gdpr', ~~gdprConsent.gdprApplies); } if (gdprConsent.consentString !== undefined) { - deepSetValue(req, 'user.consent', gdprConsent.consentString); + utils.deepSetValue(req, 'user.consent', gdprConsent.consentString); } } if (uspConsent) { - deepSetValue(req, 'user.us_privacy', uspConsent); + utils.deepSetValue(req, 'user.us_privacy', uspConsent); } if (config.getConfig('coppa')) { - deepSetValue(req, 'user.coppa', 1); + utils.deepSetValue(req, 'user.coppa', 1); } return req; } function buildSite(refInfo) { - let loc = parseUrl(refInfo.referer); + let loc = utils.parseUrl(refInfo.referer); let result = { page: `${loc.protocol}://${loc.hostname}${loc.pathname}`, secure: ~~(loc.protocol === 'https') @@ -126,23 +126,23 @@ function buildBid(tag) { } function fillBidMeta(bid, tag) { - if (isStr(tag.agencyName)) { - deepSetValue(bid, 'meta.agencyName', tag.agencyName); + if (utils.isStr(tag.agencyName)) { + utils.deepSetValue(bid, 'meta.agencyName', tag.agencyName); } - if (isNumber(tag.advertiserId)) { - deepSetValue(bid, 'meta.advertiserId', tag.advertiserId); + if (utils.isNumber(tag.advertiserId)) { + utils.deepSetValue(bid, 'meta.advertiserId', tag.advertiserId); } - if (isStr(tag.advertiserName)) { - deepSetValue(bid, 'meta.advertiserName', tag.advertiserName); + if (utils.isStr(tag.advertiserName)) { + utils.deepSetValue(bid, 'meta.advertiserName', tag.advertiserName); } - if (isArray(tag.advertiserDomains)) { - deepSetValue(bid, 'meta.advertiserDomains', tag.advertiserDomains); + if (utils.isArray(tag.advertiserDomains)) { + utils.deepSetValue(bid, 'meta.advertiserDomains', tag.advertiserDomains); } - if (isStr(tag.primaryCatId)) { - deepSetValue(bid, 'meta.primaryCatId', tag.primaryCatId); + if (utils.isStr(tag.primaryCatId)) { + utils.deepSetValue(bid, 'meta.primaryCatId', tag.primaryCatId); } - if (isArray(tag.secondaryCatIds)) { - deepSetValue(bid, 'meta.secondaryCatIds', tag.secondaryCatIds); + if (utils.isArray(tag.secondaryCatIds)) { + utils.deepSetValue(bid, 'meta.secondaryCatIds', tag.secondaryCatIds); } } @@ -204,7 +204,7 @@ export const spec = { return []; } if (response.debug) { - logInfo(`ADKERNEL DEBUG:\n${response.debug}`); + utils.logInfo(`ADKERNEL DEBUG:\n${response.debug}`); } return response.tags.map(buildBid); }, diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index c2d6ca4d4dd..5cfb44f7127 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -1,26 +1,8 @@ -import { - _each, - cleanObj, - contains, - createTrackPixelHtml, - deepAccess, - deepSetValue, - getAdUnitSizes, - getDNT, - inIframe, - isArray, - isArrayOfNums, - isEmpty, - isNumber, - isPlainObject, - isStr, - mergeDeep, - parseGPTSingleSizeArrayToRtbSize, - parseUrl -} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {find, includes} from '../src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; import {config} from '../src/config.js'; /* @@ -88,13 +70,7 @@ export const spec = { {code: 'converge', gvlid: 248}, {code: 'adomega'}, {code: 'denakop'}, - {code: 'rtbanalytica'}, - {code: 'unibots'}, - {code: 'catapultx'}, - {code: 'ergadx'}, - {code: 'turktelekom'}, - {code: 'felixads'}, - {code: 'motionspots'} + {code: 'rtbanalytica'} ], supportedMediaTypes: [BANNER, VIDEO, NATIVE], @@ -120,16 +96,17 @@ export const spec = { * @returns {ServerRequest[]} */ buildRequests: function (bidRequests, bidderRequest) { - let impGroups = groupImpressionsByHostZone(bidRequests, bidderRequest.refererInfo); + let impDispatch = dispatchImps(bidRequests, bidderRequest.refererInfo); let requests = []; let schain = bidRequests[0].schain; - _each(impGroups, impGroup => { - let {host, zoneId, imps} = impGroup; - const request = buildRtbRequest(imps, bidderRequest, schain); - requests.push({ - method: 'POST', - url: `https://${host}/hb?zone=${zoneId}&v=${VERSION}`, - data: JSON.stringify(request) + Object.keys(impDispatch).forEach(host => { + Object.keys(impDispatch[host]).forEach(zoneId => { + const request = buildRtbRequest(impDispatch[host][zoneId], bidderRequest, schain); + requests.push({ + method: 'POST', + url: `https://${host}/hb?zone=${zoneId}&v=${VERSION}`, + data: JSON.stringify(request) + }); }); }); return requests; @@ -176,24 +153,24 @@ export const spec = { prBid.mediaType = NATIVE; prBid.native = buildNativeAd(JSON.parse(rtbBid.adm)); } - if (isStr(rtbBid.dealid)) { + if (utils.isStr(rtbBid.dealid)) { prBid.dealId = rtbBid.dealid; } - if (isArray(rtbBid.adomain)) { - deepSetValue(prBid, 'meta.advertiserDomains', rtbBid.adomain); + if (utils.isArray(rtbBid.adomain)) { + utils.deepSetValue(prBid, 'meta.advertiserDomains', rtbBid.adomain); } - if (isArray(rtbBid.cat)) { - deepSetValue(prBid, 'meta.secondaryCatIds', rtbBid.cat); + if (utils.isArray(rtbBid.cat)) { + utils.deepSetValue(prBid, 'meta.secondaryCatIds', rtbBid.cat); } - if (isPlainObject(rtbBid.ext)) { - if (isNumber(rtbBid.ext.advertiser_id)) { - deepSetValue(prBid, 'meta.advertiserId', rtbBid.ext.advertiser_id); + if (utils.isPlainObject(rtbBid.ext)) { + if (utils.isNumber(rtbBid.ext.advertiser_id)) { + utils.deepSetValue(prBid, 'meta.advertiserId', rtbBid.ext.advertiser_id); } - if (isStr(rtbBid.ext.advertiser_name)) { - deepSetValue(prBid, 'meta.advertiserName', rtbBid.ext.advertiser_name); + if (utils.isStr(rtbBid.ext.advertiser_name)) { + utils.deepSetValue(prBid, 'meta.advertiserName', rtbBid.ext.advertiser_name); } - if (isStr(rtbBid.ext.agency_name)) { - deepSetValue(prBid, 'meta.agencyName', rtbBid.ext.agency_name); + if (utils.isStr(rtbBid.ext.agency_name)) { + utils.deepSetValue(prBid, 'meta.agencyName', rtbBid.ext.agency_name); } } @@ -225,19 +202,17 @@ registerBidder(spec); * @param bidRequests {BidRequest[]} * @param refererInfo {refererInfo} */ -function groupImpressionsByHostZone(bidRequests, refererInfo) { +function dispatchImps(bidRequests, refererInfo) { let secure = (refererInfo && refererInfo.referer.indexOf('https:') === 0); - return Object.values( - bidRequests.map(bidRequest => buildImp(bidRequest, secure)) - .reduce((acc, curr, index) => { - let bidRequest = bidRequests[index]; - let {zoneId, host} = bidRequest.params; - let key = `${host}_${zoneId}`; - acc[key] = acc[key] || {host: host, zoneId: zoneId, imps: []}; - acc[key].imps.push(curr); - return acc; - }, {}) - ); + return bidRequests.map(bidRequest => buildImp(bidRequest, secure)) + .reduce((acc, curr, index) => { + let bidRequest = bidRequests[index]; + let {zoneId, host} = bidRequest.params; + acc[host] = acc[host] || {}; + acc[host][zoneId] = acc[host][zoneId] || []; + acc[host][zoneId].push(curr); + return acc; + }, {}); } function getBidFloor(bid, mediaType, sizes) { @@ -265,19 +240,19 @@ function buildImp(bidRequest, secure) { var mediaType; var sizes = []; - if (deepAccess(bidRequest, 'mediaTypes.banner')) { - sizes = getAdUnitSizes(bidRequest); + if (utils.deepAccess(bidRequest, 'mediaTypes.banner')) { + sizes = utils.getAdUnitSizes(bidRequest); imp.banner = { - format: sizes.map(wh => parseGPTSingleSizeArrayToRtbSize(wh)), + format: sizes.map(wh => utils.parseGPTSingleSizeArrayToRtbSize(wh)), topframe: 0 }; mediaType = BANNER; - } else if (deepAccess(bidRequest, 'mediaTypes.video')) { - let video = deepAccess(bidRequest, 'mediaTypes.video'); + } else if (utils.deepAccess(bidRequest, 'mediaTypes.video')) { + let video = utils.deepAccess(bidRequest, 'mediaTypes.video'); imp.video = {}; if (video.playerSize) { sizes = video.playerSize[0]; - imp.video = Object.assign(imp.video, parseGPTSingleSizeArrayToRtbSize(sizes) || {}); + imp.video = Object.assign(imp.video, utils.parseGPTSingleSizeArrayToRtbSize(sizes) || {}); } if (bidRequest.params.video) { Object.keys(bidRequest.params.video) @@ -285,7 +260,7 @@ function buildImp(bidRequest, secure) { .forEach(key => imp.video[key] = bidRequest.params.video[key]); } mediaType = VIDEO; - } else if (deepAccess(bidRequest, 'mediaTypes.native')) { + } else if (utils.deepAccess(bidRequest, 'mediaTypes.native')) { let nativeRequest = buildNativeRequest(bidRequest.mediaTypes.native); imp.native = { ver: '1.1', @@ -323,7 +298,7 @@ function buildNativeRequest(nativeReq) { if (desc.assetType === 'img') { assetRoot[desc.assetType] = buildImageAsset(desc, v); } else if (desc.assetType === 'data') { - assetRoot.data = cleanObj({type: desc.type, len: v.len}); + assetRoot.data = utils.cleanObj({type: desc.type, len: v.len}); } else if (desc.assetType === 'title') { assetRoot.title = {len: v.len || 90}; } else { @@ -347,7 +322,7 @@ function buildImageAsset(desc, val) { img.wmin = val.aspect_ratios[0].min_width; img.hmin = val.aspect_ratios[0].min_height; } - return cleanObj(img); + return utils.cleanObj(img); } /** @@ -360,9 +335,9 @@ function isSyncMethodAllowed(syncRule, bidderCode) { if (!syncRule) { return false; } - let bidders = isArray(syncRule.bidders) ? syncRule.bidders : [bidderCode]; + let bidders = utils.isArray(syncRule.bidders) ? syncRule.bidders : [bidderCode]; let rule = syncRule.filter === 'include'; - return contains(bidders, bidderCode) === rule; + return utils.contains(bidders, bidderCode) === rule; } /** @@ -383,141 +358,56 @@ function getAllowedSyncMethod(bidderCode) { } /** - * Create device object from fpd and host-collected data - * @param fpd {Object} - * @returns {{device: Object}} - */ -function makeDevice(fpd) { - let device = mergeDeep({ - 'ip': 'caller', - 'ipv6': 'caller', - 'ua': 'caller', - 'js': 1, - 'language': getLanguage() - }, fpd.device || {}); - if (getDNT()) { - device.dnt = 1; - } - return {device: device}; -} - -/** - * Create site or app description object - * @param bidderRequest {BidderRequest} - * @param fpd {Object} - * @returns {{site: Object}|{app: Object}} - */ -function makeSiteOrApp(bidderRequest, fpd) { - let {refererInfo} = bidderRequest; - let appConfig = config.getConfig('app'); - if (isEmpty(appConfig)) { - return {site: createSite(refererInfo, fpd)} - } else { - return {app: appConfig}; - } -} - -/** - * Create user description object + * Builds complete rtb request + * @param imps {Object} Collection of rtb impressions * @param bidderRequest {BidderRequest} - * @param fpd {Object} - * @returns {{user: Object} | undefined} + * @param schain {Object=} Supply chain config + * @return {Object} Complete rtb request */ -function makeUser(bidderRequest, fpd) { - let {gdprConsent} = bidderRequest; - let user = fpd.user || {}; - if (gdprConsent && gdprConsent.consentString !== undefined) { - deepSetValue(user, 'ext.consent', gdprConsent.consentString); - } - let eids = getExtendedUserIds(bidderRequest); - if (eids) { - deepSetValue(user, 'ext.eids', eids); +function buildRtbRequest(imps, bidderRequest, schain) { + let {bidderCode, gdprConsent, auctionId, refererInfo, timeout, uspConsent} = bidderRequest; + let coppa = config.getConfig('coppa'); + let req = { + 'id': auctionId, + 'imp': imps, + 'site': createSite(refererInfo), + 'at': 1, + 'device': { + 'ip': 'caller', + 'ipv6': 'caller', + 'ua': 'caller', + 'js': 1, + 'language': getLanguage() + }, + 'tmax': parseInt(timeout) + }; + if (utils.getDNT()) { + req.device.dnt = 1; } - if (!isEmpty(user)) { return {user: user}; } -} - -/** - * Create privacy regulations object - * @param bidderRequest {BidderRequest} - * @returns {{regs: Object} | undefined} - */ -function makeRegulations(bidderRequest) { - let {gdprConsent, uspConsent} = bidderRequest; - let regs = {}; if (gdprConsent) { if (gdprConsent.gdprApplies !== undefined) { - deepSetValue(regs, 'regs.ext.gdpr', ~~gdprConsent.gdprApplies); + utils.deepSetValue(req, 'regs.ext.gdpr', ~~gdprConsent.gdprApplies); + } + if (gdprConsent.consentString !== undefined) { + utils.deepSetValue(req, 'user.ext.consent', gdprConsent.consentString); } } if (uspConsent) { - deepSetValue(regs, 'regs.ext.us_privacy', uspConsent); - } - if (config.getConfig('coppa')) { - deepSetValue(regs, 'regs.coppa', 1); - } - if (!isEmpty(regs)) { - return regs; + utils.deepSetValue(req, 'regs.ext.us_privacy', uspConsent); } -} - -/** - * Create top-level request object - * @param bidderRequest {BidderRequest} - * @param imps {Object} Impressions - * @param fpd {Object} First party data - * @returns - */ -function makeBaseRequest(bidderRequest, imps, fpd) { - let {auctionId, timeout} = bidderRequest; - let request = { - 'id': auctionId, - 'imp': imps, - 'at': 1, - 'tmax': parseInt(timeout) - }; - if (!isEmpty(fpd.bcat)) { - request.bcat = fpd.bcat; - } - if (!isEmpty(fpd.badv)) { - request.badv = fpd.badv; + if (coppa) { + utils.deepSetValue(req, 'regs.coppa', 1); } - return request; -} - -/** - * Initialize sync capabilities - * @param bidderRequest {BidderRequest} - */ -function makeSyncInfo(bidderRequest) { - let {bidderCode} = bidderRequest; let syncMethod = getAllowedSyncMethod(bidderCode); if (syncMethod) { - let res = {}; - deepSetValue(res, 'ext.adk_usersync', syncMethod); - return res; + utils.deepSetValue(req, 'ext.adk_usersync', syncMethod); } -} - -/** - * Builds complete rtb request - * @param imps {Object} Collection of rtb impressions - * @param bidderRequest {BidderRequest} - * @param schain {Object=} Supply chain config - * @return {Object} Complete rtb request - */ -function buildRtbRequest(imps, bidderRequest, schain) { - let fpd = config.getConfig('ortb2') || {}; - - let req = mergeDeep( - makeBaseRequest(bidderRequest, imps, fpd), - makeDevice(fpd), - makeSiteOrApp(bidderRequest, fpd), - makeUser(bidderRequest, fpd), - makeRegulations(bidderRequest), - makeSyncInfo(bidderRequest) - ); if (schain) { - deepSetValue(req, 'source.ext.schain', schain); + utils.deepSetValue(req, 'source.ext.schain', schain); + } + let eids = getExtendedUserIds(bidderRequest); + if (eids) { + utils.deepSetValue(req, 'user.ext.eids', eids); } return req; } @@ -534,24 +424,25 @@ function getLanguage() { /** * Creates site description object */ -function createSite(refInfo, fpd) { - let url = parseUrl(refInfo.referer); +function createSite(refInfo) { + let url = utils.parseUrl(refInfo.referer); let site = { 'domain': url.hostname, 'page': `${url.protocol}://${url.hostname}${url.pathname}` }; - mergeDeep(site, fpd.site); - if (!inIframe() && document.referrer) { + if (self === top && document.referrer) { site.ref = document.referrer; - } else { - delete site.ref; + } + let keywords = document.getElementsByTagName('meta')['keywords']; + if (keywords && keywords.content) { + site.keywords = keywords.content; } return site; } function getExtendedUserIds(bidderRequest) { - let eids = deepAccess(bidderRequest, 'bids.0.userIdAsEids'); - if (isArray(eids)) { + let eids = utils.deepAccess(bidderRequest, 'bids.0.userIdAsEids'); + if (utils.isArray(eids)) { return eids; } } @@ -563,7 +454,7 @@ function getExtendedUserIds(bidderRequest) { function formatAdMarkup(bid) { let adm = bid.adm; if ('nurl' in bid) { - adm += createTrackPixelHtml(`${bid.nurl}&px=1`); + adm += utils.createTrackPixelHtml(`${bid.nurl}&px=1`); } return adm; } @@ -573,8 +464,8 @@ function formatAdMarkup(bid) { */ function validateNativeAdUnit(adUnit) { return validateNativeImageSize(adUnit.image) && validateNativeImageSize(adUnit.icon) && - !deepAccess(adUnit, 'privacyLink.required') && // not supported yet - !deepAccess(adUnit, 'privacyIcon.required'); // not supported yet + !utils.deepAccess(adUnit, 'privacyLink.required') && // not supported yet + !utils.deepAccess(adUnit, 'privacyIcon.required'); // not supported yet } /** @@ -585,9 +476,9 @@ function validateNativeImageSize(img) { return true; } if (img.sizes) { - return isArrayOfNums(img.sizes, 2); + return utils.isArrayOfNums(img.sizes, 2); } - if (isArray(img.aspect_ratios)) { + if (utils.isArray(img.aspect_ratios)) { return img.aspect_ratios.length > 0 && img.aspect_ratios[0].min_height && img.aspect_ratios[0].min_width; } return true; @@ -604,14 +495,14 @@ function buildNativeAd(nativeResp) { javascriptTrackers: jstracker ? [jstracker] : undefined, privacyLink: privacy, }; - _each(assets, asset => { + utils._each(assets, asset => { let assetName = NATIVE_MODEL[asset.id].name; let assetType = NATIVE_MODEL[asset.id].assetType; - nativeAd[assetName] = asset[assetType].text || asset[assetType].value || cleanObj({ + nativeAd[assetName] = asset[assetType].text || asset[assetType].value || utils.cleanObj({ url: asset[assetType].url, width: asset[assetType].w, height: asset[assetType].h }); }); - return cleanObj(nativeAd); + return utils.cleanObj(nativeAd); } diff --git a/modules/adlivetechBidAdapter.md b/modules/adlivetechBidAdapter.md deleted file mode 100644 index 612e669ea1a..00000000000 --- a/modules/adlivetechBidAdapter.md +++ /dev/null @@ -1,61 +0,0 @@ -# Overview - -Module Name: Adlivetech Bidder Adapter -Module Type: Bidder Adapter -Maintainer: grid-tech@themediagrid.com - -# Description - -Module that connects to Grid demand source to fetch bids. -The adapter is GDPR compliant and supports banner and video (instream and outstream). - -# Test Parameters -``` - var adUnits = [ - { - code: 'test-div', - sizes: [[300, 250]], - bids: [ - { - bidder: "adlivetech", - params: { - uid: '1', - bidFloor: 0.5 - } - } - ] - },{ - code: 'test-div', - sizes: [[728, 90]], - bids: [ - { - bidder: "adlivetech", - params: { - uid: 2, - keywords: { - brandsafety: ['disaster'], - topic: ['stress', 'fear'] - } - } - } - ] - }, - { - code: 'test-div', - sizes: [[728, 90]], - mediaTypes: { video: { - context: 'instream', - playerSize: [728, 90], - mimes: ['video/mp4'] - }, - bids: [ - { - bidder: "adlivetech", - params: { - uid: 11 - } - } - ] - } - ]; -``` diff --git a/modules/adlooxAdServerVideo.js b/modules/adlooxAdServerVideo.js index bd715cb34f3..2a61e59b714 100644 --- a/modules/adlooxAdServerVideo.js +++ b/modules/adlooxAdServerVideo.js @@ -9,50 +9,50 @@ import { registerVideoSupport } from '../src/adServerManager.js'; import { command as analyticsCommand, COMMAND } from './adlooxAnalyticsAdapter.js'; import { ajax } from '../src/ajax.js'; -import CONSTANTS from '../src/constants.json'; +import { EVENTS } from '../src/constants.json'; import { targeting } from '../src/targeting.js'; -import { logInfo, isFn, logError, isPlainObject, isStr, isBoolean, deepSetValue, deepClone, timestamp, logWarn } from '../src/utils.js'; +import * as utils from '../src/utils.js'; const MODULE = 'adlooxAdserverVideo'; const URL_VAST = 'https://j.adlooxtracking.com/ads/vast/tag.php'; export function buildVideoUrl(options, callback) { - logInfo(MODULE, 'buildVideoUrl', options); + utils.logInfo(MODULE, 'buildVideoUrl', options); - if (!isFn(callback)) { - logError(MODULE, 'invalid callback'); + if (!utils.isFn(callback)) { + utils.logError(MODULE, 'invalid callback'); return false; } - if (!isPlainObject(options)) { - logError(MODULE, 'missing options'); + if (!utils.isPlainObject(options)) { + utils.logError(MODULE, 'missing options'); return false; } - if (!(options.url_vast === undefined || isStr(options.url_vast))) { - logError(MODULE, 'invalid url_vast options value'); + if (!(options.url_vast === undefined || utils.isStr(options.url_vast))) { + utils.logError(MODULE, 'invalid url_vast options value'); return false; } - if (!(isPlainObject(options.adUnit) || isPlainObject(options.bid))) { - logError(MODULE, "requires either 'adUnit' or 'bid' options value"); + if (!(utils.isPlainObject(options.adUnit) || utils.isPlainObject(options.bid))) { + utils.logError(MODULE, "requires either 'adUnit' or 'bid' options value"); return false; } - if (!isStr(options.url)) { - logError(MODULE, 'invalid url options value'); + if (!utils.isStr(options.url)) { + utils.logError(MODULE, 'invalid url options value'); return false; } - if (!(options.wrap === undefined || isBoolean(options.wrap))) { - logError(MODULE, 'invalid wrap options value'); + if (!(options.wrap === undefined || utils.isBoolean(options.wrap))) { + utils.logError(MODULE, 'invalid wrap options value'); return false; } - if (!(options.blob === undefined || isBoolean(options.blob))) { - logError(MODULE, 'invalid blob options value'); + if (!(options.blob === undefined || utils.isBoolean(options.blob))) { + utils.logError(MODULE, 'invalid blob options value'); return false; } // same logic used in modules/dfpAdServerVideo.js options.bid = options.bid || targeting.getWinningBids(options.adUnit.code)[0]; - deepSetValue(options.bid, 'ext.adloox.video.adserver', true); + utils.deepSetValue(options.bid, 'ext.adloox.video.adserver', true); if (options.wrap !== false) { VASTWrapper(options, callback); @@ -70,11 +70,11 @@ registerVideoSupport('adloox', { function track(options, callback) { callback(options.url); - const bid = deepClone(options.bid); + const bid = utils.deepClone(options.bid); bid.ext.adloox.video.adserver = false; analyticsCommand(COMMAND.TRACK, { - eventType: CONSTANTS.EVENTS.BID_WON, + eventType: EVENTS.BID_WON, args: bid }); } @@ -85,13 +85,13 @@ function VASTWrapper(options, callback) { function process(result) { function getAd(xml) { if (!xml || xml.documentElement.tagName != 'VAST') { - logError(MODULE, 'not a VAST tag, using non-wrapped tracking'); + utils.logError(MODULE, 'not a VAST tag, using non-wrapped tracking'); return; } const ads = xml.querySelectorAll('Ad'); if (!ads.length) { - logError(MODULE, 'no VAST ads, using non-wrapped tracking'); + utils.logError(MODULE, 'no VAST ads, using non-wrapped tracking'); return; } @@ -132,7 +132,7 @@ function VASTWrapper(options, callback) { options.url = toBlob(chain[0]); - const epoch = timestamp() - new Date().getTimezoneOffset() * 60 * 1000; + const epoch = utils.timestamp() - new Date().getTimezoneOffset() * 60 * 1000; const expires0 = options.bid.ttl * 1000 - (epoch - options.bid.responseTimestamp); const expires = Math.max(30 * 1000, expires0); setTimeout(function() { urls.forEach(u => URL.revokeObjectURL(u)) }, expires); @@ -154,7 +154,7 @@ function VASTWrapper(options, callback) { const wrapper = getWrapper(ad); if (wrapper) { if (chain.length > 5) { - logWarn(MODULE, `got wrapped tag at depth ${chain.length}, not continuing`); + utils.logWarn(MODULE, `got wrapped tag at depth ${chain.length}, not continuing`); blobify(); return track(options, callback); } @@ -191,7 +191,7 @@ function VASTWrapper(options, callback) { if (duration != 15) args.push([ 'duration', duration ]); if (skip) args.push([ 'skip', skip ]); - logInfo(MODULE, `processed VAST tag chain of depth ${chain.depth}, running callback`); + utils.logInfo(MODULE, `processed VAST tag chain of depth ${chain.depth}, running callback`); analyticsCommand(COMMAND.URL, { url: (options.url_vast || URL_VAST) + '?', @@ -202,7 +202,7 @@ function VASTWrapper(options, callback) { } function fetch(url, withoutcredentials) { - logInfo(MODULE, `fetching VAST ${url}`); + utils.logInfo(MODULE, `fetching VAST ${url}`); ajax(url, { success: function(responseText, q) { @@ -210,10 +210,10 @@ function VASTWrapper(options, callback) { }, error: function(statusText, q) { if (!withoutcredentials) { - logWarn(MODULE, `unable to download (${statusText}), suspected CORS withCredentials problem, retrying without`); + utils.logWarn(MODULE, `unable to download (${statusText}), suspected CORS withCredentials problem, retrying without`); return fetch(url, true); } - logError(MODULE, `failed to fetch (${statusText}), using non-wrapped tracking`); + utils.logError(MODULE, `failed to fetch (${statusText}), using non-wrapped tracking`); process(); } }, undefined, { withCredentials: !withoutcredentials }); diff --git a/modules/adlooxAnalyticsAdapter.js b/modules/adlooxAnalyticsAdapter.js index 1091b87a22d..cfd01b4434a 100644 --- a/modules/adlooxAnalyticsAdapter.js +++ b/modules/adlooxAnalyticsAdapter.js @@ -6,28 +6,12 @@ import adapterManager from '../src/adapterManager.js'; import adapter from '../src/AnalyticsAdapter.js'; -import {loadExternalScript} from '../src/adloader.js'; -import {auctionManager} from '../src/auctionManager.js'; -import {AUCTION_COMPLETED} from '../src/auction.js'; -import CONSTANTS from '../src/constants.json'; -import {find} from '../src/polyfill.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import { - deepAccess, - getGptSlotInfoForAdUnitCode, - getUniqueIdentifierStr, - insertElement, - isFn, - isNumber, - isPlainObject, - isStr, - logError, - logInfo, - logMessage, - logWarn, - mergeDeep, - parseUrl -} from '../src/utils.js'; +import { loadExternalScript } from '../src/adloader.js'; +import { auctionManager } from '../src/auctionManager.js'; +import { AUCTION_COMPLETED } from '../src/auction.js'; +import { EVENTS } from '../src/constants.json'; +import find from 'core-js-pure/features/array/find.js'; +import * as utils from '../src/utils.js'; const MODULE = 'adlooxAnalyticsAdapter'; @@ -59,19 +43,14 @@ MACRO['targetelt'] = function(b, c) { MACRO['creatype'] = function(b, c) { return b.mediaType == 'video' ? ADLOOX_MEDIATYPE.VIDEO : ADLOOX_MEDIATYPE.DISPLAY; }; -MACRO['pageurl'] = function(b, c) { - const refererInfo = getRefererInfo(); - return (refererInfo.canonicalUrl || refererInfo.referer || '').substr(0, 300).split(/[?#]/)[0]; -}; -MACRO['pbadslot'] = function(b, c) { +MACRO['pbAdSlot'] = function(b, c) { const adUnit = find(auctionManager.getAdUnits(), a => b.adUnitCode === a.code); - return deepAccess(adUnit, 'ortb2Imp.ext.data.pbadslot') || getGptSlotInfoForAdUnitCode(b.adUnitCode).gptSlot || b.adUnitCode; + return utils.deepAccess(adUnit, 'fpd.context.pbAdSlot') || utils.getGptSlotInfoForAdUnitCode(b.adUnitCode).gptSlot || b.adUnitCode; }; -MACRO['pbAdSlot'] = MACRO['pbadslot']; // legacy const PARAMS_DEFAULT = { 'id1': function(b) { return b.adUnitCode }, - 'id2': '%%pbadslot%%', + 'id2': '%%pbAdSlot%%', 'id3': function(b) { return b.bidder }, 'id4': function(b) { return b.adId }, 'id5': function(b) { return b.dealId }, @@ -86,7 +65,7 @@ let analyticsAdapter = Object.assign(adapter({ analyticsType: 'endpoint' }), { track({ eventType, args }) { if (!analyticsAdapter[`handle_${eventType}`]) return; - logInfo(MODULE, 'track', eventType, args); + utils.logInfo(MODULE, 'track', eventType, args); analyticsAdapter[`handle_${eventType}`](args); } @@ -98,45 +77,45 @@ analyticsAdapter.originEnableAnalytics = analyticsAdapter.enableAnalytics; analyticsAdapter.enableAnalytics = function(config) { analyticsAdapter.context = null; - logInfo(MODULE, 'config', config); + utils.logInfo(MODULE, 'config', config); - if (!isPlainObject(config.options)) { - logError(MODULE, 'missing options'); + if (!utils.isPlainObject(config.options)) { + utils.logError(MODULE, 'missing options'); return; } - if (!(config.options.js === undefined || isStr(config.options.js))) { - logError(MODULE, 'invalid js options value'); + if (!(config.options.js === undefined || utils.isStr(config.options.js))) { + utils.logError(MODULE, 'invalid js options value'); return; } - if (!(config.options.toselector === undefined || isFn(config.options.toselector))) { - logError(MODULE, 'invalid toselector options value'); + if (!(config.options.toselector === undefined || utils.isFn(config.options.toselector))) { + utils.logError(MODULE, 'invalid toselector options value'); return; } - if (!isStr(config.options.client)) { - logError(MODULE, 'invalid client options value'); + if (!utils.isStr(config.options.client)) { + utils.logError(MODULE, 'invalid client options value'); return; } - if (!isNumber(config.options.clientid)) { - logError(MODULE, 'invalid clientid options value'); + if (!utils.isNumber(config.options.clientid)) { + utils.logError(MODULE, 'invalid clientid options value'); return; } - if (!isNumber(config.options.tagid)) { - logError(MODULE, 'invalid tagid options value'); + if (!utils.isNumber(config.options.tagid)) { + utils.logError(MODULE, 'invalid tagid options value'); return; } - if (!isNumber(config.options.platformid)) { - logError(MODULE, 'invalid platformid options value'); + if (!utils.isNumber(config.options.platformid)) { + utils.logError(MODULE, 'invalid platformid options value'); return; } - if (!(config.options.params === undefined || isPlainObject(config.options.params))) { - logError(MODULE, 'invalid params options value'); + if (!(config.options.params === undefined || utils.isPlainObject(config.options.params))) { + utils.logError(MODULE, 'invalid params options value'); return; } analyticsAdapter.context = { js: config.options.js || URL_JS, toselector: config.options.toselector || function(bid) { - let code = getGptSlotInfoForAdUnitCode(bid.adUnitCode).divId || bid.adUnitCode; + let code = utils.getGptSlotInfoForAdUnitCode(bid.adUnitCode).divId || bid.adUnitCode; // https://mathiasbynens.be/notes/css-escapes code = code.replace(/^\d/, '\\3$& '); return `#${code}` @@ -148,7 +127,7 @@ analyticsAdapter.enableAnalytics = function(config) { params: [] }; - config.options.params = mergeDeep({}, PARAMS_DEFAULT, config.options.params || {}); + config.options.params = utils.mergeDeep({}, PARAMS_DEFAULT, config.options.params || {}); Object .keys(config.options.params) .forEach(k => { @@ -200,15 +179,15 @@ analyticsAdapter.url = function(url, args, bid) { let n = args.length; while (n-- > 0) { - if (isFn(args[n][1])) { + if (utils.isFn(args[n][1])) { try { args[n][1] = args[n][1](bid); } catch (_) { - logError(MODULE, 'macro', args[n][0], _.message); + utils.logError(MODULE, 'macro', args[n][0], _.message); args[n][1] = `ERROR: ${_.message}`; } } - if (isStr(args[n][1])) { + if (utils.isStr(args[n][1])) { args[n][1] = macros(args[n][1]); } } @@ -216,24 +195,24 @@ analyticsAdapter.url = function(url, args, bid) { return url + a2qs(args); } -analyticsAdapter[`handle_${CONSTANTS.EVENTS.AUCTION_END}`] = function(auctionDetails) { +analyticsAdapter[`handle_${EVENTS.AUCTION_END}`] = function(auctionDetails) { if (!(auctionDetails.auctionStatus == AUCTION_COMPLETED && auctionDetails.bidsReceived.length > 0)) return; - analyticsAdapter[`handle_${CONSTANTS.EVENTS.AUCTION_END}`] = NOOP; + analyticsAdapter[`handle_${EVENTS.AUCTION_END}`] = NOOP; - logMessage(MODULE, 'preloading verification JS'); + utils.logMessage(MODULE, 'preloading verification JS'); - const uri = parseUrl(analyticsAdapter.url(`${analyticsAdapter.context.js}#`)); + const uri = utils.parseUrl(analyticsAdapter.url(`${analyticsAdapter.context.js}#`)); const link = document.createElement('link'); link.setAttribute('href', `${uri.protocol}://${uri.host}${uri.pathname}`); link.setAttribute('rel', 'preload'); link.setAttribute('as', 'script'); - insertElement(link); + utils.insertElement(link); } -analyticsAdapter[`handle_${CONSTANTS.EVENTS.BID_WON}`] = function(bid) { - if (deepAccess(bid, 'ext.adloox.video.adserver')) { - logMessage(MODULE, `measuring '${bid.mediaType}' ad unit code '${bid.adUnitCode}' via Ad Server module`); +analyticsAdapter[`handle_${EVENTS.BID_WON}`] = function(bid) { + if (utils.deepAccess(bid, 'ext.adloox.video.adserver')) { + utils.logMessage(MODULE, `measuring '${bid.mediaType}' ad unit code '${bid.adUnitCode}' via Ad Server module`); return; } @@ -243,11 +222,11 @@ analyticsAdapter[`handle_${CONSTANTS.EVENTS.BID_WON}`] = function(bid) { el = document.querySelector(sl); } catch (_) { } if (!el) { - logWarn(MODULE, `unable to find ad unit code '${bid.adUnitCode}' slot using selector '${sl}' (use options.toselector to change), ignoring`); + utils.logWarn(MODULE, `unable to find ad unit code '${bid.adUnitCode}' slot using selector '${sl}' (use options.toselector to change), ignoring`); return; } - logMessage(MODULE, `measuring '${bid.mediaType}' unit at '${bid.adUnitCode}'`); + utils.logMessage(MODULE, `measuring '${bid.mediaType}' unit at '${bid.adUnitCode}'`); const params = analyticsAdapter.context.params.concat([ [ 'tagid', '%%tagid%%' ], @@ -272,12 +251,11 @@ export default analyticsAdapter; const COMMAND_QUEUE = {}; export const COMMAND = { CONFIG: 'config', - TOSELECTOR: 'toselector', URL: 'url', TRACK: 'track' }; export function command(cmd, data, callback0) { - const cid = getUniqueIdentifierStr(); + const cid = utils.getUniqueIdentifierStr(); const callback = function() { delete COMMAND_QUEUE[cid]; if (callback0) callback0.apply(null, arguments); @@ -288,7 +266,7 @@ export function command(cmd, data, callback0) { function commandProcess(cid) { const { cmd, data, callback } = COMMAND_QUEUE[cid]; - logInfo(MODULE, 'command', cmd, data); + utils.logInfo(MODULE, 'command', cmd, data); switch (cmd) { case COMMAND.CONFIG: @@ -300,9 +278,6 @@ function commandProcess(cid) { }; callback(response); break; - case COMMAND.TOSELECTOR: - callback(analyticsAdapter.context.toselector(data.bid)); - break; case COMMAND.URL: if (data.ids) data.args = data.args.concat(analyticsAdapter.context.params.filter(p => /^id([1-9]|10)$/.test(p[0]))); // not >10 callback(analyticsAdapter.url(data.url, data.args, data.bid)); @@ -312,7 +287,7 @@ function commandProcess(cid) { callback(); // drain queue break; default: - logWarn(MODULE, 'command unknown', cmd); + utils.logWarn(MODULE, 'command unknown', cmd); // do not callback as arguments are unknown and to aid debugging } } diff --git a/modules/adlooxAnalyticsAdapter.md b/modules/adlooxAnalyticsAdapter.md index e21261d0b8d..d4d53a81b3c 100644 --- a/modules/adlooxAnalyticsAdapter.md +++ b/modules/adlooxAnalyticsAdapter.md @@ -2,11 +2,11 @@ Module Name: Adloox Analytics Adapter Module Type: Analytics Adapter - Maintainer: contact@adloox.com + Maintainer: technique@adloox.com # Description -Analytics adapter for adloox.com. Contact contact@adloox.com for information. +Analytics adapter for adloox.com. Contact adops@adloox.com for information. This module can be used to track: @@ -34,7 +34,7 @@ When tracking video you have two options: To view an [example of an Adloox integration](../integrationExamples/gpt/adloox.html): - gulp serve --nolint --notest --modules=gptPreAuction,categoryTranslation,dfpAdServerVideo,rtdModule,instreamTracking,rubiconBidAdapter,spotxBidAdapter,adlooxAnalyticsAdapter,adlooxAdServerVideo,adlooxRtdProvider + gulp serve --nolint --notest --modules=gptPreAuction,categoryTranslation,dfpAdServerVideo,instreamTracking,rubiconBidAdapter,spotxBidAdapter,adlooxAnalyticsAdapter,adlooxAdServerVideo **N.B.** `categoryTranslation` is required by `dfpAdServerVideo` that otherwise causes a JavaScript console warning @@ -44,8 +44,6 @@ Now point your browser at: http://localhost:9999/integrationExamples/gpt/adloox. The example is published publically at: https://storage.googleapis.com/adloox-ads-js-test/prebid.html?pbjs_debug=true -**N.B.** this will show a [CORS error](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors) for the request `https://p.adlooxtracking.com/q?...` that is safe to ignore on the public example page; it is related to the [RTD integration](./adlooxRtdProvider.md) which requires pre-registration of your sites - It is recommended you use [Google Chrome's 'Local Overrides' located in the Developer Tools panel](https://www.trysmudford.com/blog/chrome-local-overrides/) to explore the example without the inconvience of having to run your own web server. #### Pre-built `prebid.js` @@ -63,7 +61,7 @@ You should be able to use this during the QA process of your own internal testin The main Prebid.js documentation is a bit opaque on this but you can use the following to test only Adloox's modules: gulp lint - gulp test-coverage --file 'test/spec/modules/adloox{AnalyticsAdapter,AdServerVideo,RtdProvider}_spec.js' + gulp test-coverage --file 'test/spec/modules/adloox{AnalyticsAdapter,AdServerVideo}_spec.js' gulp view-coverage # Integration @@ -105,8 +103,8 @@ For example, you have a number of reporting breakdown slots available in the for platformid: 0, tagid: 0, params: { - id1: function(b) { return b.adUnitCode }, // do not change when using the Adloox RTD Provider - id2: '%%pbadslot%%', // do not change when using the Adloox RTD Provider + id1: function(b) { return b.adUnitCode }, + id2: '%%pbAdSlot%%', id3: function(b) { return b.bidder }, id4: function(b) { return b.adId }, id5: function(b) { return b.dealId }, @@ -125,9 +123,7 @@ For example, you have a number of reporting breakdown slots available in the for The following macros are available - * `%%pbadslot%%`: [Prebid Ad Slot](https://docs.prebid.org/features/pbAdSlot.html) returns [`AdUnit.code`](https://docs.prebid.org/features/pbAdSlot.html) if set otherwise returns [`AdUnit.code`](https://docs.prebid.org/dev-docs/adunit-reference.html#adunit) - * it is recommended you read the [Prebid Ad Slot section in the Adloox RTD Provider documentation](./adlooxRtdProvider.md#prebid-ad-slot) - * `%%pageurl%%`: [`canonicalUrl`](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-Page-URL) from the [`refererInfo` object](https://docs.prebid.org/dev-docs/bidder-adaptor.html#referrers) otherwise uses `referer` + * `%%pbAdSlot%%`: [Prebid Ad Slot](https://docs.prebid.org/features/pbAdSlot.html) returns [`AdUnit.code`](https://docs.prebid.org/features/pbAdSlot.html) if set otherwise returns [`AdUnit.code`](https://docs.prebid.org/dev-docs/adunit-reference.html#adunit) ### Functions diff --git a/modules/adlooxRtdProvider.js b/modules/adlooxRtdProvider.js deleted file mode 100644 index bb8334ec8fe..00000000000 --- a/modules/adlooxRtdProvider.js +++ /dev/null @@ -1,407 +0,0 @@ -/** - * This module adds the Adloox provider to the real time data module - * This module adds the [Adloox]{@link https://www.adloox.com/} provider to the real time data module - * The {@link module:modules/realTimeData} module is required - * The module will fetch segments from Adloox's server - * @module modules/adlooxRtdProvider - * @requires module:modules/realTimeData - * @requires module:modules/adlooxAnalyticsAdapter - */ - -/* eslint standard/no-callback-literal: "off" */ -/* eslint prebid/validate-imports: "off" */ - -import {command as analyticsCommand, COMMAND} from './adlooxAnalyticsAdapter.js'; -import {config as _config} from '../src/config.js'; -import {submodule} from '../src/hook.js'; -import {ajax} from '../src/ajax.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import { - _each, - deepAccess, - deepSetValue, - getAdUnitSizes, - getGptSlotInfoForAdUnitCode, - isArray, - isBoolean, - isInteger, - isPlainObject, - isStr, - logError, - logInfo, - logWarn, - mergeDeep -} from '../src/utils.js'; -import {includes} from '../src/polyfill.js'; - -const MODULE_NAME = 'adloox'; -const MODULE = `${MODULE_NAME}RtdProvider`; - -const API_ORIGIN = 'https://p.adlooxtracking.com'; -const SEGMENT_HISTORIC = { 'a': 'aud', 'd': 'dis', 'v': 'vid' }; -const SEGMENT_HISTORIC_VALUES = Object.keys(SEGMENT_HISTORIC).map(k => SEGMENT_HISTORIC[k]); - -const ADSERVER_TARGETING_PREFIX = 'adl_'; - -const CREATIVE_WIDTH_MIN = 20; -const CREATIVE_HEIGHT_MIN = 20; -const CREATIVE_AREA_MIN = CREATIVE_WIDTH_MIN * CREATIVE_HEIGHT_MIN; -// try to avoid using IntersectionObserver as it has unbounded (observed multi-second) latency -let intersectionObserver = window == top ? false : undefined; -const intersectionObserverElements = []; -// .map/.findIndex are safe here as they are only used for intersectionObserver -function atf(adUnit, cb) { - analyticsCommand(COMMAND.TOSELECTOR, { bid: { adUnitCode: adUnit.code } }, function(selector) { - const element = document.querySelector(selector); - if (!element) return cb(null); - - if (window.getComputedStyle(element)['display'] == 'none') return cb(NaN); - - try { - // short circuit for cross-origin - if (intersectionObserver) throw false; - - // Google's advice is to collapse slots on no fill but - // we have to cater to clients that grow slots on fill - const rect = (function(rect) { - const sizes = getAdUnitSizes(adUnit); - - if (sizes.length == 0) return false; - // interstitial (0x0, 1x1) - if (sizes.length == 1 && (sizes[0][0] * sizes[0][1]) <= 1) return true; - // try to catch premium slots (coord=0,0) as they will likely bounce into view - if (rect.top <= -window.pageYOffset && rect.left <= -window.pageXOffset && rect.top == rect.bottom) return true; - - // pick the smallest creative size as many publishers will just leave the element unbounded in the vertical - let width = Infinity; - let height = Infinity; - for (let i = 0; i < sizes.length; i++) { - const area = sizes[i][0] * sizes[i][1]; - if (area < CREATIVE_AREA_MIN) continue; - if (area < (width * height)) { - width = sizes[i][0]; - height = sizes[i][1]; - } - } - // we also scale the smallest size to the size of the slot as publishers resize units depending on viewport - const scale = Math.min(1, (rect.right - rect.left) / width); - - return { - left: rect.left, - right: rect.left + Math.max(CREATIVE_WIDTH_MIN, scale * width), - top: rect.top, - bottom: rect.top + Math.max(CREATIVE_HEIGHT_MIN, scale * height) - }; - })(element.getBoundingClientRect()); - - if (rect === false) return cb(NaN); - if (rect === true) return cb(1); - - const W = rect.right - rect.left; - const H = rect.bottom - rect.top; - - if (W * H < CREATIVE_AREA_MIN) return cb(NaN); - - let el; - let win = window; - while (1) { - // https://stackoverflow.com/a/8876069 - const vw = Math.max(win.document.documentElement.clientWidth || 0, win.innerWidth || 0); - const vh = Math.max(win.document.documentElement.clientHeight || 0, win.innerHeight || 0); - - // cut to viewport - rect.left = Math.min(Math.max(rect.left, 0), vw); - rect.right = Math.min(Math.max(rect.right, 0), vw); - rect.top = Math.min(Math.max(rect.top, 0), vh); - rect.bottom = Math.min(Math.max(rect.bottom, 0), vh); - - if (win == top) return cb(((rect.right - rect.left) * (rect.bottom - rect.top)) / (W * H)); - el = win.frameElement; - if (!el) throw false; // cross-origin - win = win.parent; - - // transpose to frame element - const frameElementRect = el.getBoundingClientRect(); - rect.left += frameElementRect.left; - rect.right = Math.min(rect.right + frameElementRect.left, frameElementRect.right); - rect.top += frameElementRect.top; - rect.bottom = Math.min(rect.bottom + frameElementRect.top, frameElementRect.bottom); - } - } catch (_) { - if (intersectionObserver === undefined) { - try { - intersectionObserver = new IntersectionObserver(function(entries) { - entries.forEach(entry => { - const ratio = entry.intersectionRect.width * entry.intersectionRect.height < CREATIVE_AREA_MIN ? NaN : entry.intersectionRatio; - const idx = intersectionObserverElements.findIndex(x => x.element == entry.target); - intersectionObserverElements[idx].cb.forEach(cb => cb(ratio)); - intersectionObserverElements.splice(idx, 1); - intersectionObserver.unobserve(entry.target); - }); - }); - } catch (_) { - intersectionObserver = false; - } - } - if (!intersectionObserver) return cb(null); - const idx = intersectionObserverElements.findIndex(x => x.element == element); - if (idx == -1) { - intersectionObserverElements.push({ element, cb: [ cb ] }); - intersectionObserver.observe(element); - } else { - intersectionObserverElements[idx].cb.push(cb); - } - } - }); -} - -function init(config, userConsent) { - logInfo(MODULE, 'init', config, userConsent); - - if (!isPlainObject(config)) { - logError(MODULE, 'missing config'); - return false; - } - if (config.params === undefined) config.params = {}; - if (!(isPlainObject(config.params))) { - logError(MODULE, 'invalid params'); - return false; - } - if (!(config.params.api_origin === undefined || isStr(config.params.api_origin))) { - logError(MODULE, 'invalid api_origin params value'); - return false; - } - if (!(config.params.imps === undefined || (isInteger(config.params.imps) && config.params.imps > 0))) { - logError(MODULE, 'invalid imps params value'); - return false; - } - if (!(config.params.freqcap_ip === undefined || (isInteger(config.params.freqcap_ip) && config.params.freqcap_ip >= 0))) { - logError(MODULE, 'invalid freqcap_ip params value'); - return false; - } - if (!(config.params.freqcap_ipua === undefined || (isInteger(config.params.freqcap_ipua) && config.params.freqcap_ipua >= 0))) { - logError(MODULE, 'invalid freqcap_ipua params value'); - return false; - } - if (!(config.params.thresholds === undefined || (isArray(config.params.thresholds) && config.params.thresholds.every(x => isInteger(x) && x > 0 && x <= 100)))) { - logError(MODULE, 'invalid thresholds params value'); - return false; - } - if (!(config.params.slotinpath === undefined || isBoolean(config.params.slotinpath))) { - logError(MODULE, 'invalid slotinpath params value'); - return false; - } - // legacy/deprecated configuration code path - if (!(config.params.params === undefined || (isPlainObject(config.params.params) && isInteger(config.params.params.clientid) && isInteger(config.params.params.tagid) && isInteger(config.params.params.platformid)))) { - logError(MODULE, 'invalid subsection params block'); - return false; - } - - config.params.thresholds = config.params.thresholds || [ 50, 60, 70, 80, 90 ]; - - function analyticsConfigCallback(data) { - config = mergeDeep(config.params, data); - } - if (config.params.params) { - logWarn(MODULE, `legacy/deprecated configuration (please migrate to ${MODULE_NAME}AnalyticsAdapter)`); - analyticsConfigCallback(config.params.params); - } else { - analyticsCommand(COMMAND.CONFIG, null, analyticsConfigCallback); - } - - return true; -} - -function getBidRequestData(reqBidsConfigObj, callback, config, userConsent) { - // gptPreAuction runs *after* RTD so pbadslot may not be populated... (╯°□°)╯ ┻━┻ - const adUnits = (reqBidsConfigObj.adUnits || getGlobal().adUnits).map(adUnit => { - let path = deepAccess(adUnit, 'ortb2Imp.ext.data.pbadslot'); - if (!path) path = getGptSlotInfoForAdUnitCode(adUnit.code).gptSlot; - return { - path: path, - unit: adUnit - }; - }).filter(adUnit => !!adUnit.path); - - let response = {}; - function setSegments() { - function val(v, k) { - if (!((SEGMENT_HISTORIC[k] || k == 'atf') && v >= 0)) return v; - return config.params.thresholds.filter(t => t <= v); - } - - const ortb2 = _config.getConfig('ortb2') || {}; - const dataSite = _config.getConfig('ortb2.site.ext.data') || {}; - const dataUser = _config.getConfig('ortb2.user.ext.data') || {}; - - _each(response, (v0, k0) => { - if (k0 == '_') return; - const k = SEGMENT_HISTORIC[k0] || k0; - const v = val(v0, k0); - deepSetValue(k == k0 ? dataUser : dataSite, `${MODULE_NAME}_rtd.${k}`, v); - }); - deepSetValue(dataSite, `${MODULE_NAME}_rtd.ok`, true); - - deepSetValue(ortb2, 'site.ext.data', dataSite); - deepSetValue(ortb2, 'user.ext.data', dataUser); - _config.setConfig({ ortb2 }); - - adUnits.forEach((adUnit, i) => { - _each(response['_'][i], (v0, k0) => { - const k = SEGMENT_HISTORIC[k0] || k0; - const v = val(v0, k0); - deepSetValue(adUnit.unit, `ortb2Imp.ext.data.${MODULE_NAME}_rtd.${k}`, v); - }); - }); - }; - - // mergeDeep does not handle merging deep arrays... (╯°□°)╯ ┻━┻ - function mergeDeep(target, ...sources) { - function emptyValue(v) { - if (isPlainObject(v)) { - return {}; - } else if (isArray(v)) { - return []; - } else { - return undefined; - } - } - - if (!sources.length) return target; - const source = sources.shift(); - - if (isPlainObject(target) && isPlainObject(source)) { - Object.keys(source).forEach(key => { - if (!(key in target)) target[key] = emptyValue(source[key]); - target[key] = target[key] !== undefined ? mergeDeep(target[key], source[key]) : source[key]; - }); - } else if (isArray(target) && isArray(source)) { - source.forEach((v, i) => { - if (!(i in target)) target[i] = emptyValue(v); - target[i] = target[i] !== undefined ? mergeDeep(target[i], v) : v; - }); - } else { - target = source; - } - - return mergeDeep(target, ...sources); - } - - let semaphore = 1; - function semaphoreInc(inc) { - if (semaphore == 0) return; - semaphore += inc; - if (semaphore == 0) { - setSegments() - callback(); - } - } - - const refererInfo = getRefererInfo(); - const args = [ - [ 'v', `pbjs-${getGlobal().version}` ], - [ 'c', config.params.clientid ], - [ 'p', config.params.platformid ], - [ 't', config.params.tagid ], - [ 'imp', config.params.imps ], - [ 'fc_ip', config.params.freqcap_ip ], - [ 'fc_ipua', config.params.freqcap_ipua ], - [ 'pn', (refererInfo.canonicalUrl || refererInfo.referer || '').substr(0, 300).split(/[?#]/)[0] ] - ]; - - if (!adUnits.length) { - logWarn(MODULE, 'no suitable adUnits (missing pbadslot?)'); - } - const atfQueue = []; - adUnits.map((adUnit, i) => { - const ref = [ adUnit.path ]; - if (!config.params.slotinpath) ref.push(adUnit.unit.code); - args.push(['s', ref.join('\t')]); - - semaphoreInc(1); - atfQueue.push(function() { - atf(adUnit.unit, function(x) { - let viewable = document.visibilityState === undefined || document.visibilityState == 'visible'; - try { viewable = viewable && top.document.hasFocus() } catch (_) {} - logInfo(MODULE, `atf code=${adUnit.unit.code} has area=${x}, viewable=${viewable}`); - const atfList = []; atfList[i] = { atf: parseInt(x * 100) }; - response = mergeDeep(response, { _: atfList }); - semaphoreInc(-1); - }); - }); - }); - function atfCb() { - atfQueue.forEach(x => x()); - } - if (document.readyState == 'loading') { - document.addEventListener('DOMContentLoaded', atfCb, false); - } else { - atfCb(); - } - - analyticsCommand(COMMAND.URL, { - url: (config.params.api_origin || API_ORIGIN) + '/q?', - args: args - }, function(url) { - ajax(url, { - success: function(responseText, q) { - try { - if (q.getResponseHeader('content-type') == 'application/json') { - response = mergeDeep(response, JSON.parse(responseText)); - } else { - throw false; - } - } catch (_) { - logError(MODULE, 'unexpected response'); - } - semaphoreInc(-1); - }, - error: function(statusText, q) { - logError(MODULE, 'request failed'); - semaphoreInc(-1); - } - }); - }); -} - -function getTargetingData(adUnitArray, config, userConsent) { - function targetingNormalise(v) { - if (isArray(v) && v.length == 0) return undefined; - if (isBoolean(v)) v = ~~v; - if (!v) return undefined; // empty string and zero - return v; - } - - const dataSite = _config.getConfig(`ortb2.site.ext.data.${MODULE_NAME}_rtd`) || {}; - if (!dataSite.ok) return {}; - - const dataUser = _config.getConfig(`ortb2.user.ext.data.${MODULE_NAME}_rtd`) || {}; - return getGlobal().adUnits.filter(adUnit => includes(adUnitArray, adUnit.code)).reduce((a, adUnit) => { - a[adUnit.code] = {}; - - _each(dataSite, (v0, k) => { - if (includes(SEGMENT_HISTORIC_VALUES, k)) return; // ignore site average viewability - const v = targetingNormalise(v0); - if (v) a[adUnit.code][ADSERVER_TARGETING_PREFIX + k] = v; - }); - - const adUnitSegments = deepAccess(adUnit, `ortb2Imp.ext.data.${MODULE_NAME}_rtd`, {}); - _each(Object.assign({}, dataUser, adUnitSegments), (v0, k) => { - const v = targetingNormalise(v0); - if (v) a[adUnit.code][ADSERVER_TARGETING_PREFIX + k] = v; - }); - - return a; - }, {}); -} - -export const subModuleObj = { - name: MODULE_NAME, - init, - getBidRequestData, - getTargetingData, - atf // used by adlooxRtdProvider_spec.js -}; - -submodule('realTimeData', subModuleObj); diff --git a/modules/adlooxRtdProvider.md b/modules/adlooxRtdProvider.md deleted file mode 100644 index 6c75fbc2d8b..00000000000 --- a/modules/adlooxRtdProvider.md +++ /dev/null @@ -1,105 +0,0 @@ -# Overview - - Module Name: Adloox RTD Provider - Module Type: RTD Provider - Maintainer: contact@adloox.com - -# Description - -RTD provider for adloox.com. Contact contact@adloox.com for information. - -This provider fetches segments and populates the [First Party Data](https://docs.prebid.org/features/firstPartyData.html) attributes, some examples of the segments as described by the Adloox 'Google Publisher Tag Targeting Guidelines' and where they are placed are: - - * Page segments are placed into `ortb2.site.ext.data.adloox_rtd`: - * **`ok`:** boolean (use to capture if our module successfully ran) - * Device segments are placed into `ortb2.user.ext.data.adloox_rtd`: - * **`ivt`:** boolean - * **`ua_old`:** boolean - * **`ip`:** list of strings describing classification of IP (eg. `rfc-special`, `iab-dc`, ...) - * AdUnit segments are placed into `AdUnit.ortb2Imp.ext.data.adloox_rtd`: - * **`{dis,vid,aud}`:** an list of integers describing the likelihood the AdUnit will be visible - * **`atf`:** an list of integers describing the percentage of pixels visible at auction - * measured only once at pre-auction - * usable when the publisher uses the strategy of collapsing ad slots on no-fill - * using the reverse strategy, growing ad slots on fill, invalidates the measurement the position of all content (including the slots) changes post-auction - * works best when your page loads your ad slots have their actual size rendered (ie. not zero height) - * uses the smallest ad unit (above a threshold area of 20x20) supplied by the [publisher to Prebid.js](https://docs.prebid.org/dev-docs/examples/basic-example.html) and measures viewability as if that size to be used - * when used in cross-origin (unfriendly) IFRAME environments the ad slot is directly measured as is (ignoring publisher provided sizes) due to limitations in using [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) - -**N.B.** this provider does not offer or utilise any user orientated data - -These segments are also sent to your ad server but are translated using the following rules: - - * prepended the segment name with `adl_` - * segments are filtered out when their value is either: - * empty string ("") - * zero (`0`) - * boolean `false` - * empty list/array - -For example: - - * `ortb2.site.ext.data.adloox_rtd.ok` is translated to `adl_ok` - * `ortb2.user.ext.data.adloox_rtd.ivt` is translated to `adl_ivt` - * `AdUnit.ortb2Imp.ext.data.adloox_rtd.dis` is translated to `adl_dis` - -## Example - -To view an example of an Adloox integration look at the example provided in the [Adloox Analytics Adapter documentation](./adlooxAnalyticsAdapter.md#example). - -# Integration - -To use this, you *must* also integrate the [Adloox Analytics Adapter](./adlooxAnalyticsAdapter.md) as shown below: - - pbjs.setConfig({ - ... - - realTimeData: { - auctionDelay: 100, // see below for guidance - dataProviders: [ - { - name: 'adloox', - params: { // optional, defaults shown - thresholds: [ 50, 60, 70, 80, 90 ], - slotinpath: false - } - } - ] - }, - - ... - }); - pbjs.enableAnalytics({ - provider: 'adloox', - options: { - client: 'adlooxtest', - clientid: 127, - platformid: 0, - tagid: 0 - } - }); - -You may optionally pass a subsection `params` in the `params` block to the Adloox RTD Provider, these will be passed through to the segment handler as is and as described by the integration guidelines. - -**N.B.** If you pass `params` to the Adloox Analytics Adapter, `id1` (`AdUnit.code`) and `id2` (`%%pbadslot%%`) *must* describe a stable identifier otherwise no usable segments will be served and so they *must not* be changed; if `id1` for your inventory could contain a non-stable random number please consult with us before continuing - -Though our segment technology is fast (less than 10ms) the time it takes for the users device to connect to our service and fetch the segments may not be. For this reason we recommend setting `auctionDelay` no lower than 100ms and if possible you should explore using user-agent sourced information such as [NetworkInformation.{rtt,downlink,...}](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation) to dynamically tune this for each user. - -## Prebid Ad Slot - -To create reliable segments, a stable description for slots on your inventory needs to be supplied which is typically solved by using the [Prebid Ad Slot](https://docs.prebid.org/features/pbAdSlot.html). - -You may use one of two ways to do achieve this: - - * for display inventory [using GPT](https://developers.google.com/publisher-tag/guides/get-started) you may configure Prebid.js to automatically use the [full ad unit path](https://developers.google.com/publisher-tag/reference#googletag.Slot_getAdUnitPath) - 1. include the [`gptPreAuction` module](https://docs.prebid.org/dev-docs/modules/gpt-pre-auction.html) - 1. wrap both `pbjs.setConfig({...})` and `pbjs.enableAnalytics({...})` with `googletag.cmd.push(function() { ... })` - * set `pbadslot` in the [first party data](https://docs.prebid.org/dev-docs/adunit-reference.html#first-party-data) variable `AdUnit.ortb2Imp.ext.data.pbadslot` for all your ad units - -## Timeouts - -It is strongly recommended you increase any [failsafe timeout](https://docs.prebid.org/dev-docs/faq.html#when-starting-out-what-should-my-timeouts-be) you use by at least the value you supply to `auctionDelay` above. - -Adloox recommends you use the following (based on [examples provided on the Prebid.js website](https://docs.prebid.org/dev-docs/examples/basic-example.html)) - - FAILSAFE_TIMEOUT = AUCTION_DELAY + (3 * PREBID_TIMEOUT) diff --git a/modules/admanBidAdapter.js b/modules/admanBidAdapter.js deleted file mode 100644 index 21bcb6cee26..00000000000 --- a/modules/admanBidAdapter.js +++ /dev/null @@ -1,181 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { isFn, deepAccess, logMessage } from '../src/utils.js'; -import {config} from '../src/config.js'; - -const BIDDER_CODE = 'adman'; -const AD_URL = 'https://pub.admanmedia.com/?c=o&m=multi'; -const URL_SYNC = 'https://sync.admanmedia.com'; - -function isBidResponseValid(bid) { - if (!bid.requestId || !bid.cpm || !bid.creativeId || - !bid.ttl || !bid.currency) { - return false; - } - switch (bid['mediaType']) { - case BANNER: - return Boolean(bid.width && bid.height && bid.ad); - case VIDEO: - return Boolean(bid.vastUrl); - case NATIVE: - return Boolean(bid.native && bid.native.title && bid.native.image && bid.native.impressionTrackers); - default: - return false; - } -} - -function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidfloor', 0); - } - - try { - const bidFloor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*', - }); - return bidFloor.floor; - } catch (_) { - return 0 - } -} - -function getUserId(eids, id, source, uidExt) { - if (id) { - var uid = { id }; - if (uidExt) { - uid.ext = uidExt; - } - eids.push({ - source, - uids: [ uid ] - }); - } -} - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO, NATIVE], - - isBidRequestValid: (bid) => { - return Boolean(bid.bidId && bid.params && !isNaN(bid.params.placementId)); - }, - - buildRequests: (validBidRequests = [], bidderRequest) => { - let winTop = window; - let location; - try { - location = new URL(bidderRequest.refererInfo.referer) - winTop = window.top; - } catch (e) { - location = winTop.location; - logMessage(e); - }; - let placements = []; - let request = { - 'deviceWidth': winTop.screen.width, - 'deviceHeight': winTop.screen.height, - 'language': (navigator && navigator.language) ? navigator.language : '', - 'secure': 1, - 'host': location.host, - 'page': location.pathname, - 'placements': placements - }; - request.language.indexOf('-') != -1 && (request.language = request.language.split('-')[0]) - if (bidderRequest) { - if (bidderRequest.uspConsent) { - request.ccpa = bidderRequest.uspConsent; - } - if (bidderRequest.gdprConsent) { - request.gdpr = bidderRequest.gdprConsent - } - } - const len = validBidRequests.length; - - for (let i = 0; i < len; i++) { - let bid = validBidRequests[i]; - let traff = bid.params.traffic || BANNER - const placement = { - placementId: bid.params.placementId, - bidId: bid.bidId, - sizes: bid.mediaTypes && bid.mediaTypes[traff] && bid.mediaTypes[traff].sizes ? bid.mediaTypes[traff].sizes : [], - traffic: traff, - eids: [], - bidFloor: getBidFloor(bid) - } - if (bid.schain) { - placement.schain = bid.schain; - } - if (bid.userId) { - getUserId(placement.eids, bid.userId.uid2 && bid.userId.uid2.id, 'uidapi.com'); - getUserId(placement.eids, bid.userId.lotamePanoramaId, 'lotame.com'); - getUserId(placement.eids, bid.userId.idx, 'idx.lat'); - } - if (traff === VIDEO) { - placement.playerSize = bid.mediaTypes[VIDEO].playerSize; - placement.minduration = bid.mediaTypes[VIDEO].minduration; - placement.maxduration = bid.mediaTypes[VIDEO].maxduration; - placement.mimes = bid.mediaTypes[VIDEO].mimes; - placement.protocols = bid.mediaTypes[VIDEO].protocols; - placement.startdelay = bid.mediaTypes[VIDEO].startdelay; - placement.placement = bid.mediaTypes[VIDEO].placement; - placement.skip = bid.mediaTypes[VIDEO].skip; - placement.skipafter = bid.mediaTypes[VIDEO].skipafter; - placement.minbitrate = bid.mediaTypes[VIDEO].minbitrate; - placement.maxbitrate = bid.mediaTypes[VIDEO].maxbitrate; - placement.delivery = bid.mediaTypes[VIDEO].delivery; - placement.playbackmethod = bid.mediaTypes[VIDEO].playbackmethod; - placement.api = bid.mediaTypes[VIDEO].api; - placement.linearity = bid.mediaTypes[VIDEO].linearity; - } - placements.push(placement); - } - return { - method: 'POST', - url: AD_URL, - data: request - }; - }, - - interpretResponse: (serverResponse) => { - let response = []; - serverResponse = serverResponse.body; - for (let i = 0; i < serverResponse.length; i++) { - let resItem = serverResponse[i]; - if (isBidResponseValid(resItem)) { - const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : []; - resItem.meta = { ...resItem.meta, advertiserDomains }; - - response.push(resItem); - } - } - return response; - }, - - getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { - let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; - let syncUrl = URL_SYNC + `/${syncType}?pbjs=1`; - if (gdprConsent && gdprConsent.consentString) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; - } - } - if (uspConsent && uspConsent.consentString) { - syncUrl += `&ccpa_consent=${uspConsent.consentString}`; - } - - const coppa = config.getConfig('coppa') ? 1 : 0; - syncUrl += `&coppa=${coppa}`; - - return [{ - type: syncType, - url: syncUrl - }]; - } - -}; - -registerBidder(spec); diff --git a/modules/admaruBidAdapter.js b/modules/admaruBidAdapter.js deleted file mode 100644 index 65f62c77e26..00000000000 --- a/modules/admaruBidAdapter.js +++ /dev/null @@ -1,81 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER} from '../src/mediaTypes.js'; - -const ADMARU_ENDPOINT = 'https://p1.admaru.net/AdCall'; -const BIDDER_CODE = 'admaru'; - -const DEFAULT_BID_TTL = 360; - -function parseBid(rawBid, currency) { - const bid = {}; - - bid.cpm = rawBid.price; - bid.impid = rawBid.impid; - bid.requestId = rawBid.impid; - bid.netRevenue = true; - bid.dealId = ''; - bid.creativeId = rawBid.crid; - bid.currency = currency; - bid.ad = rawBid.adm; - bid.width = rawBid.w; - bid.height = rawBid.h; - bid.mediaType = BANNER; - bid.ttl = DEFAULT_BID_TTL; - - return bid; -} - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER], - - isBidRequestValid: function (bid) { - return !!(bid && bid.params && bid.params.pub_id && bid.params.adspace_id); - }, - - buildRequests: function (validBidRequests, bidderRequest) { - return validBidRequests.map(bid => { - const payload = { - pub_id: bid.params.pub_id, - adspace_id: bid.params.adspace_id, - bidderRequestId: bid.bidderRequestId, - bidId: bid.bidId - }; - - return { - method: 'GET', - url: ADMARU_ENDPOINT, - data: payload, - } - }) - }, - - interpretResponse: function (serverResponse, bidRequest) { - const bidResponses = []; - let bid = null; - - if (!serverResponse.hasOwnProperty('body') || !serverResponse.body.hasOwnProperty('seatbid')) { - return bidResponses; - } - - const serverBody = serverResponse.body; - const seatbid = serverBody.seatbid; - - for (let i = 0; i < seatbid.length; i++) { - if (!seatbid[i].hasOwnProperty('bid')) { - continue; - } - - const innerBids = seatbid[i].bid; - for (let j = 0; j < innerBids.length; j++) { - bid = parseBid(innerBids[j], serverBody.cur); - - bidResponses.push(bid); - } - } - - return bidResponses; - } -} - -registerBidder(spec); diff --git a/modules/admaruBidAdapter.md b/modules/admaruBidAdapter.md deleted file mode 100644 index 9985a660ac6..00000000000 --- a/modules/admaruBidAdapter.md +++ /dev/null @@ -1,34 +0,0 @@ -# Overview - -``` -Module Name: Admaru Bidder Adapter -Module Type: Bidder Adapter -Maintainer: support@admaru.com -``` - -# Description - -Module that connects to Admaru demand sources - -# Test Parameters -``` - var adUnits = [ - { - code: 'test-div', - mediaTypes: { - banner: { - sizes: [[300, 250]], // a display size - } - }, - bids: [ - { - bidder: "admaru", - params: { - pub_id: '1234', // string - required - adspace_id: '1234' // string - required - } - } - ] - } - ]; -``` diff --git a/modules/admixerBidAdapter.js b/modules/admixerBidAdapter.js index dfb76a03804..5c01152200e 100644 --- a/modules/admixerBidAdapter.js +++ b/modules/admixerBidAdapter.js @@ -1,15 +1,14 @@ -import { logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; -import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js'; const BIDDER_CODE = 'admixer'; -const ALIASES = ['go2net', 'adblender', 'adsyield', 'futureads']; +const ALIASES = ['go2net', 'adblender', 'adsyield']; const ENDPOINT_URL = 'https://inv-nets.admixer.net/prebid.1.2.aspx'; export const spec = { code: BIDDER_CODE, aliases: ALIASES, - supportedMediaTypes: [BANNER, VIDEO, NATIVE], + supportedMediaTypes: ['banner', 'video'], /** * Determines whether or not the given bid request is valid. */ @@ -20,20 +19,9 @@ export const spec = { * Make a server request from the list of BidRequests. */ buildRequests: function (validRequest, bidderRequest) { - let w; - let docRef; - do { - w = w ? w.parent : window; - try { - docRef = w.document.referrer; - } catch (e) { - break; - } - } while (w !== window.top); const payload = { imps: [], ortb2: config.getConfig('ortb2'), - docReferrer: docRef, }; let endpointUrl; if (bidderRequest) { @@ -58,10 +46,11 @@ export const spec = { Object.keys(bid).forEach(key => imp[key] = bid[key]); payload.imps.push(imp); }); + const payloadString = JSON.stringify(payload); return { - method: 'POST', + method: 'GET', url: endpointUrl || ENDPOINT_URL, - data: payload, + data: `data=${payloadString}`, }; }, /** @@ -73,7 +62,7 @@ export const spec = { const {body: {ads = []} = {}} = serverResponse; ads.forEach((ad) => bidResponses.push(ad)); } catch (e) { - logError(e); + utils.logError(e); } return bidResponses; }, diff --git a/modules/admixerIdSystem.js b/modules/admixerIdSystem.js index 49ffe4f4680..c963f1e5b88 100644 --- a/modules/admixerIdSystem.js +++ b/modules/admixerIdSystem.js @@ -5,7 +5,7 @@ * @requires module:modules/userId */ -import { logError, logInfo } from '../src/utils.js' +import * as utils from '../src/utils.js' import { ajax } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; import {getStorageManager} from '../src/storageManager.js'; @@ -43,13 +43,13 @@ export const admixerIdSubmodule = { getId(config, consentData) { const {e, p, pid} = (config && config.params) || {}; if (!pid || typeof pid !== 'string') { - logError('admixerId submodule requires partner id to be defined'); + utils.logError('admixerId submodule requires partner id to be defined'); return; } const gdpr = (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0; const consentString = gdpr ? consentData.consentString : ''; if (gdpr && !consentString) { - logInfo('Consent string is required to call admixer id.'); + utils.logInfo('Consent string is required to call admixer id.'); return; } const url = `https://inv-nets.admixer.net/cntcm.aspx?ssp=${pid}${e ? `&e=${e}` : ''}${p ? `&p=${p}` : ''}${consentString ? `&cs=${consentString}` : ''}`; @@ -83,7 +83,7 @@ function retrieveVisitorId(url, callback) { } }, error: error => { - logInfo(`admixerId: fetch encountered an error`, error); + utils.logInfo(`admixerId: fetch encountered an error`, error); callback(); } }, undefined, { method: 'GET', withCredentials: true }); diff --git a/modules/adnowBidAdapter.js b/modules/adnowBidAdapter.js index 472d0fdb2e1..7412db8d7b6 100644 --- a/modules/adnowBidAdapter.js +++ b/modules/adnowBidAdapter.js @@ -1,7 +1,7 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE} from '../src/mediaTypes.js'; -import {deepAccess, parseQueryStringParameters, parseSizesInput} from '../src/utils.js'; -import {includes} from '../src/polyfill.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { NATIVE, BANNER } from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; +import includes from 'core-js-pure/features/array/includes.js'; const BIDDER_CODE = 'adnow'; const ENDPOINT = 'https://n.ads3-adnow.com/a'; @@ -61,13 +61,13 @@ export const spec = { }; if (mediaType === BANNER) { - data.sizes = parseSizesInput( + data.sizes = utils.parseSizesInput( req.mediaTypes && req.mediaTypes.banner && req.mediaTypes.banner.sizes ).join('|') } else { data.width = data.height = 200; - let sizes = deepAccess(req, 'mediaTypes.native.image.sizes', []); + let sizes = utils.deepAccess(req, 'mediaTypes.native.image.sizes', []); if (sizes.length > 0) { const size = Array.isArray(sizes[0]) ? sizes[0] : sizes; @@ -81,7 +81,7 @@ export const spec = { return { method: 'GET', url: ENDPOINT, - data: parseQueryStringParameters(data), + data: utils.parseQueryStringParameters(data), options: { withCredentials: false, crossOrigin: true diff --git a/modules/adnuntiusBidAdapter.js b/modules/adnuntiusBidAdapter.js index 9e05ea664d8..68c3e9caffd 100644 --- a/modules/adnuntiusBidAdapter.js +++ b/modules/adnuntiusBidAdapter.js @@ -1,6 +1,6 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; -import { isStr, deepAccess } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; @@ -9,12 +9,12 @@ const ENDPOINT_URL = 'https://ads.adnuntius.delivery/i'; const GVLID = 855; const checkSegment = function (segment) { - if (isStr(segment)) return segment; + if (utils.isStr(segment)) return segment; if (segment.id) return segment.id } const getSegmentsFromOrtb = function (ortb2) { - const userData = deepAccess(ortb2, 'user.data'); + const userData = utils.deepAccess(ortb2, 'user.data'); let segments = []; if (userData) { userData.forEach(userdat => { @@ -27,7 +27,7 @@ const getSegmentsFromOrtb = function (ortb2) { } const handleMeta = function () { - const storage = getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE}) + const storage = getStorageManager(GVLID, 'adnuntius') let adnMeta = null if (storage.localStorageIsEnabled()) { adnMeta = JSON.parse(storage.getDataFromLocalStorage('adn.metaData')) @@ -37,8 +37,7 @@ const handleMeta = function () { } const getUsi = function (meta, ortb2, bidderRequest) { - let usi = (meta !== null && meta.usi) ? meta.usi : false; - if (ortb2 && ortb2.user && ortb2.user.id) { usi = ortb2.user.id } + const usi = (meta !== null) ? meta.usi : false; return usi } @@ -56,21 +55,19 @@ export const spec = { const requests = []; const request = []; const ortb2 = config.getConfig('ortb2'); - const bidderConfig = config.getConfig(); - const adnMeta = handleMeta() const usi = getUsi(adnMeta, ortb2, bidderRequest) const segments = getSegmentsFromOrtb(ortb2); const tzo = new Date().getTimezoneOffset(); - const gdprApplies = deepAccess(bidderRequest, 'gdprConsent.gdprApplies'); - const consentString = deepAccess(bidderRequest, 'gdprConsent.consentString'); + const gdprApplies = utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies'); + const consentString = utils.deepAccess(bidderRequest, 'gdprConsent.consentString'); request.push('tzo=' + tzo) request.push('format=json') if (gdprApplies !== undefined) request.push('consentString=' + consentString); if (segments.length > 0) request.push('segments=' + segments.join(',')); if (usi) request.push('userId=' + usi); - if (bidderConfig.useCookie === false) request.push('noCookies=true') + for (var i = 0; i < validBidRequests.length; i++) { const bid = validBidRequests[i] const network = bid.params.network || 'network'; @@ -115,7 +112,6 @@ export const spec = { height: Number(ad.creativeHeight), creativeId: ad.creativeId, currency: (ad.bid) ? ad.bid.currency : 'EUR', - dealId: ad.dealId || '', meta: { advertiserDomains: (ad.destinationUrls.destination) ? [ad.destinationUrls.destination.split('/')[2]] : [] diff --git a/modules/adnuntiusRtdProvider.js b/modules/adnuntiusRtdProvider.js deleted file mode 100644 index 9234a30aa33..00000000000 --- a/modules/adnuntiusRtdProvider.js +++ /dev/null @@ -1,96 +0,0 @@ - -import { submodule } from '../src/hook.js' -import { logError, logInfo } from '../src/utils.js' -import { ajax } from '../src/ajax.js'; - -import { config as sourceConfig } from '../src/config.js'; - -const GVLID = 855; - -function init(config, userConsent) { - if (!config.params || !config.params.providers) return false - logInfo(userConsent) - return true; -} - -// Make sure that ajax has a function as callback -function prepProvider(provider) { - // Map parameter to something that adnuntius endpoint understands. - const mappedParameters = { - siteId: 's', - userId: 'browserId', - browserId: 'browserId', - folderId: 'folderId' - } - - const tzo = new Date().getTimezoneOffset(); - const URL = ['https://data.adnuntius.com/usr?tzo=' + tzo] - Object.keys(provider).forEach(key => { - URL.push(`${mappedParameters[key]}=${provider[key]}`) - }) - - return new Promise((resolve, reject) => { - ajax(URL.join('&'), { - success: function (res) { - const response = JSON.parse(res) - resolve(response) - }, - error: function (err) { reject(err) } - }); - }); -} - -function setGlobalConfig(config, segments) { - const ortbSegments = { - ortb2: { - user: { - data: [{ - name: 'adnuntius', - segment: segments - }] - } - } - } - if (config.params && config.params.bidders) { - sourceConfig.mergeBidderConfig({ - bidders: config.params.bidders, - config: ortbSegments - }) - } else { - sourceConfig.mergeConfig(ortbSegments) - } -} - -function alterBidRequests(reqBidsConfigObj, callback, config, userConsent) { - const gdpr = userConsent && userConsent.gdpr; - let allowedToRun = true - if (gdpr) { - if (userConsent.gdpr.gdprApplies) { - if (gdpr.gdprApplies && !gdpr.vendorData.vendorConsents[GVLID]) allowedToRun = false; - } - } - if (allowedToRun) { - const providerRequests = config.params.providers.map(provider => prepProvider(provider)) - - Promise.allSettled(providerRequests).then((values) => { - const segments = values.reduce((segments, array) => (array.status === 'fulfilled') ? segments.concat(array.value.segments) : [], []).map(segmentId => ({ id: segmentId })) - setGlobalConfig(config, segments) - callback(); - }) - .catch(err => logError('ADN: err', err)); - } else callback(); -} - -/** @type {RtdSubmodule} */ -export const adnuntiusSubmodule = { - name: 'adnuntius', - init: init, - getBidRequestData: alterBidRequests, - setGlobalConfig: setGlobalConfig, -}; - -export function beforeInit() { - submodule('realTimeData', adnuntiusSubmodule); -} - -beforeInit(); diff --git a/modules/adnuntiusRtdProvider.md b/modules/adnuntiusRtdProvider.md deleted file mode 100644 index e62eba13e2c..00000000000 --- a/modules/adnuntiusRtdProvider.md +++ /dev/null @@ -1,41 +0,0 @@ -### Overview - -The Adnuntius Real Time Data Provider will request segments from adnuntius data, based on what is defined in the realTimeData object. It uses the siteId and userId that a publisher provides. These will have to correspond to a previously uploaded user to Adnuntius Data. - -### Integration - -1. Build the adnuntiusRTD module into the Prebid.js package with: - -``` -gulp build --modules=adnuntiusRtdProvider,... -``` - -2. Use `setConfig` to instruct Prebid.js to initilaize the adnuntiusRtdProvider module, as specified below. - -### Configuration - -``` -var pbjs = pbjs || { que: [] } -pbjs.que.push(function () { - pbjs.setConfig({ - realTimeData: { - auctionDelay: 300, - dataProviders: [ - { - name: 'adnuntius', - waitForIt: true, - params: { - bidders: ['adnuntius'], - providers: [{ - siteId: 'site123', - userId: 'user123' - }] - } - } - ] - }, - }); -}); -``` - -Please reach out to Adnuntius if you need more info about this: prebid@adnuntius.com diff --git a/modules/adoceanBidAdapter.js b/modules/adoceanBidAdapter.js index 0c23f5e3d8a..7ce9c7ae8f2 100644 --- a/modules/adoceanBidAdapter.js +++ b/modules/adoceanBidAdapter.js @@ -1,11 +1,11 @@ -import { _each, parseSizesInput, isStr, isArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'adocean'; function buildEndpointUrl(emiter, payloadMap) { const payload = []; - _each(payloadMap, function(v, k) { + utils._each(payloadMap, function(v, k) { payload.push(k + '=' + encodeURIComponent(v)); }); @@ -26,12 +26,12 @@ function buildRequest(masterBidRequests, masterId, gdprConsent) { const bidIdMap = {}; - _each(masterBidRequests, function(bid, slaveId) { + utils._each(masterBidRequests, function(bid, slaveId) { if (!emiter) { emiter = bid.params.emiter; } - const slaveSizes = parseSizesInput(bid.mediaTypes.banner.sizes).join('_'); + const slaveSizes = utils.parseSizesInput(bid.mediaTypes.banner.sizes).join('_'); const rawSlaveId = bid.params.slaveId.replace('adocean', ''); payload.aosspsizes.push(rawSlaveId + '~' + slaveSizes); @@ -95,7 +95,7 @@ export const spec = { isBidRequestValid: function(bid) { const requiredParams = ['slaveId', 'masterId', 'emiter']; - if (requiredParams.some(name => !isStr(bid.params[name]) || !bid.params[name].length)) { + if (requiredParams.some(name => !utils.isStr(bid.params[name]) || !bid.params[name].length)) { return false; } @@ -106,12 +106,12 @@ export const spec = { const bidRequestsByMaster = {}; let requests = []; - _each(validBidRequests, function(bidRequest) { + utils._each(validBidRequests, function(bidRequest) { assignToMaster(bidRequest, bidRequestsByMaster); }); - _each(bidRequestsByMaster, function(masterRequests, masterId) { - _each(masterRequests, function(instanceRequests) { + utils._each(bidRequestsByMaster, function(masterRequests, masterId) { + utils._each(masterRequests, function(instanceRequests) { requests.push(buildRequest(instanceRequests, masterId, bidderRequest.gdprConsent)); }); }); @@ -122,8 +122,8 @@ export const spec = { interpretResponse: function(serverResponse, bidRequest) { let bids = []; - if (isArray(serverResponse.body)) { - _each(serverResponse.body, function(placementResponse) { + if (utils.isArray(serverResponse.body)) { + utils._each(serverResponse.body, function(placementResponse) { interpretResponse(placementResponse, bidRequest, bids); }); } diff --git a/modules/adomikAnalyticsAdapter.js b/modules/adomikAnalyticsAdapter.js index 40809c59093..5bbee86df54 100644 --- a/modules/adomikAnalyticsAdapter.js +++ b/modules/adomikAnalyticsAdapter.js @@ -1,19 +1,17 @@ import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; -import {logInfo} from '../src/utils.js'; -import {find, findIndex} from '../src/polyfill.js'; +import { logInfo } from '../src/utils.js'; +import find from 'core-js-pure/features/array/find.js'; +import findIndex from 'core-js-pure/features/array/find-index.js'; -// Events used in adomik analytics adapter. +// Events used in adomik analytics adapter const auctionInit = CONSTANTS.EVENTS.AUCTION_INIT; const auctionEnd = CONSTANTS.EVENTS.AUCTION_END; const bidRequested = CONSTANTS.EVENTS.BID_REQUESTED; const bidResponse = CONSTANTS.EVENTS.BID_RESPONSE; const bidWon = CONSTANTS.EVENTS.BID_WON; const bidTimeout = CONSTANTS.EVENTS.BID_TIMEOUT; -const ua = navigator.userAgent; - -var _sampled = true; let adomikAdapter = Object.assign(adapter({}), { @@ -30,13 +28,17 @@ let adomikAdapter = Object.assign(adapter({}), break; case bidResponse: - adomikAdapter.saveBidResponse(args); + adomikAdapter.bucketEvents.push({ + type: 'response', + event: adomikAdapter.buildBidResponse(args) + }); break; case bidWon: - args.id = args.adId; - args.placementCode = args.adUnitCode; - adomikAdapter.sendWonEvent(args); + adomikAdapter.sendWonEvent({ + id: args.adId, + placementCode: args.adUnitCode + }); break; case bidRequested: @@ -45,7 +47,7 @@ let adomikAdapter = Object.assign(adapter({}), type: 'request', event: { bidder: bid.bidder.toUpperCase(), - placementCode: bid.adUnitCode + placementCode: bid.placementCode } }); }); @@ -65,32 +67,13 @@ adomikAdapter.initializeBucketEvents = function() { adomikAdapter.bucketEvents = []; } -adomikAdapter.saveBidResponse = function(args) { - let responseSaved = adomikAdapter.bucketEvents.find((bucketEvent) => - bucketEvent.type == 'response' && bucketEvent.event.id == args.id - ); - if (responseSaved) { return true; } - adomikAdapter.bucketEvents.push({ - type: 'response', - event: adomikAdapter.buildBidResponse(args) - }); -} - -adomikAdapter.maxPartLength = function () { - return (ua.includes(' MSIE ')) ? 1600 : 60000; -}; - adomikAdapter.sendTypedEvent = function() { - let [testId, testValue] = adomikAdapter.getKeyValues(); const groupedTypedEvents = adomikAdapter.buildTypedEvents(); const bulkEvents = { - testId: testId, - testValue: testValue, uid: adomikAdapter.currentContext.uid, ahbaid: adomikAdapter.currentContext.id, hostname: window.location.hostname, - sampling: adomikAdapter.currentContext.sampling, eventsByPlacementCode: groupedTypedEvents.map(function(typedEventsByType) { let sizes = []; const eventKeys = ['request', 'response', 'winner']; @@ -122,11 +105,12 @@ adomikAdapter.sendTypedEvent = function() { const stringBulkEvents = JSON.stringify(bulkEvents) logInfo('Events sent to adomik prebid analytic ' + stringBulkEvents); + // Encode object in base64 const encodedBuf = window.btoa(stringBulkEvents); + // Create final url and split it in 1600 characters max (+endpoint length) const encodedUri = encodeURIComponent(encodedBuf); - const maxLength = adomikAdapter.maxPartLength(); - const splittedUrl = encodedUri.match(new RegExp(`.{1,${maxLength}}`, 'g')); + const splittedUrl = encodedUri.match(/.{1,1600}/g); splittedUrl.forEach((split, i) => { const partUrl = `${split}&id=${adomikAdapter.currentContext.id}&part=${i}&on=${splittedUrl.length - 1}`; @@ -136,18 +120,14 @@ adomikAdapter.sendTypedEvent = function() { }; adomikAdapter.sendWonEvent = function (wonEvent) { - let [testId, testValue] = adomikAdapter.getKeyValues(); - let keyValues = { testId: testId, testValue: testValue }; - let samplingInfo = { sampling: adomikAdapter.currentContext.sampling }; - wonEvent = { ...adomikAdapter.buildBidResponse(wonEvent), ...keyValues, ...samplingInfo }; - - const stringWonEvent = JSON.stringify(wonEvent); - logInfo('Won event sent to adomik prebid analytic ' + stringWonEvent); + const stringWonEvent = JSON.stringify(wonEvent) + logInfo('Won event sent to adomik prebid analytic ' + wonEvent); + // Encode object in base64 const encodedBuf = window.btoa(stringWonEvent); const encodedUri = encodeURIComponent(encodedBuf); const img = new Image(1, 1); - img.src = `https://${adomikAdapter.currentContext.url}/?q=${encodedUri}&id=${adomikAdapter.currentContext.id}&won=true`; + img.src = `https://${adomikAdapter.currentContext.url}/?q=${encodedUri}&id=${adomikAdapter.currentContext.id}&won=true` } adomikAdapter.buildBidResponse = function (bid) { @@ -209,49 +189,22 @@ adomikAdapter.buildTypedEvents = function () { return groupedTypedEvents; } -adomikAdapter.getKeyValues = function () { - let preventTest = sessionStorage.getItem(window.location.hostname + '_NoAdomikTest') - let inScope = sessionStorage.getItem(window.location.hostname + '_AdomikTestInScope') - let keyValues = JSON.parse(sessionStorage.getItem(window.location.hostname + '_AdomikTest')) - let testId; - let testValue; - if (typeof (keyValues) === 'object' && keyValues != undefined && !preventTest && inScope) { - testId = keyValues.testId - testValue = keyValues.testOptionLabel - } - return [testId, testValue] -} - -adomikAdapter.enable = function(options) { - adomikAdapter.currentContext = { - uid: options.id, - url: options.url, - id: '', - timeouted: false, - sampling: options.sampling - } - logInfo('Adomik Analytics enabled with config', options); - adomikAdapter.adapterEnableAnalytics(options); -}; - -adomikAdapter.checkOptions = function(options) { - if (typeof options !== 'undefined') { - if (options.id && options.url) { adomikAdapter.enable(options); } else { logInfo('Adomik Analytics disabled because id and/or url is missing from config', options); } - } else { logInfo('Adomik Analytics disabled because config is missing'); } -}; - -adomikAdapter.checkSampling = function(options) { - _sampled = typeof options === 'undefined' || - typeof options.sampling === 'undefined' || - (options.sampling > 0 && Math.random() < parseFloat(options.sampling)); - if (_sampled) { adomikAdapter.checkOptions(options) } else { logInfo('Adomik Analytics ignored for sampling', options.sampling); } -}; - adomikAdapter.adapterEnableAnalytics = adomikAdapter.enableAnalytics; -adomikAdapter.enableAnalytics = function ({ provider, options }) { - logInfo('Adomik Analytics enableAnalytics', provider); - adomikAdapter.checkSampling(options); +adomikAdapter.enableAnalytics = function (config) { + adomikAdapter.currentContext = {}; + + const initOptions = config.options; + if (initOptions) { + adomikAdapter.currentContext = { + uid: initOptions.id, + url: initOptions.url, + id: '', + timeouted: false, + } + logInfo('Adomik Analytics enabled with config', initOptions); + adomikAdapter.adapterEnableAnalytics(config); + } }; adapterManager.registerAnalyticsAdapter({ diff --git a/modules/adotBidAdapter.js b/modules/adotBidAdapter.js index ac49f7ae32d..ddd9531eb43 100644 --- a/modules/adotBidAdapter.js +++ b/modules/adotBidAdapter.js @@ -1,238 +1,313 @@ import {Renderer} from '../src/Renderer.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {isArray, isBoolean, isFn, isPlainObject, isStr, logError, replaceAuctionPrice} from '../src/utils.js'; -import {find} from '../src/polyfill.js'; -import {config} from '../src/config.js'; -import { OUTSTREAM } from '../src/video.js'; +import {isStr, isArray, isNumber, isPlainObject, isBoolean, logError, replaceAuctionPrice} from '../src/utils.js'; +import find from 'core-js-pure/features/array/find.js'; +import { config } from '../src/config.js'; -const BIDDER_CODE = 'adot'; -const ADAPTER_VERSION = 'v2.0.0'; +const ADAPTER_VERSION = 'v1.0.0'; const BID_METHOD = 'POST'; const BIDDER_URL = 'https://dsp.adotmob.com/headerbidding{PUBLISHER_PATH}/bidrequest'; -const REQUIRED_VIDEO_PARAMS = ['mimes', 'protocols']; -const DOMAIN_REGEX = new RegExp('//([^/]*)'); const FIRST_PRICE = 1; -const IMP_BUILDER = { banner: buildBanner, video: buildVideo, native: buildNative }; +const NET_REVENUE = true; +// eslint-disable-next-line no-template-curly-in-string +const AUCTION_PRICE = '${AUCTION_PRICE}'; +const TTL = 10; + +const SUPPORTED_VIDEO_CONTEXTS = ['instream', 'outstream']; +const SUPPORTED_INSTREAM_CONTEXTS = ['pre-roll', 'mid-roll', 'post-roll']; +const SUPPORTED_VIDEO_MIMES = ['video/mp4']; +const BID_SUPPORTED_MEDIA_TYPES = ['banner', 'video', 'native']; + +const DOMAIN_REGEX = new RegExp('//([^/]*)'); +const OUTSTREAM_VIDEO_PLAYER_URL = 'https://adserver.adotmob.com/video/player.min.js'; + const NATIVE_PLACEMENTS = { - title: { id: 1, name: 'title' }, - icon: { id: 2, type: 1, name: 'img' }, - image: { id: 3, type: 3, name: 'img' }, - sponsoredBy: { id: 4, name: 'data', type: 1 }, - body: { id: 5, name: 'data', type: 2 }, - cta: { id: 6, type: 12, name: 'data' } + title: {id: 1, name: 'title'}, + icon: {id: 2, type: 1, name: 'img'}, + image: {id: 3, type: 3, name: 'img'}, + sponsoredBy: {id: 4, name: 'data', type: 1}, + body: {id: 5, name: 'data', type: 2}, + cta: {id: 6, type: 12, name: 'data'} }; -const NATIVE_ID_MAPPING = { 1: 'title', 2: 'icon', 3: 'image', 4: 'sponsoredBy', 5: 'body', 6: 'cta' }; -const OUTSTREAM_VIDEO_PLAYER_URL = 'https://adserver.adotmob.com/video/player.min.js'; -const BID_RESPONSE_NET_REVENUE = true; -const BID_RESPONSE_TTL = 10; -const DEFAULT_CURRENCY = 'USD'; - -/** - * Parse string in plain object - * - * @param {string} data - * @returns {object|null} Parsed object or null - */ -function tryParse(data) { - try { - return JSON.parse(data); - } catch (err) { - logError(err); - return null; +const NATIVE_ID_MAPPING = {1: 'title', 2: 'icon', 3: 'image', 4: 'sponsoredBy', 5: 'body', 6: 'cta'}; +const NATIVE_PRESET_FORMATTERS = { + image: formatNativePresetImage +} + +function isNone(value) { + return (value === null) || (value === undefined); +} + +function groupBy(values, key) { + const groups = values.reduce((acc, value) => { + const groupId = value[key]; + + if (!acc[groupId]) acc[groupId] = []; + acc[groupId].push(value); + + return acc; + }, {}); + + return Object + .keys(groups) + .map(id => ({id, key, values: groups[id]})); +} + +function validateMediaTypes(mediaTypes, allowedMediaTypes) { + if (!isPlainObject(mediaTypes)) return false; + if (!allowedMediaTypes.some(mediaType => mediaType in mediaTypes)) return false; + + if (isBanner(mediaTypes)) { + if (!validateBanner(mediaTypes.banner)) return false; } + + if (isVideo(mediaTypes)) { + if (!validateVideo(mediaTypes.video)) return false; + } + + return true; } -/** - * Extract domain from given url - * - * @param {string} url - * @returns {string|null} Extracted domain - */ -function extractDomainFromURL(url) { - if (!url || !isStr(url)) return null; - const domain = url.match(DOMAIN_REGEX); - if (isArray(domain) && domain.length === 2) return domain[1]; - return null; +function isBanner(mediaTypes) { + return isPlainObject(mediaTypes) && isPlainObject(mediaTypes.banner); } -/** - * Create and return site OpenRtb object from given bidderRequest - * - * @param {BidderRequest} bidderRequest - * @returns {Site|null} Formatted Site OpenRtb object or null - */ -function getOpenRTBSiteObject(bidderRequest) { - if (!bidderRequest || !bidderRequest.refererInfo) return null; +function isVideo(mediaTypes) { + return isPlainObject(mediaTypes) && 'video' in mediaTypes; +} - const domain = extractDomainFromURL(bidderRequest.refererInfo.referer); - const publisherId = config.getConfig('adot.publisherId'); +function validateBanner(banner) { + return isPlainObject(banner) && + isArray(banner.sizes) && + (banner.sizes.length > 0) && + banner.sizes.every(validateMediaSizes); +} - if (!domain) return null; +function validateVideo(video) { + if (!isPlainObject(video)) return false; + if (!isStr(video.context)) return false; + if (SUPPORTED_VIDEO_CONTEXTS.indexOf(video.context) === -1) return false; + + if (!video.playerSize) return true; + if (!isArray(video.playerSize)) return false; + + return video.playerSize.every(validateMediaSizes); +} + +function validateMediaSizes(mediaSize) { + return isArray(mediaSize) && + (mediaSize.length === 2) && + mediaSize.every(size => (isNumber(size) && size >= 0)); +} + +function validateParameters(parameters, adUnit) { + if (isVideo(adUnit.mediaTypes)) { + if (!isPlainObject(parameters)) return false; + if (!isPlainObject(adUnit.mediaTypes.video)) return false; + if (!validateVideoParameters(parameters.video, adUnit)) return false; + } + + return true; +} + +function validateVideoParameters(videoParams, adUnit) { + const video = adUnit.mediaTypes.video; + + if (!video) return false; + + if (!isArray(video.mimes)) return false; + if (video.mimes.length === 0) return false; + if (!video.mimes.every(isStr)) return false; + + if (video.minDuration && !isNumber(video.minDuration)) return false; + if (video.maxDuration && !isNumber(video.maxDuration)) return false; + + if (!isArray(video.protocols)) return false; + if (video.protocols.length === 0) return false; + if (!video.protocols.every(isNumber)) return false; + + if (isInstream(video)) { + if (!videoParams.instreamContext) return false; + if (SUPPORTED_INSTREAM_CONTEXTS.indexOf(videoParams.instreamContext) === -1) return false; + } + + return true; +} + +function validateServerRequest(serverRequest) { + return isPlainObject(serverRequest) && + isPlainObject(serverRequest.data) && + isArray(serverRequest.data.imp) && + isPlainObject(serverRequest._adot_internal) && + isArray(serverRequest._adot_internal.impressions) +} +function createServerRequestFromAdUnits(adUnits, bidRequestId, adUnitContext) { + const publisherPath = config.getConfig('adot.publisherPath') === undefined ? '' : '/' + config.getConfig('adot.publisherPath'); return { - page: bidderRequest.refererInfo.referer, - domain: domain, - name: domain, - publisher: { - id: publisherId - } - }; + method: BID_METHOD, + url: BIDDER_URL.replace('{PUBLISHER_PATH}', publisherPath), + data: generateBidRequestsFromAdUnits(adUnits, bidRequestId, adUnitContext), + _adot_internal: generateAdotInternal(adUnits) + } +} + +function generateAdotInternal(adUnits) { + const impressions = adUnits.reduce((acc, adUnit) => { + const {bidId, mediaTypes, adUnitCode, params} = adUnit; + const base = {bidId, adUnitCode, container: params.video && params.video.container}; + + const imps = Object + .keys(mediaTypes) + .reduce((acc, mediaType, index) => { + const data = mediaTypes[mediaType]; + const impressionId = `${bidId}_${index}`; + + if (mediaType !== 'banner') return acc.concat({...base, impressionId}); + + const bannerImps = data.sizes.map((item, i) => ({...base, impressionId: `${impressionId}_${i}`})); + + return acc.concat(bannerImps); + }, []); + + return acc.concat(imps); + }, []); + + return {impressions}; } -/** - * Create and return Device OpenRtb object - * - * @returns {Device} Formatted Device OpenRtb object or null - */ -function getOpenRTBDeviceObject() { - return { ua: navigator.userAgent, language: navigator.language }; -} - -/** - * Create and return User OpenRtb object - * - * @param {BidderRequest} bidderRequest - * @returns {User|null} Formatted User OpenRtb object or null - */ -function getOpenRTBUserObject(bidderRequest) { - if (!bidderRequest || !bidderRequest.gdprConsent || !isStr(bidderRequest.gdprConsent.consentString)) return null; - return { ext: { consent: bidderRequest.gdprConsent.consentString } }; -} - -/** - * Create and return Regs OpenRtb object - * - * @param {BidderRequest} bidderRequest - * @returns {Regs|null} Formatted Regs OpenRtb object or null - */ -function getOpenRTBRegsObject(bidderRequest) { - if (!bidderRequest || !bidderRequest.gdprConsent || !isBoolean(bidderRequest.gdprConsent.gdprApplies)) return null; - return { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies } }; -} - -/** - * Create and return Ext OpenRtb object - * - * @param {BidderRequest} bidderRequest - * @returns {Ext|null} Formatted Ext OpenRtb object or null - */ -function getOpenRTBExtObject() { +function generateBidRequestsFromAdUnits(adUnits, bidRequestId, adUnitContext) { return { - adot: { adapter_version: ADAPTER_VERSION }, - should_use_gzip: true + id: bidRequestId, + imp: adUnits.reduce(generateImpressionsFromAdUnit, []), + site: generateSiteFromAdUnitContext(adUnitContext), + device: getDeviceInfo(), + user: getUserInfoFromAdUnitContext(adUnitContext), + regs: getRegulationFromAdUnitContext(adUnitContext), + at: FIRST_PRICE, + ext: generateBidRequestExtension() }; } -/** - * Return MediaType from MediaTypes object - * - * @param {MediaType} mediaTypes Prebid MediaTypes - * @returns {string|null} Mediatype or null if not found - */ -function getMediaType(mediaTypes) { - if (mediaTypes.banner) return 'banner'; - if (mediaTypes.video) return 'video'; - if (mediaTypes.native) return 'native'; - return null; +function generateImpressionsFromAdUnit(acc, adUnit) { + const {bidId, mediaTypes, params} = adUnit; + const {placementId} = params; + const pmp = {}; + const ext = {placementId}; + + if (placementId) pmp.deals = [{id: placementId}] + + const imps = Object + .keys(mediaTypes) + .reduce((acc, mediaType, index) => { + const data = mediaTypes[mediaType]; + const impId = `${bidId}_${index}`; + + if (mediaType === 'banner') return acc.concat(generateBannerFromAdUnit(impId, data, params)); + if (mediaType === 'video') return acc.concat({id: impId, video: generateVideoFromAdUnit(data, params), pmp, ext}); + if (mediaType === 'native') return acc.concat({id: impId, native: generateNativeFromAdUnit(data), pmp, ext}); + }, []); + + return acc.concat(imps); +} + +function isImpressionAVideo(impression) { + return isPlainObject(impression) && isPlainObject(impression.video); } -/** - * Build OpenRtb imp banner from given bidderRequest and media - * - * @param {Banner} banner MediaType Banner Object - * @param {BidderRequest} bidderRequest - * @returns {OpenRtbBanner} OpenRtb banner object - */ -function buildBanner(banner, bidderRequest) { - const pos = bidderRequest.position || 0; - const format = (banner.sizes || []).map(([w, h]) => ({ w, h })); - return { format, pos }; -} - -/** - * Build object with w and h value depending on given video media - * - * @param {Video} video MediaType Video Object - * @returns {Object} Size as { w: number; h: number } - */ -function getVideoSize(video) { - const sizes = video.playerSize || []; - const format = sizes.length > 0 ? sizes[0] : []; +function generateBannerFromAdUnit(impId, data, params) { + const {position, placementId} = params; + const pos = position || 0; + const pmp = {}; + const ext = {placementId}; - return { - w: format[0] || null, - h: format[1] || null - }; + if (placementId) pmp.deals = [{id: placementId}] + + return data.sizes.map(([w, h], index) => ({id: `${impId}_${index}`, banner: {format: [{w, h}], w, h, pos}, pmp, ext})); } -/** - * Build OpenRtb imp video from given bidderRequest and media - * - * @param {Video} video MediaType Video Object - * @returns {OpenRtbVideo} OpenRtb video object - */ -function buildVideo(video) { - const { w, h } = getVideoSize(video); +function generateVideoFromAdUnit(data, params) { + const {playerSize} = data; + const video = data + + const hasPlayerSize = isArray(playerSize) && playerSize.length > 0; + const {minDuration, maxDuration, protocols} = video; + + const size = {width: hasPlayerSize ? playerSize[0][0] : null, height: hasPlayerSize ? playerSize[0][1] : null}; + const duration = {min: isNumber(minDuration) ? minDuration : null, max: isNumber(maxDuration) ? maxDuration : null}; + const startdelay = computeStartDelay(data, params); return { - api: video.api, - w, - h, + mimes: SUPPORTED_VIDEO_MIMES, + skip: video.skippable || 0, + w: size.width, + h: size.height, + startdelay: startdelay, linearity: video.linearity || null, - mimes: video.mimes, - minduration: video.minduration, - maxduration: video.maxduration, - placement: video.placement, - playbackmethod: video.playbackmethod, - pos: video.position || 0, - protocols: video.protocols, - skip: video.skip || 0, - startdelay: video.startdelay + minduration: duration.min, + maxduration: duration.max, + protocols, + api: getApi(protocols), + format: hasPlayerSize ? playerSize.map(s => { + return {w: s[0], h: s[1]}; + }) : null, + pos: video.position || 0 }; } -/** - * Check if given Native Media is an asset of type Image. - * - * Return default native assets if given media is an asset - * Return given native assets if given media is not an asset - * - * @param {NativeMedia} native Native Mediatype - * @returns {OpenRtbNativeAssets} - */ -function cleanNativeMedia(native) { - if (native.type !== 'image') return native; +function getApi(protocols) { + let defaultValue = [2]; + let listProtocols = [ + {key: 'VPAID_1_0', value: 1}, + {key: 'VPAID_2_0', value: 2}, + {key: 'MRAID_1', value: 3}, + {key: 'ORMMA', value: 4}, + {key: 'MRAID_2', value: 5}, + {key: 'MRAID_3', value: 6}, + ]; + if (protocols) { + return listProtocols.filter(p => { + return protocols.indexOf(p.key) !== -1; + }).map(p => p.value) + } else { + return defaultValue; + } +} + +function isInstream(video) { + return isPlainObject(video) && (video.context === 'instream'); +} - return { - image: { required: true, sizes: native.sizes }, - title: { required: true }, - sponsoredBy: { required: true }, - body: { required: false }, - cta: { required: false }, - icon: { required: false } - }; +function isOutstream(video) { + return isPlainObject(video) && (video.startdelay === null) } -/** - * Build Native OpenRtb Imp from Native Mediatype - * - * @param {NativeMedia} native Native Mediatype - * @returns {OpenRtbNative} - */ -function buildNative(native) { - native = cleanNativeMedia(native); +function computeStartDelay(data, params) { + if (isInstream(data)) { + if (params.video.instreamContext === 'pre-roll') return 0; + if (params.video.instreamContext === 'mid-roll') return -1; + if (params.video.instreamContext === 'post-roll') return -2; + } + + return null; +} - const assets = Object.keys(native) - .reduce((nativeAssets, assetKey) => { - const asset = native[assetKey]; - const assetInfo = NATIVE_PLACEMENTS[assetKey]; +function generateNativeFromAdUnit(data) { + const {type} = data; + const presetFormatter = type && NATIVE_PRESET_FORMATTERS[data.type]; + const nativeFields = presetFormatter ? presetFormatter(data) : data; - if (!assetInfo) return nativeAssets; + const assets = Object + .keys(nativeFields) + .reduce((acc, placement) => { + const placementData = nativeFields[placement]; + const assetInfo = NATIVE_PLACEMENTS[placement]; - const { id, name, type } = assetInfo; - const { required, len, sizes = [] } = asset; + if (!assetInfo) return acc; + const {id, name, type} = assetInfo; + const {required, len, sizes = []} = placementData; let wmin; let hmin; @@ -244,165 +319,249 @@ function buildNative(native) { hmin = sizes[1]; } - const newAsset = {}; + const content = {}; - if (type) newAsset.type = type; - if (len) newAsset.len = len; - if (wmin) newAsset.wmin = wmin; - if (hmin) newAsset.hmin = hmin; + if (type) content.type = type; + if (len) content.len = len; + if (wmin) content.wmin = wmin; + if (hmin) content.hmin = hmin; - nativeAssets.push({ id, required, [name]: newAsset }); + acc.push({id, required, [name]: content}); - return nativeAssets; + return acc; }, []); - return { request: JSON.stringify({ assets }) }; + return { + request: JSON.stringify({assets}) + }; } -/** - * Build OpenRtb Imp object from given Adunit and Context - * - * @param {AdUnit} adUnit PrebidJS Adunit - * @param {BidderRequest} bidderRequest PrebidJS Bidder Request - * @returns {Imp} OpenRtb Impression - */ -function buildImpFromAdUnit(adUnit, bidderRequest) { - const { bidId, mediaTypes, params, adUnitCode } = adUnit; - const mediaType = getMediaType(mediaTypes); +function formatNativePresetImage(data) { + const sizes = data.sizes; - if (!mediaType) return null; + return { + image: { + required: true, + sizes + }, + title: { + required: true + }, + sponsoredBy: { + required: true + }, + body: { + required: false + }, + cta: { + required: false + }, + icon: { + required: false + } + }; +} - const media = IMP_BUILDER[mediaType](mediaTypes[mediaType], bidderRequest, adUnit) - const currency = config.getConfig('currency.adServerCurrency') || DEFAULT_CURRENCY; - const bidfloor = getMainFloor(adUnit, media.format, mediaType, currency); +function generateSiteFromAdUnitContext(adUnitContext) { + if (!adUnitContext || !adUnitContext.refererInfo) return null; + + const domain = extractSiteDomainFromURL(adUnitContext.refererInfo.referer); + const publisherId = config.getConfig('adot.publisherId'); + + if (!domain) return null; + + return { + page: adUnitContext.refererInfo.referer, + domain: domain, + name: domain, + publisher: { + id: publisherId + } + }; +} + +function extractSiteDomainFromURL(url) { + if (!url || !isStr(url)) return null; + + const domain = url.match(DOMAIN_REGEX); + + if (isArray(domain) && domain.length === 2) return domain[1]; + + return null; +} + +function getDeviceInfo() { + return {ua: navigator.userAgent, language: navigator.language}; +} + +function getUserInfoFromAdUnitContext(adUnitContext) { + if (!adUnitContext || !adUnitContext.gdprConsent) return null; + if (!isStr(adUnitContext.gdprConsent.consentString)) return null; return { - id: bidId, ext: { - placementId: params.placementId, - adUnitCode, - container: params.video && params.video.container - }, - [mediaType]: media, - bidfloorcur: currency, - bidfloor + consent: adUnitContext.gdprConsent.consentString + } }; } -/** - * Return if given video is Valid. - * A video is defined as valid if it contains all required fields - * - * @param {VideoMedia} video - * @returns {boolean} - */ -function isValidVideo(video) { - if (REQUIRED_VIDEO_PARAMS.some((param) => video[param] === undefined)) return false; - return true; +function getRegulationFromAdUnitContext(adUnitContext) { + if (!adUnitContext || !adUnitContext.gdprConsent) return null; + if (!isBoolean(adUnitContext.gdprConsent.gdprApplies)) return null; + + return { + ext: { + gdpr: adUnitContext.gdprConsent.gdprApplies + } + }; } -/** - * Return if given bid is Valid. - * A bid is defined as valid if it media is a valid video or other media - * - * @param {Bid} bid - * @returns {boolean} - */ -function isBidRequestValid(bid) { - const video = bid.mediaTypes.video; - return !video || isValidVideo(video); -} - -/** - * Build OpenRtb request from Prebid AdUnits and Bidder request - * - * @param {Array} adUnits Array of PrebidJS Adunit - * @param {BidderRequest} bidderRequest PrebidJS BidderRequest - * @param {string} requestId Request ID - * - * @returns {OpenRTBBidRequest} OpenRTB bid request - */ -function buildBidRequest(adUnits, bidderRequest, requestId) { - const data = { - id: requestId, - imp: adUnits.map((adUnit) => buildImpFromAdUnit(adUnit, bidderRequest)).filter((item) => !!item), - site: getOpenRTBSiteObject(bidderRequest), - device: getOpenRTBDeviceObject(), - user: getOpenRTBUserObject(bidderRequest), - regs: getOpenRTBRegsObject(bidderRequest), - ext: getOpenRTBExtObject(), - at: FIRST_PRICE +function generateBidRequestExtension() { + return { + adot: {adapter_version: ADAPTER_VERSION}, + should_use_gzip: true }; - return data; -} - -/** - * Build PrebidJS Ajax request - * - * @param {Array} adUnits Array of PrebidJS Adunit - * @param {BidderRequest} bidderRequest PrebidJS BidderRequest - * @param {string} bidderUrl Adot Bidder URL - * @param {string} requestId Request ID - * @returns - */ -function buildAjaxRequest(adUnits, bidderRequest, bidderUrl, requestId) { +} + +function validateServerResponse(serverResponse) { + return isPlainObject(serverResponse) && + isPlainObject(serverResponse.body) && + isStr(serverResponse.body.cur) && + isArray(serverResponse.body.seatbid); +} + +function seatBidsToAds(seatBid, bidResponse, serverRequest) { + return seatBid.bid + .filter(bid => validateBids(bid, serverRequest)) + .map(bid => generateAdFromBid(bid, bidResponse, serverRequest)); +} + +function validateBids(bid, serverRequest) { + if (!isPlainObject(bid)) return false; + if (!isStr(bid.impid)) return false; + if (!isStr(bid.crid)) return false; + if (!isNumber(bid.price)) return false; + + if (!isPlainObject(bid.ext)) return false; + if (!isPlainObject(bid.ext.adot)) return false; + if (!isStr(bid.ext.adot.media_type)) return false; + if (BID_SUPPORTED_MEDIA_TYPES.indexOf(bid.ext.adot.media_type) === -1) return false; + + if (!bid.adm && !bid.nurl) return false; + if (bid.adm) { + if (!isStr(bid.adm)) return false; + if (bid.adm.indexOf(AUCTION_PRICE) === -1) return false; + } + if (bid.nurl) { + if (!isStr(bid.nurl)) return false; + if (bid.nurl.indexOf(AUCTION_PRICE) === -1) return false; + } + + if (isBidABanner(bid)) { + if (!isNumber(bid.h)) return false; + if (!isNumber(bid.w)) return false; + } + if (isBidAVideo(bid)) { + if (!(isNone(bid.h) || isNumber(bid.h))) return false; + if (!(isNone(bid.w) || isNumber(bid.w))) return false; + } + + const impression = getImpressionData(serverRequest, bid.impid); + + if (!isPlainObject(impression.openRTB)) return false; + if (!isPlainObject(impression.internal)) return false; + if (!isStr(impression.internal.adUnitCode)) return false; + + if (isBidABanner(bid)) { + if (!isPlainObject(impression.openRTB.banner)) return false; + } + if (isBidAVideo(bid)) { + if (!isPlainObject(impression.openRTB.video)) return false; + } + if (isBidANative(bid)) { + if (!isPlainObject(impression.openRTB.native) || !tryParse(bid.adm)) return false; + } + + return true; +} + +function isBidABanner(bid) { + return isPlainObject(bid) && + isPlainObject(bid.ext) && + isPlainObject(bid.ext.adot) && + bid.ext.adot.media_type === 'banner'; +} + +function isBidAVideo(bid) { + return isPlainObject(bid) && + isPlainObject(bid.ext) && + isPlainObject(bid.ext.adot) && + bid.ext.adot.media_type === 'video'; +} + +function isBidANative(bid) { + return isPlainObject(bid) && + isPlainObject(bid.ext) && + isPlainObject(bid.ext.adot) && + bid.ext.adot.media_type === 'native'; +} + +function getImpressionData(serverRequest, impressionId) { + const openRTBImpression = find(serverRequest.data.imp, imp => imp.id === impressionId); + const internalImpression = find(serverRequest._adot_internal.impressions, imp => imp.impressionId === impressionId); + return { - method: BID_METHOD, - url: bidderUrl, - data: buildBidRequest(adUnits, bidderRequest, requestId) + id: impressionId, + openRTB: openRTBImpression || null, + internal: internalImpression || null }; } -/** - * Split given PrebidJS Request in Dictionnary - * - * @param {Array} validBidRequests - * @returns {Dictionnary} - */ -function splitAdUnits(validBidRequests) { - return validBidRequests.reduce((adUnits, adUnit) => { - const bidderRequestId = adUnit.bidderRequestId; - if (!adUnits[bidderRequestId]) { - adUnits[bidderRequestId] = []; - } - adUnits[bidderRequestId].push(adUnit); - return adUnits; - }, {}); +function generateAdFromBid(bid, bidResponse, serverRequest) { + const impressionData = getImpressionData(serverRequest, bid.impid); + const isVideo = isBidAVideo(bid); + const base = { + requestId: impressionData.internal.bidId, + cpm: bid.price, + currency: bidResponse.cur, + ttl: TTL, + creativeId: bid.crid, + netRevenue: NET_REVENUE, + mediaType: bid.ext.adot.media_type, + }; + + if (bid.adomain) { + base.meta = { advertiserDomains: bid.adomain }; + } + + if (isBidANative(bid)) return {...base, native: formatNativeData(bid)}; + + const size = getSizeFromBid(bid, impressionData); + const creative = getCreativeFromBid(bid, impressionData); + + return { + ...base, + height: size.height, + width: size.width, + ad: creative.markup, + adUrl: creative.markupUrl, + vastXml: isVideo && !isStr(creative.markupUrl) ? creative.markup : null, + vastUrl: isVideo && isStr(creative.markupUrl) ? creative.markupUrl : null, + renderer: creative.renderer + }; } -/** - * Build Ajax request Array - * - * @param {Array} validBidRequests - * @param {BidderRequest} bidderRequest - * @returns {Array} - */ -function buildRequests(validBidRequests, bidderRequest) { - const adUnits = splitAdUnits(validBidRequests); - const publisherPathConfig = config.getConfig('adot.publisherPath'); - const publisherPath = publisherPathConfig === undefined ? '' : '/' + publisherPathConfig; - const bidderUrl = BIDDER_URL.replace('{PUBLISHER_PATH}', publisherPath); - - return Object.keys(adUnits).map((requestId) => buildAjaxRequest(adUnits[requestId], bidderRequest, bidderUrl, requestId)); -} - -/** - * Build Native PrebidJS Response grom OpenRtb Response - * - * @param {OpenRtbBid} bid - * - * @returns {NativeAssets} Native PrebidJS - */ -function buildNativeBidData(bid) { - const { adm, price } = bid; +function formatNativeData({adm, price}) { const parsedAdm = tryParse(adm); - const { assets, link: { url, clicktrackers }, imptrackers, jstracker } = parsedAdm.native; + const {assets, link: {url, clicktrackers}, imptrackers, jstracker} = parsedAdm.native; + const placements = NATIVE_PLACEMENTS; + const placementIds = NATIVE_ID_MAPPING; return assets.reduce((acc, asset) => { - const placementName = NATIVE_ID_MAPPING[asset.id]; - const content = placementName && asset[NATIVE_PLACEMENTS[placementName].name]; + const placementName = placementIds[asset.id]; + const content = placementName && asset[placements[placementName].name]; if (!content) return acc; - acc[placementName] = content.text || content.value || { url: content.url, width: content.w, height: content.h }; + acc[placementName] = content.text || content.value || {url: content.url, width: content.w, height: content.h}; return acc; }, { clickUrl: url, @@ -412,38 +571,57 @@ function buildNativeBidData(bid) { }); } -/** - * Return Adot Renderer if given Bid is a video one - * - * @param {OpenRtbBid} bid - * @param {string} mediaType - * @returns {any|null} - */ -function buildRenderer(bid, mediaType) { - if (!(mediaType === VIDEO && - bid.ext && - bid.ext.adot && - bid.ext.adot.container && - bid.ext.adot.adUnitCode && - bid.ext.adot.video && - bid.ext.adot.video.type === OUTSTREAM)) return null; - - const container = bid.ext.adot.container - const adUnitCode = bid.ext.adot.adUnitCode +function getSizeFromBid(bid, impressionData) { + if (isNumber(bid.w) && isNumber(bid.h)) { + return { width: bid.w, height: bid.h }; + } + + if (isImpressionAVideo(impressionData.openRTB)) { + const { video } = impressionData.openRTB; + + if (isNumber(video.w) && isNumber(video.h)) { + return { width: video.w, height: video.h }; + } + } + + return { width: null, height: null }; +} + +function getCreativeFromBid(bid, impressionData) { + const shouldUseAdMarkup = !!bid.adm; + const price = bid.price; + return { + markup: shouldUseAdMarkup ? replaceAuctionPrice(bid.adm, price) : null, + markupUrl: !shouldUseAdMarkup ? replaceAuctionPrice(bid.nurl, price) : null, + renderer: getRendererFromBid(bid, impressionData) + }; +} + +function getRendererFromBid(bid, impressionData) { + const isOutstreamImpression = isBidAVideo(bid) && + isImpressionAVideo(impressionData.openRTB) && + isOutstream(impressionData.openRTB.video); + + return isOutstreamImpression + ? buildOutstreamRenderer(impressionData) + : null; +} + +function buildOutstreamRenderer(impressionData) { const renderer = Renderer.install({ url: OUTSTREAM_VIDEO_PLAYER_URL, loaded: false, - adUnitCode: adUnitCode + adUnitCode: impressionData.internal.adUnitCode }); renderer.setRender((ad) => { ad.renderer.push(() => { - const domContainer = container - ? document.querySelector(container) - : document.getElementById(adUnitCode); + const container = impressionData.internal.container + ? document.querySelector(impressionData.internal.container) + : document.getElementById(impressionData.internal.adUnitCode); - const player = new window.VASTPlayer(domContainer); + const player = new window.VASTPlayer(container); player.on('ready', () => { player.adVolume = 0; @@ -463,181 +641,54 @@ function buildRenderer(bid, mediaType) { return renderer; } -/** - * Build PrebidJS response from OpenRtbBid - * - * @param {OpenRtbBid} bid - * @param {string} mediaType - * @returns {Object} - */ -function buildCreativeBidData(bid, mediaType) { - const adm = bid.adm ? replaceAuctionPrice(bid.adm, bid.price) : null; - const nurl = (!bid.adm && bid.nurl) ? replaceAuctionPrice(bid.nurl, bid.price) : null; - - return { - width: bid.ext.adot.size && bid.ext.adot.size.w, - height: bid.ext.adot.size && bid.ext.adot.size.h, - ad: adm, - adUrl: nurl, - vastXml: mediaType === VIDEO && !isStr(nurl) ? adm : null, - vastUrl: mediaType === VIDEO && isStr(nurl) ? nurl : null, - renderer: buildRenderer(bid, mediaType) - }; +function tryParse(data) { + try { + return JSON.parse(data); + } catch (err) { + logError(err); + return null; + } } -/** - * Return if given bid and imp are valid - * - * @param {OpenRtbBid} bid OpenRtb Bid - * @param {Imp} imp OpenRtb Imp - * @returns {boolean} - */ -function isBidImpInvalid(bid, imp) { - return !bid || !imp; -} - -/** - * Build PrebidJS Bid Response from given OpenRTB Bid - * - * @param {OpenRtbBid} bid - * @param {OpenRtbBidResponse} bidResponse - * @param {OpenRtbBid} imp - * @returns {PrebidJSResponse} - */ -function buildBidResponse(bid, bidResponse, imp) { - if (isBidImpInvalid(bid, imp)) return null; - const mediaType = bid.ext.adot.media_type; - const baseBid = { - requestId: bid.impid, - cpm: bid.price, - currency: bidResponse.cur, - ttl: BID_RESPONSE_TTL, - creativeId: bid.crid, - netRevenue: BID_RESPONSE_NET_REVENUE, - mediaType - }; +const adotBidderSpec = { + code: 'adot', + supportedMediaTypes: [BANNER, VIDEO, NATIVE], + isBidRequestValid(adUnit) { + const allowedBidderCodes = [this.code]; + + return isPlainObject(adUnit) && + allowedBidderCodes.indexOf(adUnit.bidder) !== -1 && + isStr(adUnit.adUnitCode) && + isStr(adUnit.bidderRequestId) && + isStr(adUnit.bidId) && + validateMediaTypes(adUnit.mediaTypes, this.supportedMediaTypes) && + validateParameters(adUnit.params, adUnit); + }, + buildRequests(adUnits, adUnitContext) { + if (!adUnits) return null; + + return groupBy(adUnits, 'bidderRequestId').map(group => { + const bidRequestId = group.id; + const adUnits = groupBy(group.values, 'bidId').map((group) => { + const length = group.values.length; + return length > 0 && group.values[length - 1] + }); - if (bid.dealid) baseBid.dealId = bid.dealid; - if (bid.adomain) baseBid.meta = { advertiserDomains: bid.adomain }; - - if (mediaType === NATIVE) return { ...baseBid, native: buildNativeBidData(bid) }; - return { ...baseBid, ...buildCreativeBidData(bid, mediaType) }; -} - -/** - * Find OpenRtb Imp from request with same id that given bid - * - * @param {OpenRtbBid} bid - * @param {OpenRtbRequest} bidRequest - * @returns {Imp} OpenRtb Imp - */ -function getImpfromBid(bid, bidRequest) { - if (!bidRequest || !bidRequest.imp) return null; - const imps = bidRequest.imp; - return find(imps, (imp) => imp.id === bid.impid); -} - -/** - * Return if given response is valid - * - * @param {OpenRtbBidResponse} response - * @returns {boolean} - */ -function isValidResponse(response) { - return isPlainObject(response) && - isPlainObject(response.body) && - isStr(response.body.cur) && - isArray(response.body.seatbid); -} - -/** - * Return if given request is valid - * - * @param {OpenRtbRequest} request - * @returns {boolean} - */ -function isValidRequest(request) { - return isPlainObject(request) && - isPlainObject(request.data) && - isArray(request.data.imp); -} - -/** - * Interpret given OpenRtb Response to build PrebidJS Response - * - * @param {OpenRtbBidResponse} serverResponse - * @param {OpenRtbRequest} request - * @returns {PrebidJSResponse} - */ -function interpretResponse(serverResponse, request) { - if (!isValidResponse(serverResponse) || !isValidRequest(request)) return []; - - const bidsResponse = serverResponse.body; - const bidRequest = request.data; - - return bidsResponse.seatbid.reduce((pbsResponse, seatbid) => { - if (!seatbid || !isArray(seatbid.bid)) return pbsResponse; - seatbid.bid.forEach((bid) => { - const imp = getImpfromBid(bid, bidRequest); - const bidResponse = buildBidResponse(bid, bidsResponse, imp); - if (bidResponse) pbsResponse.push(bidResponse); + return createServerRequestFromAdUnits(adUnits, bidRequestId, adUnitContext) }); - return pbsResponse; - }, []); -} + }, + interpretResponse(serverResponse, serverRequest) { + if (!validateServerRequest(serverRequest)) return []; + if (!validateServerResponse(serverResponse)) return []; -/** - * Call Adunit getFloor function with given argument to get specific floor. - * Return 0 by default - * - * @param {AdUnit} adUnit - * @param {Array|string} size Adunit size or * - * @param {string} mediaType - * @param {string} currency USD by default - * - * @returns {number} Floor price - */ -function getFloor(adUnit, size, mediaType, currency) { - if (!isFn(adUnit.getFloor)) return 0; - - const floorResult = adUnit.getFloor({ currency, mediaType, size }); - - return floorResult.currency === currency ? floorResult.floor : 0; -} - -/** - * Call getFloor for each format and return the lower floor - * Return 0 by default - * - * interface Format { w: number; h: number } - * - * @param {AdUnit} adUnit - * @param {Array} formats Media formats - * @param {string} mediaType - * @param {string} currency USD by default - * - * @returns {number} Lower floor. - */ -function getMainFloor(adUnit, formats, mediaType, currency) { - if (!formats) return getFloor(adUnit, '*', mediaType, currency); - - return formats.reduce((bidFloor, format) => { - const floor = getFloor(adUnit, [format.w, format.h], mediaType, currency) - const maxFloor = bidFloor || Number.MAX_SAFE_INTEGER; - return floor !== 0 && floor < maxFloor ? floor : bidFloor; - }, null) || 0; -} - -/** - * Adot PrebidJS Adapter - */ -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, NATIVE, VIDEO], - isBidRequestValid, - buildRequests, - interpretResponse, - getFloor + const bidResponse = serverResponse.body; + + return bidResponse.seatbid + .filter(seatBid => isPlainObject(seatBid) && isArray(seatBid.bid)) + .reduce((acc, seatBid) => acc.concat(seatBidsToAds(seatBid, bidResponse, serverRequest)), []); + } }; -registerBidder(spec); +registerBidder(adotBidderSpec); + +export {adotBidderSpec as spec}; diff --git a/modules/adotBidAdapter.md b/modules/adotBidAdapter.md index d1622e5f901..894a592ec18 100644 --- a/modules/adotBidAdapter.md +++ b/modules/adotBidAdapter.md @@ -6,7 +6,7 @@ Adot Bidder Adapter is a module that enables the communication between the Prebi - Module name: Adot Bidder Adapter - Module type: Bidder Adapter -- Maintainer: `alexandre.lorin@adotmob.com` +- Maintainer: `aurelien.giudici@adotmob.com` - Supported media types: `banner`, `video`, `native` ## Example ad units @@ -34,9 +34,9 @@ const adUnit = { ### Video ad unit -#### Video ad unit +#### Outstream video ad unit -Adot Bidder Adapter accepts video ad units using the following ad unit format: +Adot Bidder Adapter accepts outstream video ad units using the following ad unit format: ```javascript const adUnit = { @@ -51,9 +51,9 @@ const adUnit = { // Content MIME types supported by the ad unit. mimes: ['video/mp4'], // Minimum accepted video ad duration (in seconds). - minduration: 5, + minDuration: 5, // Maximum accepted video ad duration (in seconds). - maxduration: 35, + maxDuration: 35, // Video protocols supported by the ad unit (see the OpenRTB 2.5 specifications, // section 5.8). protocols: [2, 3] @@ -61,7 +61,45 @@ const adUnit = { }, bids: [{ bidder: 'adot', - params: {} + params: { + video: {} + } + }] +} +``` + +#### Instream video ad unit + +Adot Bidder Adapter accepts instream video ad units using the following ad unit format: + +```javascript +const adUnit = { + code: 'test-div', + mediaTypes: { + video: { + // Video context. Must be 'instream'. + context: 'instream', + // Video dimensions supported by the video ad unit. + // Each ad unit size is formatted as follows: [width, height]. + playerSize: [[300, 250]], + // Content MIME types supported by the ad unit. + mimes: ['video/mp4'], + // Minimum accepted video ad duration (in seconds). + minDuration: 5, + // Maximum accepted video ad duration (in seconds). + maxDuration: 35, + // Video protocols supported by the ad unit (see the OpenRTB 2.5 specifications, + // section 5.8). + protocols: [2, 3] + } + }, + bids: [{ + bidder: 'adot', + params: { + video: { + instreamContext: 'pre-roll' + } + } }] } ``` diff --git a/modules/adpartnerBidAdapter.js b/modules/adpartnerBidAdapter.js deleted file mode 100644 index e8d8a43aa1b..00000000000 --- a/modules/adpartnerBidAdapter.js +++ /dev/null @@ -1,215 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import { buildUrl } from '../src/utils.js' -import {ajax} from '../src/ajax.js'; - -const BIDDER_CODE = 'adpartner'; -export const ENDPOINT_PROTOCOL = 'https'; -export const ENDPOINT_DOMAIN = 'a4p.adpartner.pro'; -export const ENDPOINT_PATH = '/hb/bid'; - -export const spec = { - code: BIDDER_CODE, - - isBidRequestValid: function (bidRequest) { - return !!parseInt(bidRequest.params.unitId) || !!parseInt(bidRequest.params.partnerId); - }, - - buildRequests: function (validBidRequests, bidderRequest) { - let referer = window.location.href; - try { - referer = typeof bidderRequest.refererInfo === 'undefined' - ? window.top.location.href - : bidderRequest.refererInfo.referer; - } catch (e) {} - - let bidRequests = []; - let beaconParams = { - tag: [], - partner: [], - sizes: [], - referer: '' - }; - - validBidRequests.forEach(function(validBidRequest) { - let bidRequestObject = { - adUnitCode: validBidRequest.adUnitCode, - sizes: validBidRequest.sizes, - bidId: validBidRequest.bidId, - referer: referer - }; - - if (parseInt(validBidRequest.params.unitId)) { - bidRequestObject.unitId = parseInt(validBidRequest.params.unitId); - beaconParams.tag.push(validBidRequest.params.unitId); - } - - if (parseInt(validBidRequest.params.partnerId)) { - bidRequestObject.unitId = 0; - bidRequestObject.partnerId = parseInt(validBidRequest.params.partnerId); - beaconParams.partner.push(validBidRequest.params.partnerId); - } - - bidRequests.push(bidRequestObject); - - beaconParams.sizes.push(spec.joinSizesToString(validBidRequest.sizes)); - beaconParams.referer = encodeURIComponent(referer); - }); - - if (beaconParams.partner.length > 0) { - beaconParams.partner = beaconParams.partner.join(','); - } else { - delete beaconParams.partner; - } - - beaconParams.tag = beaconParams.tag.join(','); - beaconParams.sizes = beaconParams.sizes.join(','); - - let adPartnerRequestUrl = buildUrl({ - protocol: ENDPOINT_PROTOCOL, - hostname: ENDPOINT_DOMAIN, - pathname: ENDPOINT_PATH, - search: beaconParams - }); - - return { - method: 'POST', - url: adPartnerRequestUrl, - data: JSON.stringify(bidRequests) - }; - }, - - joinSizesToString: function(sizes) { - let res = []; - sizes.forEach(function(size) { - res.push(size.join('x')); - }); - - return res.join('|'); - }, - - interpretResponse: function (serverResponse, bidRequest) { - const validBids = JSON.parse(bidRequest.data); - - if (typeof serverResponse.body === 'undefined') { - return []; - } - - return validBids - .map(bid => ({ - bid: bid, - ad: serverResponse.body[bid.adUnitCode] - })) - .filter(item => item.ad) - .map(item => spec.adResponse(item.bid, item.ad)); - }, - - adResponse: function(bid, ad) { - const bidObject = { - requestId: bid.bidId, - ad: ad.ad, - cpm: ad.cpm, - width: ad.width, - height: ad.height, - ttl: 60, - creativeId: ad.creativeId, - netRevenue: ad.netRevenue, - currency: ad.currency, - winNotification: ad.winNotification - } - - bidObject.meta = {}; - if (ad.adomain && ad.adomain.length > 0) { - bidObject.meta.advertiserDomains = ad.adomain; - } - - return bidObject; - }, - - onBidWon: function(data) { - data.winNotification.forEach(function(unitWon) { - let adPartnerBidWonUrl = buildUrl({ - protocol: ENDPOINT_PROTOCOL, - hostname: ENDPOINT_DOMAIN, - pathname: unitWon.path - }); - - if (unitWon.method === 'POST') { - spec.postRequest(adPartnerBidWonUrl, JSON.stringify(unitWon.data)); - } - }); - - return true; - }, - - postRequest(endpoint, data) { - ajax(endpoint, null, data, {method: 'POST'}); - }, - - getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { - const syncs = []; - - if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) { - return syncs; - } - - let appendGdprParams = function (url, gdprParams) { - if (gdprParams === null) { - return url; - } - - return url + (url.indexOf('?') >= 0 ? '&' : '?') + gdprParams; - }; - - let gdprParams = null; - if (gdprConsent) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - gdprParams = `gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - gdprParams = `gdpr_consent=${gdprConsent.consentString}`; - } - } - - serverResponses.forEach(resp => { - if (resp.body) { - Object.keys(resp.body).map(function(key, index) { - let respObject = resp.body[key]; - if (respObject['syncs'] !== undefined && - Array.isArray(respObject.syncs) && - respObject.syncs.length > 0) { - if (syncOptions.iframeEnabled) { - respObject.syncs.filter(function (syncIframeObject) { - if (syncIframeObject['type'] !== undefined && - syncIframeObject['link'] !== undefined && - syncIframeObject.type === 'iframe') { return true; } - return false; - }).forEach(function (syncIframeObject) { - syncs.push({ - type: 'iframe', - url: appendGdprParams(syncIframeObject.link, gdprParams) - }); - }); - } - if (syncOptions.pixelEnabled) { - respObject.syncs.filter(function (syncImageObject) { - if (syncImageObject['type'] !== undefined && - syncImageObject['link'] !== undefined && - syncImageObject.type === 'image') { return true; } - return false; - }).forEach(function (syncImageObject) { - syncs.push({ - type: 'image', - url: appendGdprParams(syncImageObject.link, gdprParams) - }); - }); - } - } - }); - } - }); - - return syncs; - }, - -} - -registerBidder(spec); diff --git a/modules/adpartnerBidAdapter.md b/modules/adpartnerBidAdapter.md index 2dc1c31c4c3..ad105c43a8a 100644 --- a/modules/adpartnerBidAdapter.md +++ b/modules/adpartnerBidAdapter.md @@ -23,19 +23,7 @@ About us : https://adpartner.pro { bidder: "adpartner", params: { - unitId: 6698 - } - } - ] - }, - { - code: 'div-adpartner-example-2', - sizes: [[300, 250]], - bids: [ - { - bidder: "adpartner", - params: { - partnerId: 6698 + unitId: 5809 } } ] diff --git a/modules/adplusBidAdapter.js b/modules/adplusBidAdapter.js deleted file mode 100644 index 4707ca2ff5a..00000000000 --- a/modules/adplusBidAdapter.js +++ /dev/null @@ -1,203 +0,0 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import * as utils from '../src/utils.js'; -import { BANNER } from '../src/mediaTypes.js'; -import { getStorageManager } from '../src/storageManager.js'; - -// #region Constants -export const BIDDER_CODE = 'adplus'; -export const ADPLUS_ENDPOINT = 'https://ssp.ad-plus.com.tr/server/headerBidding'; -export const DGID_CODE = 'adplus_dg_id'; -export const SESSION_CODE = 'adplus_s_id'; -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); -const COOKIE_EXP = 1000 * 60 * 60 * 24; // 1 day -// #endregion - -// #region Helpers -export function isValidUuid (uuid) { - return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test( - uuid - ); -} - -function getSessionId() { - let sid = storage.cookiesAreEnabled() && storage.getCookie(SESSION_CODE); - - if ( - !sid || !isValidUuid(sid) - ) { - sid = utils.generateUUID(); - setSessionId(sid); - } - - return sid; -} - -function setSessionId(sid) { - if (storage.cookiesAreEnabled()) { - const expires = new Date(Date.now() + COOKIE_EXP).toISOString(); - - storage.setCookie(SESSION_CODE, sid, expires); - } -} -// #endregion - -// #region Bid request validation -function isBidRequestValid(bid) { - if (!bid) { - utils.logError(BIDDER_CODE, 'bid, can not be empty', bid); - return false; - } - - if (!bid.params) { - utils.logError(BIDDER_CODE, 'bid.params is required.'); - return false; - } - - if (!bid.params.adUnitId || typeof bid.params.adUnitId !== 'string') { - utils.logError( - BIDDER_CODE, - 'bid.params.adUnitId is missing or has wrong type.' - ); - return false; - } - - if (!bid.params.inventoryId || typeof bid.params.inventoryId !== 'string') { - utils.logError( - BIDDER_CODE, - 'bid.params.inventoryId is missing or has wrong type.' - ); - return false; - } - - if ( - !bid.mediaTypes || - !bid.mediaTypes[BANNER] || - !utils.isArray(bid.mediaTypes[BANNER].sizes) || - bid.mediaTypes[BANNER].sizes.length <= 0 || - !utils.isArrayOfNums(bid.mediaTypes[BANNER].sizes[0]) - ) { - utils.logError(BIDDER_CODE, 'Wrong or missing size parameters.'); - return false; - } - - return true; -} -// #endregion - -// #region Building the bid requests -/** - * - * @param {object} bid - * @returns - */ -function createBidRequest(bid) { - // Developer Params - const { - inventoryId, - adUnitId, - extraData, - yearOfBirth, - gender, - categories, - latitude, - longitude, - sdkVersion, - } = bid.params; - - return { - method: 'GET', - url: ADPLUS_ENDPOINT, - data: utils.cleanObj({ - bidId: bid.bidId, - inventoryId, - adUnitId, - adUnitWidth: bid.mediaTypes[BANNER].sizes[0][0], - adUnitHeight: bid.mediaTypes[BANNER].sizes[0][1], - extraData, - yearOfBirth, - gender, - categories, - latitude, - longitude, - sdkVersion: sdkVersion || '1', - session: getSessionId(), - interstitial: 0, - token: typeof window.top === 'object' && window.top[DGID_CODE] ? window.top[DGID_CODE] : undefined, - secure: window.location.protocol === 'https:' ? 1 : 0, - screenWidth: screen.width, - screenHeight: screen.height, - language: window.navigator.language || 'en-US', - pageUrl: window.location.href, - domain: window.location.hostname, - referrer: window.location.referrer, - }), - }; -} - -function buildRequests(validBidRequests, bidderRequest) { - return validBidRequests.map((req) => createBidRequest(req)); -} -// #endregion - -// #region Interpreting Responses -/** - * - * @param {HeaderBiddingResponse} responseData - * @param { object } bidParams - * @returns - */ -function createAdResponse(responseData, bidParams) { - return { - requestId: responseData.requestID, - cpm: responseData.cpm, - currency: responseData.currency, - width: responseData.width, - height: responseData.height, - creativeId: responseData.creativeID, - dealId: responseData.dealID, - netRevenue: responseData.netRevenue, - ttl: responseData.ttl, - ad: responseData.ad, - mediaType: responseData.mediaType, - meta: { - advertiserDomains: responseData.advertiserDomains, - primaryCatId: utils.isArray(responseData.categoryIDs) && responseData.categoryIDs.length > 0 - ? responseData.categoryIDs[0] : undefined, - secondaryCatIds: responseData.categoryIDs, - }, - }; -} - -function interpretResponse(response, request) { - // In case of empty response - if ( - response.body == null || - !utils.isArray(response.body) || - response.body.length === 0 - ) { - return []; - } - const bids = response.body.map((bid) => createAdResponse(bid)); - return bids; -} -// #endregion - -// #region Bidder -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER], - isBidRequestValid, - buildRequests, - interpretResponse, - onTimeout(timeoutData) { - utils.logError('Adplus adapter timed out for the auction.', timeoutData); - }, - onBidWon(bid) { - utils.logInfo( - `Adplus adapter won the auction. Bid id: ${bid.bidId}, Ad Unit Id: ${bid.adUnitId}, Inventory Id: ${bid.inventoryId}` - ); - }, -}; - -registerBidder(spec); -// #endregion diff --git a/modules/adplusBidAdapter.md b/modules/adplusBidAdapter.md deleted file mode 100644 index dce9e4a312f..00000000000 --- a/modules/adplusBidAdapter.md +++ /dev/null @@ -1,39 +0,0 @@ -# Overview - -Module Name: AdPlus Bidder Adapter - -Module Type: Bidder Adapter - -Maintainer: adplus.destek@yaani.com.tr - -# Description - -AdPlus Prebid.js Bidder Adapter. Only banner formats are supported. - -About us : https://ssp.ad-plus.com.tr/ - -# Test Parameters - -```javascript -var adUnits = [ - { - code: "div-adplus", - mediaTypes: { - banner: { - sizes: [ - [300, 250], - ], - }, - }, - bids: [ - { - bidder: "adplus", - params: { - inventoryId: "-1", - adUnitId: "-3", - }, - }, - ], - }, -]; -``` diff --git a/modules/adpod.js b/modules/adpod.js index b7c459fd66f..57baf5b5fc6 100644 --- a/modules/adpod.js +++ b/modules/adpod.js @@ -12,37 +12,21 @@ * module that designed to support adpod video type ads. This import process allows this module to effectively act as a sub-module. */ -import { - compareOn, - deepAccess, - generateUUID, - groupBy, - isArray, - isArrayOfNums, - isNumber, - isPlainObject, - logError, - logInfo, - logWarn -} from '../src/utils.js'; -import { - addBidToAuction, - AUCTION_IN_PROGRESS, - callPrebidCache, - doCallbacksIfTimedout, - getPriceByGranularity, - getPriceGranularity -} from '../src/auction.js'; -import {checkAdUnitSetup} from '../src/prebid.js'; -import {checkVideoBidSetup} from '../src/video.js'; -import {module, setupBeforeHookFnOnce} from '../src/hook.js'; -import {store} from '../src/videoCache.js'; -import {config} from '../src/config.js'; -import {ADPOD} from '../src/mediaTypes.js'; -import {find, arrayFrom as from} from '../src/polyfill.js'; -import {auctionManager} from '../src/auctionManager.js'; +import * as utils from '../src/utils.js'; +import { addBidToAuction, doCallbacksIfTimedout, AUCTION_IN_PROGRESS, callPrebidCache, getPriceByGranularity, getPriceGranularity } from '../src/auction.js'; +import { checkAdUnitSetup } from '../src/prebid.js'; +import { checkVideoBidSetup } from '../src/video.js'; +import { setupBeforeHookFnOnce, module } from '../src/hook.js'; +import { store } from '../src/videoCache.js'; +import { config } from '../src/config.js'; +import { ADPOD } from '../src/mediaTypes.js'; +import Set from 'core-js-pure/features/set'; +import find from 'core-js-pure/features/array/find.js'; +import { auctionManager } from '../src/auctionManager.js'; import CONSTANTS from '../src/constants.json'; +const from = require('core-js-pure/features/array/from.js'); + const TARGETING_KEY_PB_CAT_DUR = 'hb_pb_cat_dur'; const TARGETING_KEY_CACHE_ID = 'hb_cache_id'; @@ -61,7 +45,7 @@ function createBidCacheRegistry() { registry[auctionId] = {}; registry[auctionId].bidStorage = new Set(); registry[auctionId].queueDispatcher = createDispatcher(queueTimeDelay); - registry[auctionId].initialCacheKey = generateUUID(); + registry[auctionId].initialCacheKey = utils.generateUUID(); } return { @@ -84,7 +68,7 @@ function createBidCacheRegistry() { setupInitialCacheKey: function (bid) { if (!registry[bid.auctionId]) { registry[bid.auctionId] = {}; - registry[bid.auctionId].initialCacheKey = generateUUID(); + registry[bid.auctionId].initialCacheKey = utils.generateUUID(); } }, getInitialCacheKey: function (bid) { @@ -131,11 +115,11 @@ function createDispatcher(timeoutDuration) { function getPricePartForAdpodKey(bid) { let pricePart let prioritizeDeals = config.getConfig('adpod.prioritizeDeals'); - if (prioritizeDeals && deepAccess(bid, 'video.dealTier')) { + if (prioritizeDeals && utils.deepAccess(bid, 'video.dealTier')) { const adpodDealPrefix = config.getConfig(`adpod.dealTier.${bid.bidderCode}.prefix`); - pricePart = (adpodDealPrefix) ? adpodDealPrefix + deepAccess(bid, 'video.dealTier') : deepAccess(bid, 'video.dealTier'); + pricePart = (adpodDealPrefix) ? adpodDealPrefix + utils.deepAccess(bid, 'video.dealTier') : utils.deepAccess(bid, 'video.dealTier'); } else { - const granularity = getPriceGranularity(bid); + const granularity = getPriceGranularity(bid.mediaType); pricePart = getPriceByGranularity(granularity)(bid); } return pricePart @@ -148,12 +132,12 @@ function getPricePartForAdpodKey(bid) { */ function attachPriceIndustryDurationKeyToBid(bid, brandCategoryExclusion) { let initialCacheKey = bidCacheRegistry.getInitialCacheKey(bid); - let duration = deepAccess(bid, 'video.durationBucket'); + let duration = utils.deepAccess(bid, 'video.durationBucket'); const pricePart = getPricePartForAdpodKey(bid); let pcd; if (brandCategoryExclusion) { - let category = deepAccess(bid, 'meta.adServerCatId'); + let category = utils.deepAccess(bid, 'meta.adServerCatId'); pcd = `${pricePart}_${category}_${duration}s`; } else { pcd = `${pricePart}_${duration}s`; @@ -184,7 +168,7 @@ function updateBidQueue(auctionInstance, bidResponse, afterBidAdded) { let killQueue = !!(auctionInstance.getAuctionStatus() !== AUCTION_IN_PROGRESS); callDispatcher(auctionInstance, bidListArr, afterBidAdded, killQueue); } else { - logWarn('Attempted to cache a bid from an unknown auction. Bid:', bidResponse); + utils.logWarn('Attempted to cache a bid from an unknown auction. Bid:', bidResponse); } } @@ -212,7 +196,7 @@ function firePrebidCacheCall(auctionInstance, bidList, afterBidAdded) { store(bidList, function (error, cacheIds) { if (error) { - logWarn(`Failed to save to the video cache: ${error}. Video bid(s) must be discarded.`); + utils.logWarn(`Failed to save to the video cache: ${error}. Video bid(s) must be discarded.`); for (let i = 0; i < bidList.length; i++) { doCallbacksIfTimedout(auctionInstance, bidList[i]); } @@ -222,7 +206,7 @@ function firePrebidCacheCall(auctionInstance, bidList, afterBidAdded) { if (cacheIds[i].uuid !== '') { addBidToAuction(auctionInstance, bidList[i]); } else { - logInfo(`Detected a bid was not cached because the custom key was already registered. Attempted to use key: ${bidList[i].customCacheKey}. Bid was: `, bidList[i]); + utils.logInfo(`Detected a bid was not cached because the custom key was already registered. Attempted to use key: ${bidList[i].customCacheKey}. Bid was: `, bidList[i]); } afterBidAdded(); } @@ -236,14 +220,15 @@ function firePrebidCacheCall(auctionInstance, bidList, afterBidAdded) { * @param {*} auctionInstance running context of the auction * @param {Object} bidResponse incoming bid; if adpod, will be processed through hook function. If not adpod, returns to original function. * @param {Function} afterBidAdded callback function used when Prebid Cache responds - * @param {Object} videoConfig mediaTypes.video from the bid's adUnit + * @param {Object} bidderRequest copy of bid's associated bidderRequest object */ -export function callPrebidCacheHook(fn, auctionInstance, bidResponse, afterBidAdded, videoConfig) { +export function callPrebidCacheHook(fn, auctionInstance, bidResponse, afterBidAdded, bidderRequest) { + let videoConfig = utils.deepAccess(bidderRequest, 'mediaTypes.video'); if (videoConfig && videoConfig.context === ADPOD) { let brandCategoryExclusion = config.getConfig('adpod.brandCategoryExclusion'); - let adServerCatId = deepAccess(bidResponse, 'meta.adServerCatId'); + let adServerCatId = utils.deepAccess(bidResponse, 'meta.adServerCatId'); if (!adServerCatId && brandCategoryExclusion) { - logWarn('Detected a bid without meta.adServerCatId while setConfig({adpod.brandCategoryExclusion}) was enabled. This bid has been rejected:', bidResponse) + utils.logWarn('Detected a bid without meta.adServerCatId while setConfig({adpod.brandCategoryExclusion}) was enabled. This bid has been rejected:', bidResponse) afterBidAdded(); } else { if (config.getConfig('adpod.deferCaching') === false) { @@ -262,7 +247,7 @@ export function callPrebidCacheHook(fn, auctionInstance, bidResponse, afterBidAd } } } else { - fn.call(this, auctionInstance, bidResponse, afterBidAdded, videoConfig); + fn.call(this, auctionInstance, bidResponse, afterBidAdded, bidderRequest); } } @@ -275,12 +260,12 @@ export function callPrebidCacheHook(fn, auctionInstance, bidResponse, afterBidAd */ export function checkAdUnitSetupHook(fn, adUnits) { let goodAdUnits = adUnits.filter(adUnit => { - let mediaTypes = deepAccess(adUnit, 'mediaTypes'); - let videoConfig = deepAccess(mediaTypes, 'video'); + let mediaTypes = utils.deepAccess(adUnit, 'mediaTypes'); + let videoConfig = utils.deepAccess(mediaTypes, 'video'); if (videoConfig && videoConfig.context === ADPOD) { // run check to see if other mediaTypes are defined (ie multi-format); reject adUnit if so if (Object.keys(mediaTypes).length > 1) { - logWarn(`Detected more than one mediaType in adUnitCode: ${adUnit.code} while attempting to define an 'adpod' video adUnit. 'adpod' adUnits cannot be mixed with other mediaTypes. This adUnit will be removed from the auction.`); + utils.logWarn(`Detected more than one mediaType in adUnitCode: ${adUnit.code} while attempting to define an 'adpod' video adUnit. 'adpod' adUnits cannot be mixed with other mediaTypes. This adUnit will be removed from the auction.`); return false; } @@ -289,20 +274,20 @@ export function checkAdUnitSetupHook(fn, adUnits) { let playerSize = !!( ( videoConfig.playerSize && ( - isArrayOfNums(videoConfig.playerSize, 2) || ( - isArray(videoConfig.playerSize) && videoConfig.playerSize.every(sz => isArrayOfNums(sz, 2)) + utils.isArrayOfNums(videoConfig.playerSize, 2) || ( + utils.isArray(videoConfig.playerSize) && videoConfig.playerSize.every(sz => utils.isArrayOfNums(sz, 2)) ) ) ) || (videoConfig.sizeConfig) ); - let adPodDurationSec = !!(videoConfig.adPodDurationSec && isNumber(videoConfig.adPodDurationSec) && videoConfig.adPodDurationSec > 0); - let durationRangeSec = !!(videoConfig.durationRangeSec && isArrayOfNums(videoConfig.durationRangeSec) && videoConfig.durationRangeSec.every(range => range > 0)); + let adPodDurationSec = !!(videoConfig.adPodDurationSec && utils.isNumber(videoConfig.adPodDurationSec) && videoConfig.adPodDurationSec > 0); + let durationRangeSec = !!(videoConfig.durationRangeSec && utils.isArrayOfNums(videoConfig.durationRangeSec) && videoConfig.durationRangeSec.every(range => range > 0)); if (!playerSize || !adPodDurationSec || !durationRangeSec) { errMsg += (!playerSize) ? '\nmediaTypes.video.playerSize' : ''; errMsg += (!adPodDurationSec) ? '\nmediaTypes.video.adPodDurationSec' : ''; errMsg += (!durationRangeSec) ? '\nmediaTypes.video.durationRangeSec' : ''; - logWarn(errMsg); + utils.logWarn(errMsg); return false; } } @@ -322,30 +307,31 @@ export function checkAdUnitSetupHook(fn, adUnits) { * (eg if range was [5, 15, 30] -> 2s is rounded to 5s; 17s is rounded back to 15s; 18s is rounded up to 30s) * - if the bid is above the range of the listed durations (and outside the buffer), reject the bid * - set the rounded duration value in the `bid.video.durationBucket` field for accepted bids - * @param {Object} videoMediaType 'mediaTypes.video' associated to bidResponse + * @param {Object} bidderRequest copy of the bidderRequest object associated to bidResponse * @param {Object} bidResponse incoming bidResponse being evaluated by bidderFactory * @returns {boolean} return false if bid duration is deemed invalid as per adUnit configuration; return true if fine */ -function checkBidDuration(videoMediaType, bidResponse) { +function checkBidDuration(bidderRequest, bidResponse) { const buffer = 2; - let bidDuration = deepAccess(bidResponse, 'video.durationSeconds'); - let adUnitRanges = videoMediaType.durationRangeSec; + let bidDuration = utils.deepAccess(bidResponse, 'video.durationSeconds'); + let videoConfig = utils.deepAccess(bidderRequest, 'mediaTypes.video'); + let adUnitRanges = videoConfig.durationRangeSec; adUnitRanges.sort((a, b) => a - b); // ensure the ranges are sorted in numeric order - if (!videoMediaType.requireExactDuration) { + if (!videoConfig.requireExactDuration) { let max = Math.max(...adUnitRanges); if (bidDuration <= (max + buffer)) { let nextHighestRange = find(adUnitRanges, range => (range + buffer) >= bidDuration); bidResponse.video.durationBucket = nextHighestRange; } else { - logWarn(`Detected a bid with a duration value outside the accepted ranges specified in adUnit.mediaTypes.video.durationRangeSec. Rejecting bid: `, bidResponse); + utils.logWarn(`Detected a bid with a duration value outside the accepted ranges specified in adUnit.mediaTypes.video.durationRangeSec. Rejecting bid: `, bidResponse); return false; } } else { if (find(adUnitRanges, range => range === bidDuration)) { bidResponse.video.durationBucket = bidDuration; } else { - logWarn(`Detected a bid with a duration value not part of the list of accepted ranges specified in adUnit.mediaTypes.video.durationRangeSec. Exact match durations must be used for this adUnit. Rejecting bid: `, bidResponse); + utils.logWarn(`Detected a bid with a duration value not part of the list of accepted ranges specified in adUnit.mediaTypes.video.durationRangeSec. Exact match durations must be used for this adUnit. Rejecting bid: `, bidResponse); return false; } } @@ -357,34 +343,34 @@ function checkBidDuration(videoMediaType, bidResponse) { * If it's found to not be an adpod bid, it will return to original function via hook logic * @param {Function} fn reference to original function (used by hook logic) * @param {Object} bid incoming bid object - * @param {Object} adUnit adUnit object of associated bid + * @param {Object} bidRequest bidRequest object of associated bid * @param {Object} videoMediaType copy of the `bidRequest.mediaTypes.video` object; used in original function * @param {String} context value of the `bidRequest.mediaTypes.video.context` field; used in original function * @returns {boolean} this return is only used for adpod bids */ -export function checkVideoBidSetupHook(fn, bid, adUnit, videoMediaType, context) { +export function checkVideoBidSetupHook(fn, bid, bidRequest, videoMediaType, context) { if (context === ADPOD) { let result = true; let brandCategoryExclusion = config.getConfig('adpod.brandCategoryExclusion'); - if (brandCategoryExclusion && !deepAccess(bid, 'meta.primaryCatId')) { + if (brandCategoryExclusion && !utils.deepAccess(bid, 'meta.primaryCatId')) { result = false; } - if (deepAccess(bid, 'video')) { - if (!deepAccess(bid, 'video.context') || bid.video.context !== ADPOD) { + if (utils.deepAccess(bid, 'video')) { + if (!utils.deepAccess(bid, 'video.context') || bid.video.context !== ADPOD) { result = false; } - if (!deepAccess(bid, 'video.durationSeconds') || bid.video.durationSeconds <= 0) { + if (!utils.deepAccess(bid, 'video.durationSeconds') || bid.video.durationSeconds <= 0) { result = false; } else { - let isBidGood = checkBidDuration(videoMediaType, bid); + let isBidGood = checkBidDuration(bidRequest, bid); if (!isBidGood) result = false; } } if (!config.getConfig('cache.url') && bid.vastXml && !bid.vastUrl) { - logError(` + utils.logError(` This bid contains only vastXml and will not work when a prebid cache url is not specified. Try enabling prebid cache with pbjs.setConfig({ cache: {url: "..."} }); `); @@ -393,7 +379,7 @@ export function checkVideoBidSetupHook(fn, bid, adUnit, videoMediaType, context) fn.bail(result); } else { - fn.call(this, bid, adUnit, videoMediaType, context); + fn.call(this, bid, bidRequest, videoMediaType, context); } } @@ -406,7 +392,7 @@ export function adpodSetConfig(config) { if (typeof config.bidQueueTimeDelay === 'number' && config.bidQueueTimeDelay > 0) { queueTimeDelay = config.bidQueueTimeDelay; } else { - logWarn(`Detected invalid value for adpod.bidQueueTimeDelay in setConfig; must be a positive number. Using default: ${queueTimeDelay}`) + utils.logWarn(`Detected invalid value for adpod.bidQueueTimeDelay in setConfig; must be a positive number. Using default: ${queueTimeDelay}`) } } @@ -414,7 +400,7 @@ export function adpodSetConfig(config) { if (typeof config.bidQueueSizeLimit === 'number' && config.bidQueueSizeLimit > 0) { queueSizeLimit = config.bidQueueSizeLimit; } else { - logWarn(`Detected invalid value for adpod.bidQueueSizeLimit in setConfig; must be a positive number. Using default: ${queueSizeLimit}`) + utils.logWarn(`Detected invalid value for adpod.bidQueueSizeLimit in setConfig; must be a positive number. Using default: ${queueSizeLimit}`) } } } @@ -478,7 +464,7 @@ export function sortByPricePerSecond(a, b) { */ export function getTargeting({ codes, callback } = {}) { if (!callback) { - logError('No callback function was defined in the getTargeting call. Aborting getTargeting().'); + utils.logError('No callback function was defined in the getTargeting call. Aborting getTargeting().'); return; } codes = codes || []; @@ -494,7 +480,7 @@ export function getTargeting({ codes, callback } = {}) { let prioritizeDeals = config.getConfig('adpod.prioritizeDeals'); if (prioritizeDeals) { let [otherBids, highPriorityDealBids] = bids.reduce((partitions, bid) => { - let bidDealTier = deepAccess(bid, 'video.dealTier'); + let bidDealTier = utils.deepAccess(bid, 'video.dealTier'); let minDealTier = config.getConfig(`adpod.dealTier.${bid.bidderCode}.minDealTier`); if (minDealTier && bidDealTier) { if (bidDealTier >= minDealTier) { @@ -520,7 +506,7 @@ export function getTargeting({ codes, callback } = {}) { if (deferCachingEnabled === false) { adPodAdUnits.forEach((adUnit) => { let adPodTargeting = []; - let adPodDurationSeconds = deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); + let adPodDurationSeconds = utils.deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); bids .filter((bid) => bid.adUnitCode === adUnit.code) @@ -544,7 +530,7 @@ export function getTargeting({ codes, callback } = {}) { } else { let bidsToCache = []; adPodAdUnits.forEach((adUnit) => { - let adPodDurationSeconds = deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); + let adPodDurationSeconds = utils.deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); bids .filter((bid) => bid.adUnitCode === adUnit.code) @@ -560,7 +546,7 @@ export function getTargeting({ codes, callback } = {}) { if (error) { callback(error, null); } else { - let groupedBids = groupBy(bidsSuccessfullyCached, 'adUnitCode'); + let groupedBids = utils.groupBy(bidsSuccessfullyCached, 'adUnitCode'); Object.keys(groupedBids).forEach((adUnitCode) => { let adPodTargeting = []; @@ -592,7 +578,7 @@ export function getTargeting({ codes, callback } = {}) { */ function getAdPodAdUnits(codes) { return auctionManager.getAdUnits() - .filter((adUnit) => deepAccess(adUnit, 'mediaTypes.video.context') === ADPOD) + .filter((adUnit) => utils.deepAccess(adUnit, 'mediaTypes.video.context') === ADPOD) .filter((adUnit) => (codes.length > 0) ? codes.indexOf(adUnit.code) != -1 : true); } @@ -604,10 +590,10 @@ function getAdPodAdUnits(codes) { function getExclusiveBids(bidsReceived) { let bids = bidsReceived .map((bid) => Object.assign({}, bid, { [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] })); - bids = groupBy(bids, TARGETING_KEY_PB_CAT_DUR); + bids = utils.groupBy(bids, TARGETING_KEY_PB_CAT_DUR); let filteredBids = []; Object.keys(bids).forEach((targetingKey) => { - bids[targetingKey].sort(compareOn('responseTimestamp')); + bids[targetingKey].sort(utils.compareOn('responseTimestamp')); filteredBids.push(bids[targetingKey][0]); }); return filteredBids; @@ -633,8 +619,8 @@ const sharedMethods = { Object.freeze(sharedMethods); module('adpod', function shareAdpodUtilities(...args) { - if (!isPlainObject(args[0])) { - logError('Adpod module needs plain object to share methods with submodule'); + if (!utils.isPlainObject(args[0])) { + utils.logError('Adpod module needs plain object to share methods with submodule'); return; } function addMethods(object, func) { diff --git a/modules/adprimeBidAdapter.js b/modules/adprimeBidAdapter.js index d64874c393e..ef370301184 100644 --- a/modules/adprimeBidAdapter.js +++ b/modules/adprimeBidAdapter.js @@ -1,11 +1,10 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { isFn, deepAccess, logMessage } from '../src/utils.js'; -import { config } from '../src/config.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'adprime'; const AD_URL = 'https://delta.adprime.com/pbjs'; -const SYNC_URL = 'https://sync.adprime.com'; +const SYNC_URL = 'https://delta.adprime.com'; function isBidResponseValid(bid) { if (!bid.requestId || !bid.cpm || !bid.creativeId || @@ -25,8 +24,8 @@ function isBidResponseValid(bid) { } function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidfloor', 0); + if (!utils.isFn(bid.getFloor)) { + return utils.deepAccess(bid, 'params.bidfloor', 0); } try { @@ -57,7 +56,7 @@ export const spec = { winTop = window.top; } catch (e) { location = winTop.location; - logMessage(e); + utils.logMessage(e); }; let placements = []; let request = { @@ -151,8 +150,7 @@ export const spec = { }, getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { - let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; - let syncUrl = SYNC_URL + `/${syncType}?pbjs=1`; + let syncUrl = SYNC_URL if (gdprConsent && gdprConsent.consentString) { if (typeof gdprConsent.gdprApplies === 'boolean') { syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; @@ -163,15 +161,12 @@ export const spec = { if (uspConsent && uspConsent.consentString) { syncUrl += `&ccpa_consent=${uspConsent.consentString}`; } - - const coppa = config.getConfig('coppa') ? 1 : 0; - syncUrl += `&coppa=${coppa}`; - return [{ - type: syncType, + type: 'image', url: syncUrl }]; } + }; registerBidder(spec); diff --git a/modules/adqueryBidAdapter.js b/modules/adqueryBidAdapter.js deleted file mode 100644 index 348bdc90808..00000000000 --- a/modules/adqueryBidAdapter.js +++ /dev/null @@ -1,204 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER} from '../src/mediaTypes.js'; -import { logInfo, buildUrl, triggerPixel } from '../src/utils.js'; -import { getStorageManager } from '../src/storageManager.js'; - -const ADQUERY_GVLID = 902; -const ADQUERY_BIDDER_CODE = 'adquery'; -const ADQUERY_BIDDER_DOMAIN_PROTOCOL = 'https'; -const ADQUERY_BIDDER_DOMAIN = 'bidder.adquery.io'; -const ADQUERY_USER_SYNC_DOMAIN = ADQUERY_BIDDER_DOMAIN_PROTOCOL + '://' + ADQUERY_BIDDER_DOMAIN + '/prebid/userSync?1=1'; -const ADQUERY_DEFAULT_CURRENCY = 'PLN'; -const ADQUERY_NET_REVENUE = true; -const ADQUERY_TTL = 360; -const storage = getStorageManager({gvlid: ADQUERY_GVLID, bidderCode: ADQUERY_BIDDER_CODE}); - -/** @type {BidderSpec} */ -export const spec = { - code: ADQUERY_BIDDER_CODE, - gvlid: ADQUERY_GVLID, - supportedMediaTypes: [BANNER], - - /** f - * @param {object} bid - * @return {boolean} - */ - isBidRequestValid: (bid) => { - return !!(bid && bid.params && bid.params.placementId) - }, - - /** - * @param {BidRequest[]} bidRequests - * @param {*} bidderRequest - * @return {ServerRequest} - */ - buildRequests: (bidRequests, bidderRequest) => { - const requests = []; - for (let i = 0, len = bidRequests.length; i < len; i++) { - const request = { - method: 'POST', - url: ADQUERY_BIDDER_DOMAIN_PROTOCOL + '://' + ADQUERY_BIDDER_DOMAIN + '/prebid/bid', - data: buildRequest(bidRequests[i], bidderRequest), - options: { - withCredentials: false, - crossOrigin: true - } - }; - requests.push(request); - } - return requests; - }, - - /** - * @param {*} response - * @param {ServerRequest} request - * @return {Bid[]} - */ - interpretResponse: (response, request) => { - logInfo(request); - logInfo(response); - - const res = response && response.body && response.body.data; - let bidResponses = []; - - if (!res) { - return []; - } - - const bidResponse = { - requestId: res.requestId, - cpm: res.cpm, - width: res.mediaType.width, - height: res.mediaType.height, - creativeId: res.creationId, - dealId: res.dealid || '', - currency: res.currency || ADQUERY_DEFAULT_CURRENCY, - netRevenue: ADQUERY_NET_REVENUE, - ttl: ADQUERY_TTL, - referrer: '', - ad: '' + res.tag, - mediaType: res.mediaType.name || 'banner', - meta: { - advertiserDomains: res.adDomains && res.adDomains.length ? res.adDomains : [], - mediaType: res.mediaType.name || 'banner', - } - }; - bidResponses.push(bidResponse); - logInfo('bidResponses', bidResponses); - - return bidResponses; - }, - - /** - * @param {TimedOutBid} timeoutData - */ - onTimeout: (timeoutData) => { - if (timeoutData == null) { - return; - } - logInfo('onTimeout ', timeoutData); - let params = { - bidder: timeoutData.bidder, - bId: timeoutData.bidId, - adUnitCode: timeoutData.adUnitCode, - timeout: timeoutData.timeout, - auctionId: timeoutData.auctionId, - }; - let adqueryRequestUrl = buildUrl({ - protocol: ADQUERY_BIDDER_DOMAIN_PROTOCOL, - hostname: ADQUERY_BIDDER_DOMAIN, - pathname: '/prebid/eventTimeout', - search: params - }); - triggerPixel(adqueryRequestUrl); - }, - - /** - * @param {Bid} bid - */ - onBidWon: (bid) => { - logInfo('onBidWon', bid); - const bidString = JSON.stringify(bid); - const encodedBuf = window.btoa(bidString); - - let params = { - q: encodedBuf, - }; - let adqueryRequestUrl = buildUrl({ - protocol: ADQUERY_BIDDER_DOMAIN_PROTOCOL, - hostname: ADQUERY_BIDDER_DOMAIN, - pathname: '/prebid/eventBidWon', - search: params - }); - triggerPixel(adqueryRequestUrl); - }, - - /** - * @param {Bid} bid - */ - onSetTargeting: (bid) => { - logInfo('onSetTargeting', bid); - - let params = { - bidder: bid.bidder, - width: bid.width, - height: bid.height, - bid: bid.adId, - mediaType: bid.mediaType, - cpm: bid.cpm, - requestId: bid.requestId, - adUnitCode: bid.adUnitCode - }; - - let adqueryRequestUrl = buildUrl({ - protocol: ADQUERY_BIDDER_DOMAIN_PROTOCOL, - hostname: ADQUERY_BIDDER_DOMAIN, - pathname: '/prebid/eventSetTargeting', - search: params - }); - triggerPixel(adqueryRequestUrl); - }, - getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { - let syncUrl = ADQUERY_USER_SYNC_DOMAIN; - if (gdprConsent && gdprConsent.consentString) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; - } - } - if (uspConsent && uspConsent.consentString) { - syncUrl += `&ccpa_consent=${uspConsent.consentString}`; - } - return [{ - type: 'image', - url: syncUrl - }]; - } - -}; -function buildRequest(validBidRequests, bidderRequest) { - let qid = Math.random().toString(36).substring(2) + Date.now().toString(36); - let bid = validBidRequests; - - if (storage.getDataFromLocalStorage('qid')) { - qid = storage.getDataFromLocalStorage('qid'); - } else { - storage.setDataInLocalStorage('qid', qid); - } - - return { - placementCode: bid.params.placementId, - auctionId: bid.auctionId, - qid: qid, - type: bid.params.type, - adUnitCode: bid.adUnitCode, - bidId: bid.bidId, - bidder: bid.bidder, - bidderRequestId: bid.bidderRequestId, - bidRequestsCount: bid.bidRequestsCount, - bidderRequestsCount: bid.bidderRequestsCount, - }; -} - -registerBidder(spec); diff --git a/modules/adqueryBidAdapter.md b/modules/adqueryBidAdapter.md deleted file mode 100644 index e8b68e30406..00000000000 --- a/modules/adqueryBidAdapter.md +++ /dev/null @@ -1,32 +0,0 @@ -# Overview - -Module Name: Adquery Bidder Adapter -Module Type: Bidder Adapter -Maintainer: prebid@adquery.com - -# Description - -Module that connects to Adquery's demand sources. - -# Test Parameters -``` - var adUnits = [ - { - code: 'banner-adquery-div', - mediaTypes: { - banner: { - sizes: [[300, 250]], - } - }, - bids: [ - { - bidder: 'adquery', - params: { - placementId: '6d93f2a0e5f0fe2cc3a6e9e3ade964b43b07f897', - type: 'banner300x250' - } - } - ] - } - ]; -``` diff --git a/modules/adqueryIdSystem.js b/modules/adqueryIdSystem.js deleted file mode 100644 index 85421bf588d..00000000000 --- a/modules/adqueryIdSystem.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * This module adds Adquery QID to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/adqueryIdSystem - * @requires module:modules/userId - */ - -import {ajax} from '../src/ajax.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {submodule} from '../src/hook.js'; -import * as utils from '../src/utils.js'; - -const MODULE_NAME = 'qid'; -const AU_GVLID = 902; - -export const storage = getStorageManager({gvlid: AU_GVLID, moduleName: 'qid'}); - -/** - * Param or default. - * @param {String} param - * @param {String} defaultVal - */ -function paramOrDefault(param, defaultVal, arg) { - if (utils.isFn(param)) { - return param(arg); - } else if (utils.isStr(param)) { - return param; - } - return defaultVal; -} - -/** @type {Submodule} */ -export const adqueryIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - - /** - * IAB TCF Vendor ID - * @type {string} - */ - gvlid: AU_GVLID, - - /** - * decode the stored id value for passing to bid requests - * @function - * @param {{value:string}} value - * @returns {{qid:Object}} - */ - decode(value) { - let qid = storage.getDataFromLocalStorage('qid'); - if (utils.isStr(qid)) { - return {qid: qid}; - } - return (value && typeof value['qid'] === 'string') ? { 'qid': value['qid'] } : undefined; - }, - /** - * performs action to obtain id and return a value in the callback's response argument - * @function - * @param {SubmoduleConfig} [config] - * @returns {IdResponse|undefined} - */ - getId(config) { - if (!utils.isPlainObject(config.params)) { - config.params = {}; - } - const url = paramOrDefault(config.params.url, - `https://bidder.adquery.io/prebid/qid`, - config.params.urlArg); - - const resp = function (callback) { - let qid = storage.getDataFromLocalStorage('qid'); - if (utils.isStr(qid)) { - const responseObj = {qid: qid}; - callback(responseObj); - } else { - const callbacks = { - success: response => { - let responseObj; - if (response) { - try { - responseObj = JSON.parse(response); - } catch (error) { - utils.logError(error); - } - } - callback(responseObj); - }, - error: error => { - utils.logError(`${MODULE_NAME}: ID fetch encountered an error`, error); - callback(); - } - }; - ajax(url, callbacks, undefined, {method: 'GET'}); - } - }; - return {callback: resp}; - } -}; - -submodule('userId', adqueryIdSubmodule); diff --git a/modules/adqueryIdSystem.md b/modules/adqueryIdSystem.md deleted file mode 100644 index 3a49ffbe4da..00000000000 --- a/modules/adqueryIdSystem.md +++ /dev/null @@ -1,35 +0,0 @@ -# Adquery QID - -Adquery QID Module. For assistance setting up your module please contact us at [prebid@adquery.io](prebid@adquery.io). - -### Prebid Params - -Individual params may be set for the Adquery ID Submodule. At least one identifier must be set in the params. - -``` -pbjs.setConfig({ - usersync: { - userIds: [{ - name: 'qid', - storage: { - name: 'qid', - type: 'html5' - } - }] - } -}); -``` -## Parameter Descriptions for the `usersync` Configuration Section -The below parameters apply only to the Adquery User ID Module integration. - -| Param under usersync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | ID value for the Adquery ID module - `"qid"` | `"qid"` | -| storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. | | -| storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` | -| storage.name | Required | String | The name of the html5 local storage where the user ID will be stored. | `"qid"` | -| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. | `365` | -| value | Optional | Object | Used only if the page has a separate mechanism for storing the Adquery ID. The value is an object containing the values to be sent to the adapters. In this scenario, no URL is called and nothing is added to local storage | `{"qid": "2abf9f001fcd81241b67"}` | -| params | Optional | Object | Used to store params for the id system | -| params.url | Optional | String | Set an alternate GET url for qid with this parameter | -| params.urlArg | Optional | Object | Optional url parameter for params.url | diff --git a/modules/adrelevantisBidAdapter.js b/modules/adrelevantisBidAdapter.js index 3d4de7c7b9d..b6832cfeb0d 100644 --- a/modules/adrelevantisBidAdapter.js +++ b/modules/adrelevantisBidAdapter.js @@ -1,26 +1,11 @@ -import {Renderer} from '../src/Renderer.js'; -import { - chunk, - convertCamelToUnderscore, - convertTypes, - createTrackPixelHtml, - deepAccess, - deepClone, - getBidRequest, - isArray, - isArrayOfNums, - isEmpty, - isStr, - logError, - logMessage, - logWarn, - transformBidderParamKeywords -} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {find, includes} from '../src/polyfill.js'; -import {INSTREAM, OUTSTREAM} from '../src/video.js'; +import { Renderer } from '../src/Renderer.js'; +import * as utils from '../src/utils.js'; +import { config } from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import { OUTSTREAM, INSTREAM } from '../src/video.js'; const BIDDER_CODE = 'adrelevantis'; const URL = 'https://ssp.adrelevantis.com/prebid'; @@ -139,7 +124,7 @@ export const spec = { if (fpdcfg && fpdcfg.context) { let fdata = { keywords: fpdcfg.context.keywords || '', - category: fpdcfg.context.data.category || '' + category: fpdcfg.context.category || '' } payload.fpd = fdata; } @@ -160,7 +145,7 @@ export const spec = { if (!serverResponse || serverResponse.error) { let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } - logError(errorMessage); + utils.logError(errorMessage); return bids; } @@ -181,9 +166,9 @@ export const spec = { }, transformBidParams: function(params, isOpenRtb) { - params = convertTypes({ + params = utils.convertTypes({ 'placementId': 'number', - 'keywords': transformBidderParamKeywords + 'keywords': utils.transformBidderParamKeywords }, params); if (isOpenRtb) { @@ -195,7 +180,7 @@ export const spec = { } Object.keys(params).forEach(paramKey => { - let convertedKey = convertCamelToUnderscore(paramKey); + let convertedKey = utils.convertCamelToUnderscore(paramKey); if (convertedKey !== paramKey) { params[convertedKey] = params[paramKey]; delete params[paramKey]; @@ -208,7 +193,7 @@ export const spec = { } function isPopulatedArray(arr) { - return !!(isArray(arr) && arr.length > 0); + return !!(utils.isArray(arr) && arr.length > 0); } function deleteValues(keyPairObj) { @@ -221,9 +206,9 @@ function formatRequest(payload, bidderRequest) { let request = []; if (payload.tags.length > MAX_IMPS_PER_REQUEST) { - const clonedPayload = deepClone(payload); + const clonedPayload = utils.deepClone(payload); - chunk(payload.tags, MAX_IMPS_PER_REQUEST).forEach(tags => { + utils.chunk(payload.tags, MAX_IMPS_PER_REQUEST).forEach(tags => { clonedPayload.tags = tags; const payloadString = JSON.stringify(clonedPayload); request.push({ @@ -258,14 +243,14 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { try { renderer.setRender(outstreamRender); } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); + utils.logWarn('Prebid Error calling setRender on renderer', err); } renderer.setEventHandlers({ - impression: () => logMessage('AdRelevantis outstream video impression event'), - loaded: () => logMessage('AdRelevantis outstream video loaded event'), + impression: () => utils.logMessage('AdRelevantis outstream video impression event'), + loaded: () => utils.logMessage('AdRelevantis outstream video loaded event'), ended: () => { - logMessage('AdRelevantis outstream renderer video event'); + utils.logMessage('AdRelevantis outstream renderer video event'); document.querySelector(`#${adUnitCode}`).style.display = 'none'; } }); @@ -310,7 +295,7 @@ function handleOutstreamRendererEvents(bid, id, eventName) { * @return Bid */ function newBid(serverBid, rtbBid, bidderRequest) { - const bidRequest = getBidRequest(serverBid.uuid, [bidderRequest]); + const bidRequest = utils.getBidRequest(serverBid.uuid, [bidderRequest]); const bid = { requestId: serverBid.uuid, cpm: rtbBid.cpm, @@ -339,7 +324,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { ttl: 3600 }); - const videoContext = deepAccess(bidRequest, 'mediaTypes.video.context'); + const videoContext = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); switch (videoContext) { case OUTSTREAM: bid.adResponse = serverBid; @@ -349,7 +334,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { if (rtbBid.renderer_url) { const videoBid = find(bidderRequest.bids, bid => bid.bidId === serverBid.uuid); - const rendererOptions = deepAccess(videoBid, 'renderer.options'); + const rendererOptions = utils.deepAccess(videoBid, 'renderer.options'); bid.renderer = newRenderer(bid.adUnitCode, rtbBid, rendererOptions); } break; @@ -369,7 +354,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { if (jsTrackers == undefined) { jsTrackers = jsTrackerDisarmed; - } else if (isStr(jsTrackers)) { + } else if (utils.isStr(jsTrackers)) { jsTrackers = [jsTrackers, jsTrackerDisarmed]; } else { jsTrackers.push(jsTrackerDisarmed); @@ -417,10 +402,10 @@ function newBid(serverBid, rtbBid, bidderRequest) { }); try { const url = rtbBid.rtb.trackers[0].impression_urls[0]; - const tracker = createTrackPixelHtml(url); + const tracker = utils.createTrackPixelHtml(url); bid.ad += tracker; } catch (error) { - logError('Error appending tracking pixel', error); + utils.logError('Error appending tracking pixel', error); } } @@ -464,8 +449,8 @@ function bidToTag(bid) { if (bid.params.externalImpId) { tag.external_imp_id = bid.params.externalImpId; } - if (!isEmpty(bid.params.keywords)) { - let keywords = transformBidderParamKeywords(bid.params.keywords); + if (!utils.isEmpty(bid.params.keywords)) { + let keywords = utils.transformBidderParamKeywords(bid.params.keywords); if (keywords.length > 0) { keywords.forEach(deleteValues); @@ -476,7 +461,7 @@ function bidToTag(bid) { tag.category = bid.params.category; } - if (bid.mediaType === NATIVE || deepAccess(bid, `mediaTypes.${NATIVE}`)) { + if (bid.mediaType === NATIVE || utils.deepAccess(bid, `mediaTypes.${NATIVE}`)) { tag.ad_types.push(NATIVE); if (tag.sizes.length === 0) { tag.sizes = transformSizes([1, 1]); @@ -488,8 +473,8 @@ function bidToTag(bid) { } } - const videoMediaType = deepAccess(bid, `mediaTypes.${VIDEO}`); - const context = deepAccess(bid, 'mediaTypes.video.context'); + const videoMediaType = utils.deepAccess(bid, `mediaTypes.${VIDEO}`); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); tag.hb_source = 1; if (bid.mediaType === VIDEO || videoMediaType) { @@ -514,7 +499,7 @@ function bidToTag(bid) { } if ( - (isEmpty(bid.mediaType) && isEmpty(bid.mediaTypes)) || + (utils.isEmpty(bid.mediaType) && utils.isEmpty(bid.mediaTypes)) || (bid.mediaType === BANNER || (bid.mediaTypes && bid.mediaTypes[BANNER])) ) { tag.ad_types.push(BANNER); @@ -528,8 +513,8 @@ function transformSizes(requestSizes) { let sizes = []; let sizeObj = {}; - if (isArray(requestSizes) && requestSizes.length === 2 && - !isArray(requestSizes[0])) { + if (utils.isArray(requestSizes) && requestSizes.length === 2 && + !utils.isArray(requestSizes[0])) { sizeObj.width = parseInt(requestSizes[0], 10); sizeObj.height = parseInt(requestSizes[1], 10); sizes.push(sizeObj); @@ -590,7 +575,7 @@ function buildNativeRequest(params) { const isImageAsset = !!(requestKey === NATIVE_MAPPING.image.serverName || requestKey === NATIVE_MAPPING.icon.serverName); if (isImageAsset && request[requestKey].sizes) { let sizes = request[requestKey].sizes; - if (isArrayOfNums(sizes) || (isArray(sizes) && sizes.length > 0 && sizes.every(sz => isArrayOfNums(sz)))) { + if (utils.isArrayOfNums(sizes) || (utils.isArray(sizes) && sizes.length > 0 && sizes.every(sz => utils.isArrayOfNums(sz)))) { request[requestKey].sizes = transformSizes(request[requestKey].sizes); } } diff --git a/modules/adrinoBidAdapter.js b/modules/adrinoBidAdapter.js deleted file mode 100644 index 4520066c3e7..00000000000 --- a/modules/adrinoBidAdapter.js +++ /dev/null @@ -1,74 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {triggerPixel} from '../src/utils.js'; -import {NATIVE} from '../src/mediaTypes.js'; - -const BIDDER_CODE = 'adrino'; -const REQUEST_METHOD = 'POST'; -const BIDDER_HOST = 'https://prd-prebid-bidder.adrino.io'; -const GVLID = 1072; - -export const spec = { - code: BIDDER_CODE, - gvlid: GVLID, - supportedMediaTypes: [NATIVE], - - isBidRequestValid: function (bid) { - return !!(bid.bidId) && - !!(bid.params) && - !!(bid.params.hash) && - (typeof bid.params.hash === 'string') && - !!(bid.mediaTypes) && - Object.keys(bid.mediaTypes).includes(NATIVE) && - (bid.bidder === BIDDER_CODE); - }, - - buildRequests: function (validBidRequests, bidderRequest) { - const bidRequests = []; - - for (let i = 0; i < validBidRequests.length; i++) { - let requestData = { - bidId: validBidRequests[i].bidId, - nativeParams: validBidRequests[i].nativeParams, - placementHash: validBidRequests[i].params.hash, - referer: bidderRequest.refererInfo.referer, - userAgent: navigator.userAgent, - } - - if (bidderRequest && bidderRequest.gdprConsent) { - requestData.gdprConsent = { - consentString: bidderRequest.gdprConsent.consentString, - consentRequired: bidderRequest.gdprConsent.gdprApplies - } - } - - bidRequests.push({ - method: REQUEST_METHOD, - url: BIDDER_HOST + '/bidder/bid/', - data: requestData, - options: { - contentType: 'application/json', - withCredentials: false, - } - }); - } - - return bidRequests; - }, - - interpretResponse: function (serverResponse, bidRequest) { - const response = serverResponse.body; - const bidResponses = []; - if (!response.noAd) { - bidResponses.push(response); - } - return bidResponses; - }, - - onBidWon: function (bid) { - if (bid['requestId']) { - triggerPixel(BIDDER_HOST + '/bidder/won/' + bid['requestId']); - } - } -}; - -registerBidder(spec); diff --git a/modules/adrinoBidAdapter.md b/modules/adrinoBidAdapter.md deleted file mode 100644 index 5ec63a72736..00000000000 --- a/modules/adrinoBidAdapter.md +++ /dev/null @@ -1,45 +0,0 @@ -# Overview - -``` -Module Name: Adrino Bidder Adapter -Module Type: Bidder Adapter -Maintainer: dev@adrino.pl -``` - -# Description - -Module connects to Adrino bidder to fetch bids. Only native format is supported. - -# Test Parameters - -``` -var adUnits = [ - code: '/12345678/prebid_native_example_1', - mediaTypes: { - native: { - image: { - required: true, - sizes: [[300, 210],[300,150],[140,100]] - }, - title: { - required: true - }, - sponsoredBy: { - required: false - }, - body: { - required: false - }, - icon: { - required: false - } - } - }, - bids: [{ - bidder: 'adrino', - params: { - hash: 'abcdef123456' - } - }] -]; -``` diff --git a/modules/adriverBidAdapter.js b/modules/adriverBidAdapter.js index 5ab417520e9..d5a777f6111 100644 --- a/modules/adriverBidAdapter.js +++ b/modules/adriverBidAdapter.js @@ -1,14 +1,13 @@ // ADRIVER BID ADAPTER for Prebid 1.13 -import { logInfo, getWindowLocation, getBidIdParameter, _each } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import { getStorageManager } from '../src/storageManager.js'; const BIDDER_CODE = 'adriver'; const ADRIVER_BID_URL = 'https://pb.adriver.ru/cgi-bin/bid.cgi'; const TIME_TO_LIVE = 3000; -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); export const spec = { + code: BIDDER_CODE, /** @@ -22,12 +21,12 @@ export const spec = { }, buildRequests: function (validBidRequests, bidderRequest) { - logInfo('validBidRequests', validBidRequests); + utils.logInfo('validBidRequests', validBidRequests); - let win = getWindowLocation(); + let win = utils.getWindowLocation(); let customID = Math.round(Math.random() * 999999999) + '-' + Math.round(new Date() / 1000) + '-1-46-'; - let siteId = getBidIdParameter('siteid', validBidRequests[0].params) + ''; - let currency = getBidIdParameter('currency', validBidRequests[0].params); + let siteId = utils.getBidIdParameter('siteid', validBidRequests[0].params) + ''; + let currency = utils.getBidIdParameter('currency', validBidRequests[0].params); currency = 'RUB'; let timeout = null; @@ -59,8 +58,8 @@ export const spec = { 'imp': [] }; - _each(validBidRequests, (bid) => { - _each(bid.sizes, (sizes) => { + utils._each(validBidRequests, (bid) => { + utils._each(bid.sizes, (sizes) => { let width; let height; let par; @@ -68,7 +67,7 @@ export const spec = { let floorAndCurrency = _getFloor(bid, currency, sizes); let bidFloor = floorAndCurrency.floor; - let dealId = getBidIdParameter('dealid', bid.params); + let dealId = utils.getBidIdParameter('dealid', bid.params); if (typeof sizes[0] === 'number' && typeof sizes[1] === 'number') { width = sizes[0]; height = sizes[1]; @@ -94,20 +93,11 @@ export const spec = { }] }; } - logInfo('par', par); + utils.logInfo('par', par); payload.imp.push(par); }); }); - let userid = validBidRequests[0].userId; - let adrcidCookie = storage.getDataFromLocalStorage('adrcid') || validBidRequests[0].userId.adrcid; - - if (adrcidCookie) { - payload.adrcid = adrcidCookie; - payload.id5 = userid.id5id; - payload.sharedid = userid.pubcid; - payload.unifiedid = userid.tdid; - } const payloadString = JSON.stringify(payload); return { @@ -118,11 +108,11 @@ export const spec = { }, interpretResponse: function (serverResponse, bidRequest) { - logInfo('serverResponse.body.seatbid', serverResponse.body.seatbid); + utils.logInfo('serverResponse.body.seatbid', serverResponse.body.seatbid); const bidResponses = []; let nurl = 0; - _each(serverResponse.body.seatbid, (seatbid) => { - logInfo('_each', seatbid); + utils._each(serverResponse.body.seatbid, (seatbid) => { + utils.logInfo('_each', seatbid); var bid = seatbid.bid[0]; if (bid.nurl !== undefined) { nurl = bid.nurl.split('://'); @@ -145,7 +135,7 @@ export const spec = { }, ad: '' }; - logInfo('bidResponse', bidResponse); + utils.logInfo('bidResponse', bidResponse); bidResponses.push(bidResponse); } }); diff --git a/modules/adriverIdSystem.js b/modules/adriverIdSystem.js deleted file mode 100644 index 6a492fac508..00000000000 --- a/modules/adriverIdSystem.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * This module adds AdriverId to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/adriverIdSubmodule - * @requires module:modules/userId - */ - -import { logError, isPlainObject } from '../src/utils.js' -import { ajax } from '../src/ajax.js'; -import { submodule } from '../src/hook.js'; -import { getStorageManager } from '../src/storageManager.js'; - -const MODULE_NAME = 'adriverId'; - -export const storage = getStorageManager(); - -/** @type {Submodule} */ -export const adriverIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - /** - * decode the stored id value for passing to bid requests - * @function - * @param {string} value - * @returns {{adriverId:string}} - */ - decode(value) { - return { adrcid: value } - }, - /** - * performs action to obtain id and return a value in the callback's response argument - * @function - * @param {SubmoduleConfig} [config] - * @param {ConsentData} [consentData] - * @returns {IdResponse|undefined} - */ - getId(config) { - if (!isPlainObject(config.params)) { - config.params = {}; - } - const url = 'https://ad.adriver.ru/cgi-bin/json.cgi?sid=1&ad=719473&bt=55&pid=3198680&bid=7189165&bn=7189165&tuid=1'; - const resp = function (callback) { - let creationDate = storage.getDataFromLocalStorage('adrcid_cd') || storage.getCookie('adrcid_cd'); - let cookie = storage.getDataFromLocalStorage('adrcid') || storage.getCookie('adrcid'); - - if (cookie && creationDate && ((new Date().getTime() - creationDate) < 86400000)) { - const responseObj = cookie; - callback(responseObj); - } else { - const callbacks = { - success: response => { - let responseObj; - if (response) { - try { - responseObj = JSON.parse(response).adrcid; - } catch (error) { - logError(error); - } - let now = new Date(); - now.setTime(now.getTime() + 86400 * 1825 * 1000); - storage.setCookie('adrcid', responseObj, now.toUTCString(), 'Lax'); - storage.setDataInLocalStorage('adrcid', responseObj); - storage.setCookie('adrcid_cd', new Date().getTime(), now.toUTCString(), 'Lax'); - storage.setDataInLocalStorage('adrcid_cd', new Date().getTime()); - } - callback(responseObj); - }, - error: error => { - logError(`${MODULE_NAME}: ID fetch encountered an error`, error); - callback(); - } - }; - ajax(url, callbacks, undefined, {method: 'GET'}); - } - }; - return {callback: resp}; - } -}; - -submodule('userId', adriverIdSubmodule); diff --git a/modules/adriverIdSystem.md b/modules/adriverIdSystem.md deleted file mode 100644 index 797318ba977..00000000000 --- a/modules/adriverIdSystem.md +++ /dev/null @@ -1,19 +0,0 @@ -# Overview - -Module Name: AdRiver Id System -Module Type: User Id System -Maintainer: support@adriver.ru - -# Description - -Adriver user identification system - -## Example configuration for publishers: - -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'adriverId' - }] - } -}); \ No newline at end of file diff --git a/modules/adtargetBidAdapter.js b/modules/adtargetBidAdapter.js index a07b0de0f67..1779ba94371 100644 --- a/modules/adtargetBidAdapter.js +++ b/modules/adtargetBidAdapter.js @@ -1,8 +1,8 @@ -import {_map, chunk, deepAccess, flatten, isArray, logError, parseSizesInput} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {find} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import find from 'core-js-pure/features/array/find.js'; const ENDPOINT = 'https://ghb.console.adtarget.com.tr/v2/auction/'; const BIDDER_CODE = 'adtarget'; @@ -13,7 +13,7 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid: function (bid) { - return !!deepAccess(bid, 'params.aid'); + return !!utils.deepAccess(bid, 'params.aid'); }, getUserSyncs: function (syncOptions, serverResponses) { const syncs = []; @@ -42,9 +42,9 @@ export const spec = { } if (syncOptions.pixelEnabled || syncOptions.iframeEnabled) { - isArray(serverResponses) && serverResponses.forEach((response) => { + utils.isArray(serverResponses) && serverResponses.forEach((response) => { if (response.body) { - if (isArray(response.body)) { + if (utils.isArray(response.body)) { response.body.forEach(b => { addSyncs(b); }) @@ -59,10 +59,10 @@ export const spec = { buildRequests: function (bidRequests, adapterRequest) { const adapterSettings = config.getConfig(adapterRequest.bidderCode) - const chunkSize = deepAccess(adapterSettings, 'chunkSize', 10); + const chunkSize = utils.deepAccess(adapterSettings, 'chunkSize', 10); const { tag, bids } = bidToTag(bidRequests, adapterRequest); - const bidChunks = chunk(bids, chunkSize); - return _map(bidChunks, (bids) => { + const bidChunks = utils.chunk(bids, chunkSize); + return utils._map(bidChunks, (bids) => { return { data: Object.assign({}, tag, { BidRequests: bids }), adapterRequest, @@ -75,12 +75,12 @@ export const spec = { serverResponse = serverResponse.body; let bids = []; - if (!isArray(serverResponse)) { + if (!utils.isArray(serverResponse)) { return parseResponse(serverResponse, adapterRequest); } serverResponse.forEach(serverBidResponse => { - bids = flatten(bids, parseResponse(serverBidResponse, adapterRequest)); + bids = utils.flatten(bids, parseResponse(serverBidResponse, adapterRequest)); }); return bids; @@ -88,14 +88,14 @@ export const spec = { }; function parseResponse(serverResponse, adapterRequest) { - const isInvalidValidResp = !serverResponse || !isArray(serverResponse.bids); + const isInvalidValidResp = !serverResponse || !utils.isArray(serverResponse.bids); const bids = []; if (isInvalidValidResp) { const extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; const errorMessage = `in response for ${adapterRequest.bidderCode} adapter ${extMessage}`; - logError(errorMessage); + utils.logError(errorMessage); return bids; } @@ -117,23 +117,23 @@ function parseResponse(serverResponse, adapterRequest) { function bidToTag(bidRequests, adapterRequest) { const tag = { - Domain: deepAccess(adapterRequest, 'refererInfo.referer') + Domain: utils.deepAccess(adapterRequest, 'refererInfo.referer') }; if (config.getConfig('coppa') === true) { tag.Coppa = 1; } - if (deepAccess(adapterRequest, 'gdprConsent.gdprApplies')) { + if (utils.deepAccess(adapterRequest, 'gdprConsent.gdprApplies')) { tag.GDPR = 1; - tag.GDPRConsent = deepAccess(adapterRequest, 'gdprConsent.consentString'); + tag.GDPRConsent = utils.deepAccess(adapterRequest, 'gdprConsent.consentString'); } - if (deepAccess(adapterRequest, 'uspConsent')) { - tag.USP = deepAccess(adapterRequest, 'uspConsent'); + if (utils.deepAccess(adapterRequest, 'uspConsent')) { + tag.USP = utils.deepAccess(adapterRequest, 'uspConsent'); } - if (deepAccess(bidRequests[0], 'schain')) { - tag.Schain = deepAccess(bidRequests[0], 'schain'); + if (utils.deepAccess(bidRequests[0], 'schain')) { + tag.Schain = utils.deepAccess(bidRequests[0], 'schain'); } - if (deepAccess(bidRequests[0], 'userId')) { - tag.UserIds = deepAccess(bidRequests[0], 'userId'); + if (utils.deepAccess(bidRequests[0], 'userId')) { + tag.UserIds = utils.deepAccess(bidRequests[0], 'userId'); } const bids = [] @@ -147,19 +147,19 @@ function bidToTag(bidRequests, adapterRequest) { } function prepareBidRequests(bidReq) { - const mediaType = deepAccess(bidReq, 'mediaTypes.video') ? VIDEO : DISPLAY; - const sizes = mediaType === VIDEO ? deepAccess(bidReq, 'mediaTypes.video.playerSize') : deepAccess(bidReq, 'mediaTypes.banner.sizes'); + const mediaType = utils.deepAccess(bidReq, 'mediaTypes.video') ? VIDEO : DISPLAY; + const sizes = mediaType === VIDEO ? utils.deepAccess(bidReq, 'mediaTypes.video.playerSize') : utils.deepAccess(bidReq, 'mediaTypes.banner.sizes'); const bidReqParams = { 'CallbackId': bidReq.bidId, 'Aid': bidReq.params.aid, 'AdType': mediaType, - 'Sizes': parseSizesInput(sizes).join(',') + 'Sizes': utils.parseSizesInput(sizes).join(',') }; return bidReqParams; } function getMediaType(bidderRequest) { - return deepAccess(bidderRequest, 'mediaTypes.video') ? VIDEO : BANNER; + return utils.deepAccess(bidderRequest, 'mediaTypes.video') ? VIDEO : BANNER; } function createBid(bidResponse, bidRequest) { diff --git a/modules/adtelligentBidAdapter.js b/modules/adtelligentBidAdapter.js index d8638c4da47..e1c6dc1ca35 100644 --- a/modules/adtelligentBidAdapter.js +++ b/modules/adtelligentBidAdapter.js @@ -1,9 +1,9 @@ -import {_map, chunk, convertTypes, deepAccess, flatten, isArray, parseSizesInput} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {ADPOD, BANNER, VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {Renderer} from '../src/Renderer.js'; -import {find} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { ADPOD, BANNER, VIDEO } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import { Renderer } from '../src/Renderer.js'; +import find from 'core-js-pure/features/array/find.js'; const subdomainSuffixes = ['', 1, 2]; const AUCTION_PATH = '/v2/auction/'; @@ -18,9 +18,8 @@ const HOST_GETTERS = { navelix: () => 'ghb.hb.navelix.com', appaloosa: () => 'ghb.hb.appaloosa.media', onefiftytwomedia: () => 'ghb.ads.152media.com', + mediafuse: () => 'ghb.hbmp.mediafuse.com', bidsxchange: () => 'ghb.hbd.bidsxchange.com', - streamkey: () => 'ghb.hb.streamkey.net', - janet: () => 'ghb.bidder.jmgads.com', } const getUri = function (bidderCode) { let bidderWithoutSuffix = bidderCode.split('_')[0]; @@ -36,12 +35,16 @@ const syncsCache = {}; export const spec = { code: BIDDER_CODE, gvlid: 410, - aliases: ['onefiftytwomedia', 'selectmedia', 'appaloosa', 'bidsxchange', 'streamkey', 'janet', - { code: 'navelix', gvlid: 380 } + aliases: ['onefiftytwomedia', 'selectmedia', 'appaloosa', 'bidsxchange', + { code: 'navelix', gvlid: 380 }, + { + code: 'mediafuse', + skipPbsAliasing: true + } ], supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid: function (bid) { - return !!deepAccess(bid, 'params.aid'); + return !!utils.deepAccess(bid, 'params.aid'); }, getUserSyncs: function (syncOptions, serverResponses) { const syncs = []; @@ -70,9 +73,9 @@ export const spec = { } if (syncOptions.pixelEnabled || syncOptions.iframeEnabled) { - isArray(serverResponses) && serverResponses.forEach((response) => { + utils.isArray(serverResponses) && serverResponses.forEach((response) => { if (response.body) { - if (isArray(response.body)) { + if (utils.isArray(response.body)) { response.body.forEach(b => { addSyncs(b); }) @@ -91,10 +94,10 @@ export const spec = { */ buildRequests: function (bidRequests, adapterRequest) { const adapterSettings = config.getConfig(adapterRequest.bidderCode) - const chunkSize = deepAccess(adapterSettings, 'chunkSize', 10); + const chunkSize = utils.deepAccess(adapterSettings, 'chunkSize', 10); const { tag, bids } = bidToTag(bidRequests, adapterRequest); - const bidChunks = chunk(bids, chunkSize); - return _map(bidChunks, (bids) => { + const bidChunks = utils.chunk(bids, chunkSize); + return utils._map(bidChunks, (bids) => { return { data: Object.assign({}, tag, { BidRequests: bids }), adapterRequest, @@ -114,26 +117,26 @@ export const spec = { serverResponse = serverResponse.body; let bids = []; - if (!isArray(serverResponse)) { + if (!utils.isArray(serverResponse)) { return parseRTBResponse(serverResponse, adapterRequest); } serverResponse.forEach(serverBidResponse => { - bids = flatten(bids, parseRTBResponse(serverBidResponse, adapterRequest)); + bids = utils.flatten(bids, parseRTBResponse(serverBidResponse, adapterRequest)); }); return bids; }, transformBidParams(params) { - return convertTypes({ + return utils.convertTypes({ 'aid': 'number', }, params); } }; function parseRTBResponse(serverResponse, adapterRequest) { - const isEmptyResponse = !serverResponse || !isArray(serverResponse.bids); + const isEmptyResponse = !serverResponse || !utils.isArray(serverResponse.bids); const bids = []; if (isEmptyResponse) { @@ -158,26 +161,26 @@ function parseRTBResponse(serverResponse, adapterRequest) { function bidToTag(bidRequests, adapterRequest) { // start publisher env const tag = { - Domain: deepAccess(adapterRequest, 'refererInfo.referer') + Domain: utils.deepAccess(adapterRequest, 'refererInfo.referer') }; if (config.getConfig('coppa') === true) { tag.Coppa = 1; } - if (deepAccess(adapterRequest, 'gdprConsent.gdprApplies')) { + if (utils.deepAccess(adapterRequest, 'gdprConsent.gdprApplies')) { tag.GDPR = 1; - tag.GDPRConsent = deepAccess(adapterRequest, 'gdprConsent.consentString'); + tag.GDPRConsent = utils.deepAccess(adapterRequest, 'gdprConsent.consentString'); } - if (deepAccess(adapterRequest, 'uspConsent')) { - tag.USP = deepAccess(adapterRequest, 'uspConsent'); + if (utils.deepAccess(adapterRequest, 'uspConsent')) { + tag.USP = utils.deepAccess(adapterRequest, 'uspConsent'); } - if (deepAccess(bidRequests[0], 'schain')) { - tag.Schain = deepAccess(bidRequests[0], 'schain'); + if (utils.deepAccess(bidRequests[0], 'schain')) { + tag.Schain = utils.deepAccess(bidRequests[0], 'schain'); } - if (deepAccess(bidRequests[0], 'userId')) { - tag.UserIds = deepAccess(bidRequests[0], 'userId'); + if (utils.deepAccess(bidRequests[0], 'userId')) { + tag.UserIds = utils.deepAccess(bidRequests[0], 'userId'); } - if (deepAccess(bidRequests[0], 'userIdAsEids')) { - tag.UserEids = deepAccess(bidRequests[0], 'userIdAsEids'); + if (utils.deepAccess(bidRequests[0], 'userIdAsEids')) { + tag.UserEids = utils.deepAccess(bidRequests[0], 'userIdAsEids'); } if (window.adtDmp && window.adtDmp.ready) { tag.DMPId = window.adtDmp.getUID(); @@ -200,13 +203,13 @@ function bidToTag(bidRequests, adapterRequest) { * @returns {object} */ function prepareBidRequests(bidReq) { - const mediaType = deepAccess(bidReq, 'mediaTypes.video') ? VIDEO : DISPLAY; - const sizes = mediaType === VIDEO ? deepAccess(bidReq, 'mediaTypes.video.playerSize') : deepAccess(bidReq, 'mediaTypes.banner.sizes'); + const mediaType = utils.deepAccess(bidReq, 'mediaTypes.video') ? VIDEO : DISPLAY; + const sizes = mediaType === VIDEO ? utils.deepAccess(bidReq, 'mediaTypes.video.playerSize') : utils.deepAccess(bidReq, 'mediaTypes.banner.sizes'); const bidReqParams = { 'CallbackId': bidReq.bidId, 'Aid': bidReq.params.aid, 'AdType': mediaType, - 'Sizes': parseSizesInput(sizes).join(',') + 'Sizes': utils.parseSizesInput(sizes).join(',') }; bidReqParams.PlacementId = bidReq.adUnitCode; @@ -217,9 +220,9 @@ function prepareBidRequests(bidReq) { bidReqParams.PlacementId = bidReq.params.vpb_placement_id; } if (mediaType === VIDEO) { - const context = deepAccess(bidReq, 'mediaTypes.video.context'); + const context = utils.deepAccess(bidReq, 'mediaTypes.video.context'); if (context === ADPOD) { - bidReqParams.Adpod = deepAccess(bidReq, 'mediaTypes.video'); + bidReqParams.Adpod = utils.deepAccess(bidReq, 'mediaTypes.video'); } } return bidReqParams; @@ -231,7 +234,7 @@ function prepareBidRequests(bidReq) { * @returns {object} */ function getMediaType(bidderRequest) { - return deepAccess(bidderRequest, 'mediaTypes.video') ? VIDEO : BANNER; + return utils.deepAccess(bidderRequest, 'mediaTypes.video') ? VIDEO : BANNER; } /** @@ -242,7 +245,7 @@ function getMediaType(bidderRequest) { */ function createBid(bidResponse, bidRequest) { const mediaType = getMediaType(bidRequest) - const context = deepAccess(bidRequest, 'mediaTypes.video.context'); + const context = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); const bid = { requestId: bidResponse.requestId, creativeId: bidResponse.cmpId, diff --git a/modules/adtrueBidAdapter.js b/modules/adtrueBidAdapter.js index 283e1273150..96f1ceb12f0 100644 --- a/modules/adtrueBidAdapter.js +++ b/modules/adtrueBidAdapter.js @@ -1,11 +1,11 @@ -import { logWarn, isArray, inIframe, isNumber, isStr, deepClone, deepSetValue, logError, deepAccess, isBoolean } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; import {getStorageManager} from '../src/storageManager.js'; +const storage = getStorageManager(); const BIDDER_CODE = 'adtrue'; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); const ADTRUE_CURRENCY = 'USD'; const ENDPOINT_URL = 'https://hb.adtrue.com/prebid/auction'; const LOG_WARN_PREFIX = 'AdTrue: '; @@ -190,22 +190,22 @@ function _checkParamDataType(key, value, datatype) { var functionToExecute; switch (datatype) { case DATA_TYPES.BOOLEAN: - functionToExecute = isBoolean; + functionToExecute = utils.isBoolean; break; case DATA_TYPES.NUMBER: - functionToExecute = isNumber; + functionToExecute = utils.isNumber; break; case DATA_TYPES.STRING: - functionToExecute = isStr; + functionToExecute = utils.isStr; break; case DATA_TYPES.ARRAY: - functionToExecute = isArray; + functionToExecute = utils.isArray; break; } if (functionToExecute(value)) { return value; } - logWarn(LOG_WARN_PREFIX + errMsg); + utils.logWarn(LOG_WARN_PREFIX + errMsg); return UNDEFINED; } @@ -216,7 +216,7 @@ function _parseNativeResponse(bid, newBid) { try { adm = JSON.parse(bid.adm.replace(/\\/g, '')); } catch (ex) { - // logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native reponse for ad response: ' + newBid.adm); + // utils.logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native reponse for ad response: ' + newBid.adm); return; } if (adm && adm.native && adm.native.assets && adm.native.assets.length > 0) { @@ -274,13 +274,13 @@ function _createBannerRequest(bid) { var sizes = bid.mediaTypes.banner.sizes; var format = []; var bannerObj; - if (sizes !== UNDEFINED && isArray(sizes)) { + if (sizes !== UNDEFINED && utils.isArray(sizes)) { bannerObj = {}; if (!bid.params.width && !bid.params.height) { if (sizes.length === 0) { // i.e. since bid.params does not have width or height, and length of sizes is 0, need to ignore this banner imp bannerObj = UNDEFINED; - logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.banner.size missing for adunit: ' + bid.params.adUnit + '. Ignoring the banner impression in the adunit.'); + utils.logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.banner.size missing for adunit: ' + bid.params.adUnit + '. Ignoring the banner impression in the adunit.'); return bannerObj; } else { bannerObj.w = parseInt(sizes[0][0], 10); @@ -303,9 +303,9 @@ function _createBannerRequest(bid) { } } bannerObj.pos = 0; - bannerObj.topframe = inIframe() ? 0 : 1; + bannerObj.topframe = utils.inIframe() ? 0 : 1; } else { - logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.banner.size missing for adunit: ' + bid.params.adUnit + '. Ignoring the banner impression in the adunit.'); + utils.logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.banner.size missing for adunit: ' + bid.params.adUnit + '. Ignoring the banner impression in the adunit.'); bannerObj = UNDEFINED; } return bannerObj; @@ -323,10 +323,10 @@ function _createVideoRequest(bid) { } } // read playersize and assign to h and w. - if (isArray(bid.mediaTypes.video.playerSize[0])) { + if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0][0], 10); videoObj.h = parseInt(bid.mediaTypes.video.playerSize[0][1], 10); - } else if (isNumber(bid.mediaTypes.video.playerSize[0])) { + } else if (utils.isNumber(bid.mediaTypes.video.playerSize[0])) { videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0], 10); videoObj.h = parseInt(bid.mediaTypes.video.playerSize[1], 10); } @@ -337,7 +337,7 @@ function _createVideoRequest(bid) { } } else { videoObj = UNDEFINED; - logWarn(LOG_WARN_PREFIX + 'Error: Video config params missing for adunit: ' + bid.params.adUnit + ' with mediaType set as video. Ignoring video impression in the adunit.'); + utils.logWarn(LOG_WARN_PREFIX + 'Error: Video config params missing for adunit: ' + bid.params.adUnit + ' with mediaType set as video. Ignoring video impression in the adunit.'); } return videoObj; } @@ -355,7 +355,7 @@ function _checkMediaType(adm, newBid) { newBid.mediaType = NATIVE; } } catch (e) { - logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native reponse for ad response: ' + adm); + utils.logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native reponse for ad response: ' + adm); } } } @@ -401,9 +401,9 @@ function _createImpressionObject(bid, conf) { pos: 0, w: bid.params.width, h: bid.params.height, - topframe: inIframe() ? 0 : 1 + topframe: utils.inIframe() ? 0 : 1 }; - if (isArray(sizes) && sizes.length > 1) { + if (utils.isArray(sizes) && sizes.length > 1) { sizes = sizes.splice(1, sizes.length - 1); sizes.forEach(size => { format.push({ @@ -428,19 +428,19 @@ export const spec = { isBidRequestValid: function (bid) { if (bid && bid.params) { if (!bid.params.zoneId) { - logWarn(LOG_WARN_PREFIX + 'Error: missing zoneId'); + utils.logWarn(LOG_WARN_PREFIX + 'Error: missing zoneId'); return false; } if (!bid.params.publisherId) { - logWarn(LOG_WARN_PREFIX + 'Error: missing publisherId'); + utils.logWarn(LOG_WARN_PREFIX + 'Error: missing publisherId'); return false; } - if (!isStr(bid.params.publisherId)) { - logWarn(LOG_WARN_PREFIX + 'Error: publisherId is mandatory and cannot be numeric'); + if (!utils.isStr(bid.params.publisherId)) { + utils.logWarn(LOG_WARN_PREFIX + 'Error: publisherId is mandatory and cannot be numeric'); return false; } - if (!isStr(bid.params.zoneId)) { - logWarn(LOG_WARN_PREFIX + 'Error: zoneId is mandatory and cannot be numeric'); + if (!utils.isStr(bid.params.zoneId)) { + utils.logWarn(LOG_WARN_PREFIX + 'Error: zoneId is mandatory and cannot be numeric'); return false; } return true; @@ -458,7 +458,7 @@ export const spec = { let bidCurrency = ''; let bid; validBidRequests.forEach(originalBid => { - bid = deepClone(originalBid); + bid = utils.deepClone(originalBid); _parseAdSlot(bid); conf.zoneId = conf.zoneId || bid.params.zoneId; @@ -468,7 +468,7 @@ export const spec = { if (bidCurrency === '') { bidCurrency = bid.params.currency || UNDEFINED; } else if (bid.params.hasOwnProperty('currency') && bidCurrency !== bid.params.currency) { - logWarn(LOG_WARN_PREFIX + 'Currency specifier ignored. Only one currency permitted.'); + utils.logWarn(LOG_WARN_PREFIX + 'Currency specifier ignored. Only one currency permitted.'); } bid.params.currency = bidCurrency; @@ -502,28 +502,28 @@ export const spec = { if (typeof config.getConfig('device') === 'object') { payload.device = Object.assign(payload.device, config.getConfig('device')); } - deepSetValue(payload, 'source.tid', conf.transactionId); + utils.deepSetValue(payload, 'source.tid', conf.transactionId); // test bids if (window.location.href.indexOf('adtrueTest=true') !== -1) { payload.test = 1; } // adding schain object if (validBidRequests[0].schain) { - deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); + utils.deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); } // Attaching GDPR Consent Params if (bidderRequest && bidderRequest.gdprConsent) { - deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(payload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + utils.deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(payload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); } // CCPA if (bidderRequest && bidderRequest.uspConsent) { - deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); } // coppa compliance if (config.getConfig('coppa') === true) { - deepSetValue(payload, 'regs.coppa', 1); + utils.deepSetValue(payload, 'regs.coppa', 1); } return { @@ -539,12 +539,12 @@ export const spec = { let parsedRequest = JSON.parse(bidderRequest.data); let parsedReferrer = parsedRequest.site && parsedRequest.site.ref ? parsedRequest.site.ref : ''; try { - if (serverResponses.body && serverResponses.body.seatbid && isArray(serverResponses.body.seatbid)) { + if (serverResponses.body && serverResponses.body.seatbid && utils.isArray(serverResponses.body.seatbid)) { // Supporting multiple bid responses for same adSize respCur = serverResponses.body.cur || respCur; serverResponses.body.seatbid.forEach(seatbidder => { seatbidder.bid && - isArray(seatbidder.bid) && + utils.isArray(seatbidder.bid) && seatbidder.bid.forEach(bid => { let newBid = { requestId: bid.impid, @@ -598,7 +598,7 @@ export const spec = { }); } } catch (error) { - logError(error); + utils.logError(error); } return bidResponses; }, @@ -607,7 +607,7 @@ export const spec = { return []; } return responses.reduce((accum, rsp) => { - let cookieSyncs = deepAccess(rsp, 'body.ext.cookie_sync'); + let cookieSyncs = utils.deepAccess(rsp, 'body.ext.cookie_sync'); if (cookieSyncs) { let cookieSyncObjects = cookieSyncs.map(cookieSync => { return { diff --git a/modules/aduptechBidAdapter.js b/modules/aduptechBidAdapter.js index 1186e0410ab..b70f7cf3ce6 100644 --- a/modules/aduptechBidAdapter.js +++ b/modules/aduptechBidAdapter.js @@ -1,7 +1,7 @@ -import { deepAccess, getWindowTop, getWindowSelf, getAdUnitSizes } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER, NATIVE } from '../src/mediaTypes.js' +import * as utils from '../src/utils.js'; export const BIDDER_CODE = 'aduptech'; export const ENDPOINT_URL_PUBLISHER_PLACEHOLDER = '{PUBLISHER}'; @@ -37,7 +37,7 @@ export const internal = { * @returns {string} */ extractPageUrl: (bidderRequest) => { - if (bidderRequest && deepAccess(bidderRequest, 'refererInfo.canonicalUrl')) { + if (bidderRequest && utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl')) { return bidderRequest.refererInfo.canonicalUrl; } @@ -46,9 +46,9 @@ export const internal = { } try { - return getWindowTop().location.href; + return utils.getWindowTop().location.href; } catch (e) { - return getWindowSelf().location.href; + return utils.getWindowSelf().location.href; } }, @@ -59,14 +59,14 @@ export const internal = { * @returns {string} */ extractReferrer: (bidderRequest) => { - if (bidderRequest && deepAccess(bidderRequest, 'refererInfo.referer')) { + if (bidderRequest && utils.deepAccess(bidderRequest, 'refererInfo.referer')) { return bidderRequest.refererInfo.referer; } try { - return getWindowTop().document.referrer; + return utils.getWindowTop().document.referrer; } catch (e) { - return getWindowSelf().document.referrer; + return utils.getWindowSelf().document.referrer; } }, @@ -77,7 +77,7 @@ export const internal = { * @returns {null|Object.} */ extractBannerConfig: (bidRequest) => { - const sizes = getAdUnitSizes(bidRequest); + const sizes = utils.getAdUnitSizes(bidRequest); if (Array.isArray(sizes) && sizes.length > 0) { return { sizes: sizes }; } @@ -92,7 +92,7 @@ export const internal = { * @returns {null|Object.} */ extractNativeConfig: (bidRequest) => { - if (bidRequest && deepAccess(bidRequest, 'mediaTypes.native')) { + if (bidRequest && utils.deepAccess(bidRequest, 'mediaTypes.native')) { return bidRequest.mediaTypes.native; } @@ -267,7 +267,7 @@ export const spec = { const bidResponses = []; // stop here on invalid or empty data - if (!response || !deepAccess(response, 'body.bids') || response.body.bids.length === 0) { + if (!response || !utils.deepAccess(response, 'body.bids') || response.body.bids.length === 0) { return bidResponses; } diff --git a/modules/advangelistsBidAdapter.js b/modules/advangelistsBidAdapter.js deleted file mode 100755 index 605e19cfc66..00000000000 --- a/modules/advangelistsBidAdapter.js +++ /dev/null @@ -1,397 +0,0 @@ -import {deepAccess, generateUUID, isEmpty, isFn, parseSizesInput, parseUrl} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {find, includes} from '../src/polyfill.js'; - -const ADAPTER_VERSION = '1.0'; -const BIDDER_CODE = 'advangelists'; - -export const VIDEO_ENDPOINT = 'https://nep.advangelists.com/xp/get?pubid=';// 0cf8d6d643e13d86a5b6374148a4afac'; -export const BANNER_ENDPOINT = 'https://nep.advangelists.com/xp/get?pubid=';// 0cf8d6d643e13d86a5b6374148a4afac'; -export const OUTSTREAM_SRC = 'https://player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js'; -export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration', 'skip', 'playerSize', 'context']; -export const DEFAULT_MIMES = ['video/mp4', 'application/javascript']; - -let pubid = ''; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO], - - isBidRequestValid(bidRequest) { - if (typeof bidRequest != 'undefined') { - if (bidRequest.bidder !== BIDDER_CODE && typeof bidRequest.params === 'undefined') { return false; } - if (bidRequest === '' || bidRequest.params.placement === '' || bidRequest.params.pubid === '') { return false; } - return true; - } else { return false; } - }, - - buildRequests(bids, bidderRequest) { - let requests = []; - let videoBids = bids.filter(bid => isVideoBidValid(bid)); - let bannerBids = bids.filter(bid => isBannerBidValid(bid)); - videoBids.forEach(bid => { - pubid = getVideoBidParam(bid, 'pubid'); - requests.push({ - method: 'POST', - url: VIDEO_ENDPOINT + pubid, - data: createVideoRequestData(bid, bidderRequest), - bidRequest: bid - }); - }); - - bannerBids.forEach(bid => { - pubid = getBannerBidParam(bid, 'pubid'); - requests.push({ - method: 'POST', - url: BANNER_ENDPOINT + pubid, - data: createBannerRequestData(bid, bidderRequest), - bidRequest: bid - }); - }); - return requests; - }, - - interpretResponse(serverResponse, {bidRequest}) { - let response = serverResponse.body; - if (response !== null && isEmpty(response) == false) { - if (isVideoBid(bidRequest)) { - let bidResponse = { - requestId: response.id, - bidderCode: BIDDER_CODE, - cpm: response.seatbid[0].bid[0].price, - width: response.seatbid[0].bid[0].w, - height: response.seatbid[0].bid[0].h, - ttl: response.seatbid[0].bid[0].ttl || 60, - creativeId: response.seatbid[0].bid[0].crid, - meta: { 'advertiserDomains': response.seatbid[0].bid[0].adomain }, - currency: response.cur, - mediaType: VIDEO, - netRevenue: true - } - - if (response.seatbid[0].bid[0].adm) { - bidResponse.vastXml = response.seatbid[0].bid[0].adm; - bidResponse.adResponse = { - content: response.seatbid[0].bid[0].adm - }; - } else { - bidResponse.vastUrl = response.seatbid[0].bid[0].nurl; - } - - return bidResponse; - } else { - return { - requestId: response.id, - bidderCode: BIDDER_CODE, - cpm: response.seatbid[0].bid[0].price, - width: response.seatbid[0].bid[0].w, - height: response.seatbid[0].bid[0].h, - ad: response.seatbid[0].bid[0].adm, - ttl: response.seatbid[0].bid[0].ttl || 60, - creativeId: response.seatbid[0].bid[0].crid, - currency: response.cur, - meta: { 'advertiserDomains': response.seatbid[0].bid[0].adomain }, - mediaType: BANNER, - netRevenue: true - } - } - } - } -}; - -function isBannerBid(bid) { - return deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid); -} - -function isVideoBid(bid) { - return deepAccess(bid, 'mediaTypes.video'); -} - -function getBannerBidFloor(bid) { - let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'banner', size: '*' }) : {}; - return floorInfo.floor || getBannerBidParam(bid, 'bidfloor'); -} - -function getVideoBidFloor(bid) { - let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'video', size: '*' }) : {}; - return floorInfo.floor || getVideoBidParam(bid, 'bidfloor'); -} - -function isVideoBidValid(bid) { - return isVideoBid(bid) && getVideoBidParam(bid, 'pubid') && getVideoBidParam(bid, 'placement'); -} - -function isBannerBidValid(bid) { - return isBannerBid(bid) && getBannerBidParam(bid, 'pubid') && getBannerBidParam(bid, 'placement'); -} - -function getVideoBidParam(bid, key) { - return deepAccess(bid, 'params.video.' + key) || deepAccess(bid, 'params.' + key); -} - -function getBannerBidParam(bid, key) { - return deepAccess(bid, 'params.banner.' + key) || deepAccess(bid, 'params.' + key); -} - -function isMobile() { - return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent); -} - -function isConnectedTV() { - return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent); -} - -function getDoNotTrack() { - return navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.msDoNoTrack === '1' || navigator.doNotTrack === 'yes'; -} - -function findAndFillParam(o, key, value) { - try { - if (typeof value === 'function') { - o[key] = value(); - } else { - o[key] = value; - } - } catch (ex) {} -} - -function getOsVersion() { - let clientStrings = [ - { s: 'Android', r: /Android/ }, - { s: 'iOS', r: /(iPhone|iPad|iPod)/ }, - { s: 'Mac OS X', r: /Mac OS X/ }, - { s: 'Mac OS', r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ }, - { s: 'Linux', r: /(Linux|X11)/ }, - { s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ }, - { s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ }, - { s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ }, - { s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ }, - { s: 'Windows Vista', r: /Windows NT 6.0/ }, - { s: 'Windows Server 2003', r: /Windows NT 5.2/ }, - { s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ }, - { s: 'UNIX', r: /UNIX/ }, - { s: 'Search Bot', r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ } - ]; - let cs = find(clientStrings, cs => cs.r.test(navigator.userAgent)); - return cs ? cs.s : 'unknown'; -} - -function getFirstSize(sizes) { - return (sizes && sizes.length) ? sizes[0] : { w: undefined, h: undefined }; -} - -function parseSizes(sizes) { - return parseSizesInput(sizes).map(size => { - let [ width, height ] = size.split('x'); - return { - w: parseInt(width, 10) || undefined, - h: parseInt(height, 10) || undefined - }; - }); -} - -function getVideoSizes(bid) { - return parseSizes(deepAccess(bid, 'mediaTypes.video.playerSize') || bid.sizes); -} - -function getBannerSizes(bid) { - return parseSizes(deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes); -} - -function getTopWindowReferrer() { - try { - return window.top.document.referrer; - } catch (e) { - return ''; - } -} - -function getVideoTargetingParams(bid) { - const result = {}; - const excludeProps = ['playerSize', 'context', 'w', 'h']; - Object.keys(Object(bid.mediaTypes.video)) - .filter(key => !includes(excludeProps, key)) - .forEach(key => { - result[ key ] = bid.mediaTypes.video[ key ]; - }); - Object.keys(Object(bid.params.video)) - .filter(key => includes(VIDEO_TARGETING, key)) - .forEach(key => { - result[ key ] = bid.params.video[ key ]; - }); - return result; -} - -function createVideoRequestData(bid, bidderRequest) { - let topLocation = getTopWindowLocation(bidderRequest); - let topReferrer = getTopWindowReferrer(); - - let sizes = getVideoSizes(bid); - let firstSize = getFirstSize(sizes); - let bidfloor = (getVideoBidFloor(bid) == null || typeof getVideoBidFloor(bid) == 'undefined') ? 2 : getVideoBidFloor(bid); - let video = getVideoTargetingParams(bid); - const o = { - 'device': { - 'langauge': (global.navigator.language).split('-')[0], - 'dnt': (global.navigator.doNotTrack === 1 ? 1 : 0), - 'devicetype': isMobile() ? 4 : isConnectedTV() ? 3 : 2, - 'js': 1, - 'os': getOsVersion() - }, - 'at': 2, - 'site': {}, - 'tmax': 3000, - 'cur': ['USD'], - 'id': bid.bidId, - 'imp': [], - 'regs': { - 'ext': { - } - }, - 'user': { - 'ext': { - } - } - }; - - o.site['page'] = topLocation.href; - o.site['domain'] = topLocation.hostname; - o.site['search'] = topLocation.search; - o.site['domain'] = topLocation.hostname; - o.site['ref'] = topReferrer; - o.site['mobile'] = isMobile() ? 1 : 0; - const secure = topLocation.protocol.indexOf('https') === 0 ? 1 : 0; - - o.device['dnt'] = getDoNotTrack() ? 1 : 0; - - findAndFillParam(o.site, 'name', function() { - return global.top.document.title; - }); - - findAndFillParam(o.device, 'h', function() { - return global.screen.height; - }); - findAndFillParam(o.device, 'w', function() { - return global.screen.width; - }); - - let placement = getVideoBidParam(bid, 'placement'); - - for (let j = 0; j < sizes.length; j++) { - o.imp.push({ - 'id': '' + j, - 'displaymanager': '' + BIDDER_CODE, - 'displaymanagerver': '' + ADAPTER_VERSION, - 'tagId': placement, - 'bidfloor': bidfloor, - 'bidfloorcur': 'USD', - 'secure': secure, - 'video': Object.assign({ - 'id': generateUUID(), - 'pos': 0, - 'w': firstSize.w, - 'h': firstSize.h, - 'mimes': DEFAULT_MIMES - }, video) - - }); - } - - if (bidderRequest && bidderRequest.gdprConsent) { - let { gdprApplies, consentString } = bidderRequest.gdprConsent; - o.regs.ext = {'gdpr': gdprApplies ? 1 : 0}; - o.user.ext = {'consent': consentString}; - } - - return o; -} - -function getTopWindowLocation(bidderRequest) { - let url = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; - return parseUrl(config.getConfig('pageUrl') || url, { decodeSearchAsString: true }); -} - -function createBannerRequestData(bid, bidderRequest) { - let topLocation = getTopWindowLocation(bidderRequest); - let topReferrer = getTopWindowReferrer(); - - let sizes = getBannerSizes(bid); - let bidfloor = (getBannerBidFloor(bid) == null || typeof getBannerBidFloor(bid) == 'undefined') ? 2 : getBannerBidFloor(bid); - - const o = { - 'device': { - 'langauge': (global.navigator.language).split('-')[0], - 'dnt': (global.navigator.doNotTrack === 1 ? 1 : 0), - 'devicetype': isMobile() ? 4 : isConnectedTV() ? 3 : 2, - 'js': 1 - }, - 'at': 2, - 'site': {}, - 'tmax': 3000, - 'cur': ['USD'], - 'id': bid.bidId, - 'imp': [], - 'regs': { - 'ext': { - } - }, - 'user': { - 'ext': { - } - } - }; - - o.site['page'] = topLocation.href; - o.site['domain'] = topLocation.hostname; - o.site['search'] = topLocation.search; - o.site['domain'] = topLocation.hostname; - o.site['ref'] = topReferrer; - o.site['mobile'] = isMobile() ? 1 : 0; - const secure = topLocation.protocol.indexOf('https') === 0 ? 1 : 0; - - o.device['dnt'] = getDoNotTrack() ? 1 : 0; - - findAndFillParam(o.site, 'name', function() { - return global.top.document.title; - }); - - findAndFillParam(o.device, 'h', function() { - return global.screen.height; - }); - findAndFillParam(o.device, 'w', function() { - return global.screen.width; - }); - - let placement = getBannerBidParam(bid, 'placement'); - for (let j = 0; j < sizes.length; j++) { - let size = sizes[j]; - - o.imp.push({ - 'id': '' + j, - 'displaymanager': '' + BIDDER_CODE, - 'displaymanagerver': '' + ADAPTER_VERSION, - 'tagId': placement, - 'bidfloor': bidfloor, - 'bidfloorcur': 'USD', - 'secure': secure, - 'banner': { - 'id': generateUUID(), - 'pos': 0, - 'w': size['w'], - 'h': size['h'] - } - }); - } - - if (bidderRequest && bidderRequest.gdprConsent) { - let { gdprApplies, consentString } = bidderRequest.gdprConsent; - o.regs.ext = {'gdpr': gdprApplies ? 1 : 0}; - o.user.ext = {'consent': consentString}; - } - - return o; -} - -registerBidder(spec); diff --git a/modules/advangelistsBidAdapter.md b/modules/advangelistsBidAdapter.md index 04537ff677d..1765241eaf3 100755 --- a/modules/advangelistsBidAdapter.md +++ b/modules/advangelistsBidAdapter.md @@ -42,11 +42,7 @@ var videoAdUnit = { mediaTypes: { video: { playerSize : [[320, 480]], - context: 'instream', - skip: 1, - mimes : ['video/mp4', 'application/javascript'], - playbackmethod : [2,6], - maxduration: 30 + context: 'instream' } }, bids: [ @@ -54,7 +50,14 @@ var videoAdUnit = { bidder: 'advangelists', params: { pubid: '8537f00948fc37cc03c5f0f88e198a76', - placement: 1234 + placement: 1234, + video: { + id: 123, + skip: 1, + mimes : ['video/mp4', 'application/javascript'], + playbackmethod : [2,6], + maxduration: 30 + } } } ] diff --git a/modules/adxcgAnalyticsAdapter.js b/modules/adxcgAnalyticsAdapter.js index 5cd04ce13cd..9f514c545a1 100644 --- a/modules/adxcgAnalyticsAdapter.js +++ b/modules/adxcgAnalyticsAdapter.js @@ -1,8 +1,8 @@ -import { parseSizesInput, uniques, buildUrl, logError } from '../src/utils.js'; import { ajax } from '../src/ajax.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; +import * as utils from '../src/utils.js'; /** * Analytics adapter from adxcg.com @@ -32,7 +32,7 @@ var adxcgAnalyticsAdapter = Object.assign(adapter( case CONSTANTS.EVENTS.BID_ADJUSTMENT: break; case CONSTANTS.EVENTS.BID_TIMEOUT: - adxcgAnalyticsAdapter.context.events.bidTimeout = args.map(item => item.bidder).filter(uniques); + adxcgAnalyticsAdapter.context.events.bidTimeout = args.map(item => item.bidder).filter(utils.uniques); break; case CONSTANTS.EVENTS.BIDDER_DONE: break; @@ -67,7 +67,7 @@ function mapBidRequested (bidRequests) { adUnitCode: bid.adUnitCode, bidId: bid.bidId, start: bid.startTime, - sizes: parseSizesInput(bid.sizes).toString(), + sizes: utils.parseSizesInput(bid.sizes).toString(), params: bid.params }; }), @@ -112,7 +112,7 @@ function mapBidWon (bidResponse) { } function send (data) { - let adxcgAnalyticsRequestUrl = buildUrl({ + let adxcgAnalyticsRequestUrl = utils.buildUrl({ protocol: 'https', hostname: adxcgAnalyticsAdapter.context.host, pathname: '/pbrx/v2', @@ -143,7 +143,7 @@ adxcgAnalyticsAdapter.context = {}; adxcgAnalyticsAdapter.originEnableAnalytics = adxcgAnalyticsAdapter.enableAnalytics; adxcgAnalyticsAdapter.enableAnalytics = function (config) { if (!config.options.publisherId) { - logError('PublisherId option is not defined. Analytics won\'t work'); + utils.logError('PublisherId option is not defined. Analytics won\'t work'); return; } diff --git a/modules/adxcgBidAdapter.js b/modules/adxcgBidAdapter.js index 81872100cd1..e10eeaa3302 100644 --- a/modules/adxcgBidAdapter.js +++ b/modules/adxcgBidAdapter.js @@ -1,362 +1,410 @@ -// jshint esversion: 6, es3: false, node: true -'use strict'; - -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {NATIVE, BANNER, VIDEO} from '../src/mediaTypes.js'; -import { - mergeDeep, - _map, - deepAccess, - getDNT, - parseSizesInput, - deepSetValue, - isStr, - isArray, - isPlainObject, - parseUrl, - replaceAuctionPrice, triggerPixel -} from '../src/utils.js'; -import {config} from '../src/config.js'; - -const { getConfig } = config; - -const BIDDER_CODE = 'adxcg'; -const SECURE_BID_URL = 'https://pbc.adxcg.net/rtb/ortb/pbc?adExchangeId=1'; - -const NATIVE_ASSET_IDS = { 0: 'title', 2: 'icon', 3: 'image', 5: 'sponsoredBy', 4: 'body', 1: 'cta' }; -const NATIVE_PARAMS = { - title: { - id: 0, - name: 'title' - }, - icon: { - id: 2, - type: 1, - name: 'img' - }, - image: { - id: 3, - type: 3, - name: 'img' - }, - sponsoredBy: { - id: 5, - name: 'data', - type: 1 - }, - body: { - id: 4, - name: 'data', - type: 2 - }, - cta: { - id: 1, - type: 12, - name: 'data' - } -}; +import {config} from '../src/config.js' +import * as utils from '../src/utils.js' +import {registerBidder} from '../src/adapters/bidderFactory.js' +import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js' +import includes from 'core-js-pure/features/array/includes.js' + +/** + * Adapter for requesting bids from adxcg.net + * updated to latest prebid repo on 2017.10.20 + * updated for gdpr compliance on 2018.05.22 -requires gdpr compliance module + * updated to pass aditional auction and impression level parameters. added pass for video targeting parameters + * updated to fix native support for image width/height and icon 2019.03.17 + * updated support for userid - pubcid,ttid 2019.05.28 + * updated to support prebid 3.0 - remove non https, move to banner.xx.sizes, remove utils.getTopWindowLocation,remove utils.getTopWindowUrl(),remove utils.getTopWindowReferrer() + * updated to support prebid 4.0 - standardized video params, updated video validation, add onBidWon, onTimeOut, use standardized getFloor + */ + +const BIDDER_CODE = 'adxcg' +const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE] +const SOURCE = 'pbjs10' +const VIDEO_TARGETING = ['id', 'minduration', 'maxduration', 'startdelay', 'skippable', 'playback_method', 'frameworks'] +const USER_PARAMS_AUCTION = ['forcedDspIds', 'forcedCampaignIds', 'forcedCreativeIds', 'gender', 'dnt', 'language'] +const USER_PARAMS_BID = ['lineparam1', 'lineparam2', 'lineparam3'] +const BIDADAPTERVERSION = 'r20210330PB40' +const DEFAULT_MIN_FLOOR = 0; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [ NATIVE, BANNER, VIDEO ], - isBidRequestValid: (bid) => { - const params = bid.params || {}; - const { adzoneid } = params; - return !!(adzoneid); - }, - buildRequests: (validBidRequests, bidderRequest) => { - let app, site; - - const commonFpd = getConfig('ortb2') || {}; - let { user } = commonFpd; + supportedMediaTypes: SUPPORTED_AD_TYPES, + + /** + * Determines whether or not the given bid request is valid. + * + * @param {object} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function (bid) { + if (!bid || !bid.params) { + utils.logWarn(BIDDER_CODE + ': Missing bid parameters'); + return false + } - if (typeof getConfig('app') === 'object') { - app = getConfig('app') || {}; - if (commonFpd.app) { - mergeDeep(app, commonFpd.app); - } - } else { - site = getConfig('site') || {}; - if (commonFpd.site) { - mergeDeep(site, commonFpd.site); - } + if (!utils.isStr(bid.params.adzoneid)) { + utils.logWarn(BIDDER_CODE + ': adzoneid must be specified as a string'); + return false + } - if (!site.page) { - site.page = bidderRequest.refererInfo.referer; - site.domain = parseUrl(bidderRequest.refererInfo.referer).hostname; + if (isBannerRequest(bid)) { + const banneroAdUnit = utils.deepAccess(bid, 'mediaTypes.banner'); + if (!banneroAdUnit.sizes) { + utils.logWarn(BIDDER_CODE + ': banner sizes must be specified'); + return false; } } - const device = getConfig('device') || {}; - device.w = device.w || window.innerWidth; - device.h = device.h || window.innerHeight; - device.ua = device.ua || navigator.userAgent; - device.dnt = getDNT() ? 1 : 0; - device.language = (navigator && navigator.language) ? navigator.language.split('-')[0] : ''; - - const tid = validBidRequests[0].transactionId; - const test = setOnAny(validBidRequests, 'params.test'); - const currency = getConfig('currency.adServerCurrency'); - const cur = currency && [ currency ]; - const eids = setOnAny(validBidRequests, 'userIdAsEids'); - const schain = setOnAny(validBidRequests, 'schain'); - - const imp = validBidRequests.map((bid, id) => { - const floorInfo = bid.getFloor ? bid.getFloor({ - currency: currency || 'USD' - }) : {}; - const bidfloor = floorInfo.floor; - const bidfloorcur = floorInfo.currency; - const { adzoneid } = bid.params; - - const imp = { - id: id + 1, - tagid: adzoneid, - secure: 1, - bidfloor, - bidfloorcur, - ext: { - } - }; - - const assets = _map(bid.nativeParams, (bidParams, key) => { - const props = NATIVE_PARAMS[key]; - const asset = { - required: bidParams.required & 1, - }; - if (props) { - asset.id = props.id; - let wmin, hmin, w, h; - let aRatios = bidParams.aspect_ratios; - - if (aRatios && aRatios[0]) { - aRatios = aRatios[0]; - wmin = aRatios.min_width || 0; - hmin = aRatios.ratio_height * wmin / aRatios.ratio_width | 0; - } - - if (bidParams.sizes) { - const sizes = flatten(bidParams.sizes); - w = sizes[0]; - h = sizes[1]; - } + if (isVideoRequest(bid)) { + // prebid 4.0 use standardized Video parameters + const videoAdUnit = utils.deepAccess(bid, 'mediaTypes.video'); - asset[props.name] = { - len: bidParams.len, - type: props.type, - wmin, - hmin, - w, - h - }; - - return asset; - } - }).filter(Boolean); - - if (assets.length) { - imp.native = { - request: JSON.stringify({assets: assets}) - }; + if (!Array.isArray(videoAdUnit.playerSize)) { + utils.logWarn(BIDDER_CODE + ': video playerSize must be an array of integers'); + return false; } - const bannerParams = deepAccess(bid, 'mediaTypes.banner'); - - if (bannerParams && bannerParams.sizes) { - const sizes = parseSizesInput(bannerParams.sizes); - const format = sizes.map(size => { - const [ width, height ] = size.split('x'); - const w = parseInt(width, 10); - const h = parseInt(height, 10); - return { w, h }; - }); + if (!videoAdUnit.context) { + utils.logWarn(BIDDER_CODE + ': video context must be specified'); + return false; + } - imp.banner = { - format - }; + if (!Array.isArray(videoAdUnit.mimes) || videoAdUnit.mimes.length === 0) { + utils.logWarn(BIDDER_CODE + ': video mimes must be an array of strings'); + return false; } - const videoParams = deepAccess(bid, 'mediaTypes.video'); - if (videoParams) { - imp.video = videoParams; + if (!Array.isArray(videoAdUnit.protocols) || videoAdUnit.protocols.length === 0) { + utils.logWarn(BIDDER_CODE + ': video protocols must be an array of integers'); + return false; } + } - return imp; - }); + return true + }, - const request = { - id: bidderRequest.auctionId, - site, - app, - user, - geo: { utcoffset: new Date().getTimezoneOffset() }, - device, - source: { tid, fd: 1 }, - ext: { - prebid: { - channel: { - name: 'pbjs', - version: '$prebid.version$' - } - } - }, - cur, - imp + /** + * Make a server request from the list of BidRequests. + * + * an array of validBidRequests + * Info describing the request to the server. + */ + buildRequests: function (validBidRequests, bidderRequest) { + let dt = new Date(); + let ratio = window.devicePixelRatio || 1; + let iobavailable = window && window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype && 'intersectionRatio' in window.IntersectionObserverEntry.prototype + + let bt = config.getConfig('bidderTimeout'); + if (window.PREBID_TIMEOUT) { + bt = Math.min(window.PREBID_TIMEOUT, bt); + } + + let referrer = utils.deepAccess(bidderRequest, 'refererInfo.referer'); + let page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href'); + + // add common parameters + let beaconParams = { + renderformat: 'javascript', + ver: BIDADAPTERVERSION, + secure: '1', + source: SOURCE, + uw: window.screen.width, + uh: window.screen.height, + dpr: ratio, + bt: bt, + isinframe: utils.inIframe(), + cookies: utils.checkCookieSupport() ? '1' : '0', + tz: dt.getTimezoneOffset(), + dt: utils.timestamp(), + iob: iobavailable ? '1' : '0', + pbjs: '$prebid.version$', + rndid: Math.floor(Math.random() * (999999 - 100000 + 1)) + 100000, + ref: encodeURIComponent(referrer), + url: encodeURIComponent(page) }; - if (test) { - request.is_debug = !!test; - request.test = 1; + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { + beaconParams.gdpr = bidderRequest.gdprConsent.gdprApplies ? '1' : '0'; + beaconParams.gdpr_consent = bidderRequest.gdprConsent.consentString; + } + + if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.pubcid'))) { + beaconParams.pubcid = validBidRequests[0].userId.pubcid; } - if (deepAccess(bidderRequest, 'gdprConsent.gdprApplies') !== undefined) { - deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(request, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies & 1); + + if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.tdid'))) { + beaconParams.tdid = validBidRequests[0].userId.tdid; } - if (bidderRequest.uspConsent) { - deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent); + if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.id5id.uid'))) { + beaconParams.id5id = validBidRequests[0].userId.id5id.uid; } - if (eids) { - deepSetValue(request, 'user.ext.eids', eids); + if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.idl_env'))) { + beaconParams.idl_env = validBidRequests[0].userId.idl_env; } - if (schain) { - deepSetValue(request, 'source.ext.schain', schain); + let biddercustom = config.getConfig(BIDDER_CODE); + if (biddercustom) { + Object.keys(biddercustom) + .filter(param => includes(USER_PARAMS_AUCTION, param)) + .forEach(param => beaconParams[param] = encodeURIComponent(biddercustom[param])) } + // per impression parameters + let adZoneIds = []; + let prebidBidIds = []; + let sizes = []; + let bidfloors = []; + + validBidRequests.forEach((bid, index) => { + adZoneIds.push(utils.getBidIdParameter('adzoneid', bid.params)); + prebidBidIds.push(bid.bidId); + + let bidfloor = getFloor(bid); + bidfloors.push(bidfloor); + + // copy all custom parameters impression level parameters not supported above + let customBidParams = utils.getBidIdParameter('custom', bid.params) || {} + if (customBidParams) { + Object.keys(customBidParams) + .filter(param => includes(USER_PARAMS_BID, param)) + .forEach(param => beaconParams[param + '.' + index] = encodeURIComponent(customBidParams[param])) + } + + if (isBannerRequest(bid)) { + sizes.push(utils.parseSizesInput(bid.mediaTypes.banner.sizes).join('|')); + } + + if (isNativeRequest(bid)) { + sizes.push('0x0'); + } + + if (isVideoRequest(bid)) { + if (bid.params.video) { + Object.keys(bid.params.video) + .filter(param => includes(VIDEO_TARGETING, param)) + .forEach(param => beaconParams['video.' + param + '.' + index] = encodeURIComponent(bid.params.video[param])) + } + // copy video standarized params + beaconParams['video.context' + '.' + index] = utils.deepAccess(bid, 'mediaTypes.video.context'); + sizes.push(utils.parseSizesInput(bid.mediaTypes.video.playerSize).join('|')); + beaconParams['video.mimes' + '.' + index] = utils.deepAccess(bid, 'mediaTypes.video.mimes').join(','); + beaconParams['video.protocols' + '.' + index] = utils.deepAccess(bid, 'mediaTypes.video.protocols').join(','); + } + }) + + beaconParams.adzoneid = adZoneIds.join(','); + beaconParams.format = sizes.join(','); + beaconParams.prebidBidIds = prebidBidIds.join(','); + beaconParams.bidfloors = bidfloors.join(','); + + let adxcgRequestUrl = utils.buildUrl({ + protocol: 'https', + hostname: 'hbps.adxcg.net', + pathname: '/get/adi', + search: beaconParams + }); + + utils.logMessage(`calling adi adxcg`); return { - method: 'POST', - url: SECURE_BID_URL, - data: JSON.stringify(request), - options: { - contentType: 'application/json' - }, - bids: validBidRequests + contentType: 'text/plain', + method: 'GET', + url: adxcgRequestUrl, + withCredentials: true }; }, - interpretResponse: function(serverResponse, { bids }) { - if (!serverResponse.body) { - return; - } - const { seatbid, cur } = serverResponse.body; - - const bidResponses = flatten(seatbid.map(seat => seat.bid)).reduce((result, bid) => { - result[bid.impid - 1] = bid; - return result; - }, []); - - return bids.map((bid, id) => { - const bidResponse = bidResponses[id]; - if (bidResponse) { - const mediaType = deepAccess(bidResponse, 'ext.crType'); - const result = { - requestId: bid.bidId, - cpm: bidResponse.price, - creativeId: bidResponse.crid, - ttl: bidResponse.ttl ? bidResponse.ttl : 300, - netRevenue: bid.netRevenue === 'net', - currency: cur, - burl: bid.burl || '', - mediaType: mediaType, - width: bidResponse.w, - height: bidResponse.h, - dealId: bidResponse.dealid, - }; - - deepSetValue(result, 'meta.mediaType', mediaType); - if (isArray(bidResponse.adomain)) { - deepSetValue(result, 'meta.advertiserDomains', bidResponse.adomain); - } + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @return {bidRequests[]} An array of bids which were nested inside the server. + */ + interpretResponse: + function (serverResponse) { + utils.logMessage(`interpretResponse adxcg`); + let bidsAll = []; + + if (!serverResponse || !serverResponse.body || !utils.isArray(serverResponse.body.seatbid) || !serverResponse.body.seatbid.length) { + utils.logWarn(BIDDER_CODE + ': empty bid response'); + return bidsAll; + } + + serverResponse.body.seatbid.forEach((bids) => { + bids.bid.forEach((serverResponseOneItem) => { + let bid = {} + // parse general fields + bid.requestId = serverResponseOneItem.impid; + bid.cpm = serverResponseOneItem.price; + bid.creativeId = parseInt(serverResponseOneItem.crid); + bid.currency = serverResponseOneItem.currency ? serverResponseOneItem.currency : 'USD'; + bid.netRevenue = serverResponseOneItem.netRevenue ? serverResponseOneItem.netRevenue : true; + bid.ttl = serverResponseOneItem.ttl ? serverResponseOneItem.ttl : 300; + bid.width = serverResponseOneItem.w; + bid.height = serverResponseOneItem.h; + bid.burl = serverResponseOneItem.burl || ''; + + if (serverResponseOneItem.dealid != null && serverResponseOneItem.dealid.trim().length > 0) { + bid.dealId = serverResponseOneItem.dealid; + } - if (isPlainObject(bidResponse.ext)) { - if (isStr(bidResponse.ext.mediaType)) { - deepSetValue(result, 'meta.mediaType', mediaType); + if (serverResponseOneItem.ext.crType === 'banner') { + bid.ad = serverResponseOneItem.adm; + } else if (serverResponseOneItem.ext.crType === 'video') { + bid.vastUrl = serverResponseOneItem.nurl; + bid.vastXml = serverResponseOneItem.adm; + bid.mediaType = 'video'; + } else if (serverResponseOneItem.ext.crType === 'native') { + bid.mediaType = 'native'; + bid.native = parseNative(JSON.parse(serverResponseOneItem.adm)); + } else { + utils.logWarn(BIDDER_CODE + ': unknown or undefined crType'); } - if (isStr(bidResponse.ext.advertiser_id)) { - deepSetValue(result, 'meta.advertiserId', bidResponse.ext.advertiser_id); + + // prebid 4.0 meta taxonomy + if (utils.isArray(serverResponseOneItem.adomain)) { + utils.deepSetValue(bid, 'meta.advertiserDomains', serverResponseOneItem.adomain); } - if (isStr(bidResponse.ext.advertiser_name)) { - deepSetValue(result, 'meta.advertiserName', bidResponse.ext.advertiser_name); + if (utils.isArray(serverResponseOneItem.cat)) { + utils.deepSetValue(bid, 'meta.secondaryCatIds', serverResponseOneItem.cat); } - if (isStr(bidResponse.ext.agency_name)) { - deepSetValue(result, 'meta.agencyName', bidResponse.ext.agency_name); + if (utils.isPlainObject(serverResponseOneItem.ext)) { + if (utils.isStr(serverResponseOneItem.ext.advertiser_id)) { + utils.deepSetValue(bid, 'meta.mediaType', serverResponseOneItem.ext.mediaType); + } + if (utils.isStr(serverResponseOneItem.ext.advertiser_id)) { + utils.deepSetValue(bid, 'meta.advertiserId', serverResponseOneItem.ext.advertiser_id); + } + if (utils.isStr(serverResponseOneItem.ext.advertiser_name)) { + utils.deepSetValue(bid, 'meta.advertiserName', serverResponseOneItem.ext.advertiser_name); + } + if (utils.isStr(serverResponseOneItem.ext.agency_name)) { + utils.deepSetValue(bid, 'meta.agencyName', serverResponseOneItem.ext.agency_name); + } } - } - if (mediaType === BANNER) { - result.ad = bidResponse.adm; - } else if (mediaType === NATIVE) { - result.native = parseNative(bidResponse); - result.width = 0; - result.height = 0; - } else if (mediaType === VIDEO) { - result.vastUrl = bidResponse.nurl; - result.vastXml = bidResponse.adm; - } + bidsAll.push(bid) + }) + }) + return bidsAll + }, - return result; - } - }).filter(Boolean); + onBidWon: (bid) => { + if (bid.burl) { + utils.triggerPixel(utils.replaceAuctionPrice(bid.burl, bid.originalCpm)); + } }, - getUserSyncs: (syncOptions, responses, gdprConsent, uspConsent) => { - const syncs = []; - let syncUrl = config.getConfig('adxcg.usersyncUrl'); - - let query = []; - if (syncOptions.pixelEnabled && syncUrl) { - if (gdprConsent) { - query.push('gdpr=' + (gdprConsent.gdprApplies & 1)); - query.push('gdpr_consent=' + encodeURIComponent(gdprConsent.consentString || '')); - } - if (uspConsent) { - query.push('us_privacy=' + encodeURIComponent(uspConsent)); - } - syncs.push({ - type: 'image', - url: syncUrl + (query.length ? '?' + query.join('&') : '') - }); + onTimeout(timeoutData) { + if (timeoutData == null) { + return; } - return syncs; + + let beaconParams = { + A: timeoutData.bidder, + bid: timeoutData.bidId, + a: timeoutData.adUnitCode, + cn: timeoutData.timeout, + aud: timeoutData.auctionId, + }; + let adxcgRequestUrl = utils.buildUrl({ + protocol: 'https', + hostname: 'hbps.adxcg.net', + pathname: '/event/timeout.gif', + search: beaconParams + }); + utils.logWarn(BIDDER_CODE + ': onTimeout called'); + utils.triggerPixel(adxcgRequestUrl); }, - onBidWon: (bid) => { - // for native requests we put the nurl as an imp tracker, otherwise if the auction takes place on prebid server - // the server JS adapter puts the nurl in the adm as a tracking pixel and removes the attribute - if (bid.nurl) { - triggerPixel(replaceAuctionPrice(bid.nurl, bid.originalCpm)) + + getUserSyncs: function (syncOptions, serverResponses, gdprConsent) { + let params = ''; + if (gdprConsent && 'gdprApplies' in gdprConsent) { + if (gdprConsent.consentString) { + if (typeof gdprConsent.gdprApplies === 'boolean') { + params += `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { + params += `?gdpr=0&gdpr_consent=${gdprConsent.consentString}`; + } + } + } + + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: 'https://cdn.adxcg.net/pb-sync.html' + params + }]; } } -}; +} -registerBidder(spec); +function isVideoRequest(bid) { + return bid.mediaType === 'video' || !!utils.deepAccess(bid, 'mediaTypes.video'); +} -function parseNative(bid) { - const { assets, link, imptrackers, jstracker } = JSON.parse(bid.adm); - const result = { - clickUrl: link.url, - clickTrackers: link.clicktrackers || undefined, - impressionTrackers: imptrackers || undefined, - javascriptTrackers: jstracker ? [ jstracker ] : undefined - }; - assets.forEach(asset => { - const kind = NATIVE_ASSET_IDS[asset.id]; - const content = kind && asset[NATIVE_PARAMS[kind].name]; - if (content) { - result[kind] = content.text || content.value || { url: content.url, width: content.w, height: content.h }; - } - }); - return result; +function isBannerRequest(bid) { + return bid.mediaType === 'banner' || !!utils.deepAccess(bid, 'mediaTypes.banner'); } -function setOnAny(collection, key) { - for (let i = 0, result; i < collection.length; i++) { - result = deepAccess(collection[i], key); - if (result) { - return result; - } +function isNativeRequest(bid) { + return bid.mediaType === 'native' || !!utils.deepAccess(bid, 'mediaTypes.native'); +} + +function getFloor(bid) { + if (!utils.isFn(bid.getFloor)) { + return utils.deepAccess(bid, 'params.floor', DEFAULT_MIN_FLOOR); + } + + try { + const floor = bid.getFloor({ + currency: 'EUR', + mediaType: '*', + size: '*', + bidRequest: bid + }); + return floor.floor; + } catch (e) { + utils.logWarn(BIDDER_CODE + ': call to getFloor failed:' + e.message); + return DEFAULT_MIN_FLOOR; } } -function flatten(arr) { - return [].concat(...arr); +function parseNative(nativeResponse) { + let bidNative = {}; + bidNative = { + clickUrl: nativeResponse.link.url, + impressionTrackers: nativeResponse.imptrackers, + clickTrackers: nativeResponse.clktrackers, + javascriptTrackers: nativeResponse.jstrackers + }; + + nativeResponse.assets.forEach(asset => { + if (asset.title && asset.title.text) { + bidNative.title = asset.title.text; + } + + if (asset.img && asset.img.url) { + bidNative.image = { + url: asset.img.url, + height: asset.img.h, + width: asset.img.w + }; + } + + if (asset.icon && asset.icon.url) { + bidNative.icon = { + url: asset.icon.url, + height: asset.icon.h, + width: asset.icon.w + }; + } + + if (asset.data && asset.data.label === 'DESC' && asset.data.value) { + bidNative.body = asset.data.value; + } + + if (asset.data && asset.data.label === 'SPONSORED' && asset.data.value) { + bidNative.sponsoredBy = asset.data.value; + } + }) + return bidNative; } + +registerBidder(spec) diff --git a/modules/adxcgBidAdapter.md b/modules/adxcgBidAdapter.md index 1e4ef9cd6f9..8eccdb11dee 100644 --- a/modules/adxcgBidAdapter.md +++ b/modules/adxcgBidAdapter.md @@ -34,34 +34,31 @@ Module that connects to an Adxcg.com zone to fetch bids. code: 'native-ad-div', mediaTypes: { native: { - image: { + image: { sendId: false, - required: false, - sizes: [127, 83] + required: true, + sizes: [80, 80] }, icon: { - sizes: [80, 80], - required: false, + sendId: true, + }, + brand: { sendId: true, }, title: { sendId: false, - required: false, + required: true, len: 75 }, body: { sendId: false, - required: false, + required: true, len: 200 }, - cta: { - sendId: false, - required: false, - len: 75 - }, sponsoredBy: { sendId: false, - required: false + required: false, + len: 20 } } }, @@ -76,19 +73,21 @@ Module that connects to an Adxcg.com zone to fetch bids. code: 'video-div', mediaTypes: { video: { - playerSize: [640, 480], - context: 'instream', - mimes: ['video/mp4'], - protocols: [2, 3, 5, 6, 8], - playback_method: ['auto_play_sound_off'], - maxduration: 100, - skip: 1 - } + playerSize: [640, 480], + context: 'instream', + mimes: ['video/mp4'], + protocols: [5, 6, 8], + playback_method: ['auto_play_sound_off'] + } }, bids: [{ bidder: 'adxcg', params: { - adzoneid: '20' + adzoneid: '20', + video: { + maxduration: 100, + skippable: true + } } }] } diff --git a/modules/adxpremiumAnalyticsAdapter.js b/modules/adxpremiumAnalyticsAdapter.js index 9066c26fb00..f11e3b8d4e5 100644 --- a/modules/adxpremiumAnalyticsAdapter.js +++ b/modules/adxpremiumAnalyticsAdapter.js @@ -1,9 +1,9 @@ -import {deepClone, logError, logInfo} from '../src/utils.js'; -import {ajax} from '../src/ajax.js'; +import { ajax } from '../src/ajax.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; -import {includes} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import includes from 'core-js-pure/features/array/includes.js'; const analyticsType = 'endpoint'; const defaultUrl = 'https://adxpremium.services/graphql'; @@ -95,7 +95,7 @@ function auctionInit(args) { completeObject.auction_id = args.auctionId; completeObject.publisher_id = adxpremiumAnalyticsAdapter.initOptions.pubId; - try { completeObject.referer = encodeURI(args.bidderRequests[0].refererInfo.referer.split('?')[0]); } catch (e) { logError('AdxPremium Analytics - ' + e.message); } + try { completeObject.referer = encodeURI(args.bidderRequests[0].refererInfo.referer.split('?')[0]); } catch (e) { utils.logError('AdxPremium Analytics - ' + e.message); } if (args.adUnitCodes && args.adUnitCodes.length > 0) { elementIds = args.adUnitCodes; } @@ -140,20 +140,20 @@ function bidWon(args) { if (requestDelivered) { if (completeObject.events[eventIndex]) { // do the upgrade - logInfo('AdxPremium Analytics - Upgrading request'); + utils.logInfo('AdxPremium Analytics - Upgrading request'); completeObject.events[eventIndex].is_winning = true; completeObject.events[eventIndex].is_upgrade = true; - upgradedObject = deepClone(completeObject); + upgradedObject = utils.deepClone(completeObject); upgradedObject.events = [completeObject.events[eventIndex]]; sendEvent(upgradedObject); // send upgrade } else { - logInfo('AdxPremium Analytics - CANNOT FIND INDEX FOR REQUEST ' + args.requestId); + utils.logInfo('AdxPremium Analytics - CANNOT FIND INDEX FOR REQUEST ' + args.requestId); } } else { completeObject.events[eventIndex].is_winning = true; } } else { - logInfo('AdxPremium Analytics - Response not found, creating new one.'); + utils.logInfo('AdxPremium Analytics - Response not found, creating new one.'); let tmpObject = { type: 'RESPONSE', bidder_code: args.bidderCode, @@ -167,14 +167,14 @@ function bidWon(args) { is_winning: true, is_lost: true }; - let lostObject = deepClone(completeObject); + let lostObject = utils.deepClone(completeObject); lostObject.events = [tmpObject]; sendEvent(lostObject); // send lost object } } function bidTimeout(args) { - let timeoutObject = deepClone(completeObject); + let timeoutObject = utils.deepClone(completeObject); timeoutObject.events = []; let usedRequestIds = []; @@ -191,12 +191,12 @@ function bidTimeout(args) { if (timeoutObject.events.length > 0) { sendEvent(timeoutObject); // send timeouted - logInfo('AdxPremium Analytics - Sending timeouted requests'); + utils.logInfo('AdxPremium Analytics - Sending timeouted requests'); } } function auctionEnd(args) { - logInfo('AdxPremium Analytics - Auction Ended at ' + Date.now()); + utils.logInfo('AdxPremium Analytics - Auction Ended at ' + Date.now()); if (timeoutBased) { setTimeout(function () { requestSent = true; sendEvent(completeObject); }, 3500); } else { sendEventFallback(); } } @@ -212,22 +212,22 @@ function deviceType() { } function clearSlot(elementId) { - if (includes(elementIds, elementId)) { elementIds.splice(elementIds.indexOf(elementId), 1); logInfo('AdxPremium Analytics - Done with: ' + elementId); } + if (includes(elementIds, elementId)) { elementIds.splice(elementIds.indexOf(elementId), 1); utils.logInfo('AdxPremium Analytics - Done with: ' + elementId); } if (elementIds.length == 0 && !requestSent && !timeoutBased) { requestSent = true; sendEvent(completeObject); - logInfo('AdxPremium Analytics - Everything ready'); + utils.logInfo('AdxPremium Analytics - Everything ready'); } } export function testSend() { sendEvent(completeObject); - logInfo('AdxPremium Analytics - Sending without any conditions, used for testing'); + utils.logInfo('AdxPremium Analytics - Sending without any conditions, used for testing'); } function sendEventFallback() { setTimeout(function () { - if (!requestSent) { requestSent = true; sendEvent(completeObject); logInfo('AdxPremium Analytics - Sending event using fallback method.'); } + if (!requestSent) { requestSent = true; sendEvent(completeObject); utils.logInfo('AdxPremium Analytics - Sending event using fallback method.'); } }, 2000); } @@ -241,11 +241,11 @@ function sendEvent(completeObject) { if (adxpremiumAnalyticsAdapter.initOptions.sid) { ajaxEndpoint = 'https://' + adxpremiumAnalyticsAdapter.initOptions.sid + '.adxpremium.services/graphql' } - ajax(ajaxEndpoint, function () { logInfo('AdxPremium Analytics - Sending complete events at ' + Date.now()) }, dataToSend, { + ajax(ajaxEndpoint, function () { utils.logInfo('AdxPremium Analytics - Sending complete events at ' + Date.now()) }, dataToSend, { contentType: 'application/json', method: 'POST' }); - } catch (err) { logError('AdxPremium Analytics - Sending event error: ' + err); } + } catch (err) { utils.logError('AdxPremium Analytics - Sending event error: ' + err); } } // save the base class function @@ -256,7 +256,7 @@ adxpremiumAnalyticsAdapter.enableAnalytics = function (config) { adxpremiumAnalyticsAdapter.initOptions = config.options; if (!config.options.pubId) { - logError('AdxPremium Analytics - Publisher ID (pubId) option is not defined. Analytics won\'t work'); + utils.logError('AdxPremium Analytics - Publisher ID (pubId) option is not defined. Analytics won\'t work'); return; } diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index 6fcce753596..38731fdc91c 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -1,15 +1,13 @@ -import {buildUrl, deepAccess, parseSizesInput} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {config} from '../src/config.js'; -import {createEidsArray} from './userId/eids.js'; -import {find} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; +import find from 'core-js-pure/features/array/find.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; const VERSION = '1.0'; const BIDDER_CODE = 'adyoulike'; const DEFAULT_DC = 'hb-api'; const CURRENCY = 'USD'; -const GVLID = 259; const NATIVE_IMAGE = { image: { @@ -37,7 +35,6 @@ const NATIVE_IMAGE = { export const spec = { code: BIDDER_CODE, - gvlid: GVLID, supportedMediaTypes: [BANNER, NATIVE, VIDEO], aliases: ['ayl'], // short code /** @@ -61,7 +58,6 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function (bidRequests, bidderRequest) { - let hasVideo = false; const payload = { Version: VERSION, Bids: bidRequests.reduce((accumulator, bidReq) => { @@ -89,7 +85,6 @@ export const spec = { accumulator[bidReq.bidId].Native = nativeReq; } if (mediatype === VIDEO) { - hasVideo = true; accumulator[bidReq.bidId].Video = bidReq.mediaTypes.video; const size = bidReq.mediaTypes.video.playerSize; @@ -102,21 +97,17 @@ export const spec = { PageRefreshed: getPageRefreshed() }; - if (bidderRequest.gdprConsent) { + if (bidderRequest && bidderRequest.gdprConsent) { payload.gdprConsent = { consentString: bidderRequest.gdprConsent.consentString, consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : null }; } - if (bidderRequest.uspConsent) { + if (bidderRequest && bidderRequest.uspConsent) { payload.uspConsent = bidderRequest.uspConsent; } - if (deepAccess(bidderRequest, 'userId')) { - payload.userId = createEidsArray(bidderRequest.userId); - } - const data = JSON.stringify(payload); const options = { withCredentials: true @@ -124,7 +115,7 @@ export const spec = { return { method: 'POST', - url: createEndpoint(bidRequests, bidderRequest, hasVideo), + url: createEndpoint(bidRequests, bidderRequest), data, options }; @@ -184,13 +175,11 @@ function getCanonicalUrl() { /* Get mediatype from bidRequest */ function getMediatype(bidRequest) { - if (deepAccess(bidRequest, 'mediaTypes.banner')) { - return BANNER; - } - if (deepAccess(bidRequest, 'mediaTypes.video')) { + if (utils.deepAccess(bidRequest, 'mediaTypes.video')) { return VIDEO; - } - if (deepAccess(bidRequest, 'mediaTypes.native')) { + } else if (utils.deepAccess(bidRequest, 'mediaTypes.banner')) { + return BANNER; + } else if (utils.deepAccess(bidRequest, 'mediaTypes.native')) { return NATIVE; } } @@ -219,13 +208,12 @@ function getPageRefreshed() { } /* Create endpoint url */ -function createEndpoint(bidRequests, bidderRequest, hasVideo) { +function createEndpoint(bidRequests, bidderRequest) { let host = getHostname(bidRequests); - const endpoint = hasVideo ? '/hb-api/prebid-video/v1' : '/hb-api/prebid/v1'; - return buildUrl({ + return utils.buildUrl({ protocol: 'https', host: `${DEFAULT_DC}${host}.omnitagjs.com`, - pathname: endpoint, + pathname: '/hb-api/prebid/v1', search: createEndpointQS(bidderRequest) }); } @@ -272,7 +260,7 @@ function getSizeArray(bid) { } } - return parseSizesInput(inputSize); + return utils.parseSizesInput(inputSize); } /* Get parsed size from request size */ @@ -350,6 +338,14 @@ function getTrackers(eventsArray, jsTrackers) { return result; } +function getVideoAd(response) { + var adJson = {}; + if (typeof response.Ad === 'string') { + adJson = JSON.parse(response.Ad.match(/\/\*PREBID\*\/(.*)\/\*PREBID\*\//)[1]); + return utils.deepAccess(adJson, 'Content.MainVideo.Vast'); + } +} + function getNativeAssets(response, nativeConfig) { if (typeof response.Native === 'object') { return response.Native; @@ -408,7 +404,7 @@ function getNativeAssets(response, nativeConfig) { imgSize[1] = response.Height || 250; } - const url = getImageUrl(adJson, deepAccess(adJson, 'Content.Preview.Thumbnail.Image'), imgSize[0], imgSize[1]); + const url = getImageUrl(adJson, utils.deepAccess(adJson, 'Content.Preview.Thumbnail.Image'), imgSize[0], imgSize[1]); if (url) { native[key] = { url, @@ -426,9 +422,9 @@ function getNativeAssets(response, nativeConfig) { iconSize[1] = 50; } - const icurl = getImageUrl(adJson, deepAccess(adJson, 'Content.Preview.Sponsor.Logo.Resource'), iconSize[0], iconSize[1]); + const icurl = getImageUrl(adJson, utils.deepAccess(adJson, 'Content.Preview.Sponsor.Logo.Resource'), iconSize[0], iconSize[1]); - if (icurl) { + if (url) { native[key] = { url: icurl, width: iconSize[0], @@ -437,10 +433,10 @@ function getNativeAssets(response, nativeConfig) { } break; case 'privacyIcon': - native[key] = getImageUrl(adJson, deepAccess(adJson, 'Content.Preview.Credit.Logo.Resource'), 25, 25); + native[key] = getImageUrl(adJson, utils.deepAccess(adJson, 'Content.Preview.Credit.Logo.Resource'), 25, 25); break; case 'privacyLink': - native[key] = deepAccess(adJson, 'Content.Preview.Credit.Url'); + native[key] = utils.deepAccess(adJson, 'Content.Preview.Credit.Url'); break; } }); @@ -477,17 +473,13 @@ function createBid(response, bidRequests) { meta: response.Meta || { advertiserDomains: [] } }; - // retreive video response if present - const vast64 = response.Vast; - if (vast64) { - bid.width = response.Width; - bid.height = response.Height; - bid.vastXml = window.atob(vast64); - bid.mediaType = 'video'; - } else if (request.Native) { - // format Native response if Native was requested + if (request && request.Native) { bid.native = getNativeAssets(response, request.Native); bid.mediaType = 'native'; + } else if (request && request.Video) { + const vast64 = response.Vast || getVideoAd(response); + bid.vastXml = vast64 ? window.atob(vast64) : ''; + bid.mediaType = 'video'; } else { bid.width = response.Width; bid.height = response.Height; diff --git a/modules/afpBidAdapter.js b/modules/afpBidAdapter.js deleted file mode 100644 index 6565942bcc8..00000000000 --- a/modules/afpBidAdapter.js +++ /dev/null @@ -1,166 +0,0 @@ -import {includes} from '../src/polyfill.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {Renderer} from '../src/Renderer.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; - -export const IS_DEV = location.hostname === 'localhost' -export const BIDDER_CODE = 'afp' -export const SSP_ENDPOINT = 'https://ssp.afp.ai/api/prebid' -export const REQUEST_METHOD = 'POST' -export const TEST_PAGE_URL = 'https://rtbinsight.ru/smiert-bolshikh-dannykh-kto-na-novienkogo/' -const SDK_PATH = 'https://cdn.afp.ai/ssp/sdk.js?auto_initialization=false&deploy_to_parent_window=true' -const TTL = 60 -export const IN_IMAGE_BANNER_TYPE = 'In-image' -export const IN_IMAGE_MAX_BANNER_TYPE = 'In-image Max' -export const IN_CONTENT_BANNER_TYPE = 'In-content Banner' -export const IN_CONTENT_VIDEO_TYPE = 'In-content Video' -export const OUT_CONTENT_VIDEO_TYPE = 'Out-content Video' -export const IN_CONTENT_STORY_TYPE = 'In-content Stories' -export const ACTION_SCROLLER_TYPE = 'Action Scroller' -export const ACTION_SCROLLER_LIGHT_TYPE = 'Action Scroller Light' -export const JUST_BANNER_TYPE = 'Just Banner' - -export const mediaTypeByPlaceType = { - [IN_IMAGE_BANNER_TYPE]: BANNER, - [IN_IMAGE_MAX_BANNER_TYPE]: BANNER, - [IN_CONTENT_BANNER_TYPE]: BANNER, - [IN_CONTENT_STORY_TYPE]: BANNER, - [ACTION_SCROLLER_TYPE]: BANNER, - [ACTION_SCROLLER_LIGHT_TYPE]: BANNER, - [JUST_BANNER_TYPE]: BANNER, - [IN_CONTENT_VIDEO_TYPE]: VIDEO, - [OUT_CONTENT_VIDEO_TYPE]: VIDEO, -} - -const wrapAd = (dataToCreatePlace) => { - return ` - - - - - - - - - - ` -} - -const bidRequestMap = {} - -const createRenderer = (bid, dataToCreatePlace) => { - const renderer = new Renderer({ - targetId: bid.adUnitCode, - url: SDK_PATH, - callback() { - renderer.loaded = true - window.afp.createPlaceByData(dataToCreatePlace) - } - }) - - return renderer -} - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO], - isBidRequestValid({mediaTypes, params}) { - if (typeof params !== 'object' || typeof mediaTypes !== 'object') { - return false - } - - const {placeId, placeType, imageUrl, imageWidth, imageHeight} = params - const media = mediaTypes[mediaTypeByPlaceType[placeType]] - - if (placeId && media) { - if (mediaTypeByPlaceType[placeType] === VIDEO) { - if (!media.playerSize) { - return false - } - } else if (mediaTypeByPlaceType[placeType] === BANNER) { - if (!media.sizes) { - return false - } - } - if (includes([IN_IMAGE_BANNER_TYPE, IN_IMAGE_MAX_BANNER_TYPE], placeType)) { - if (imageUrl && imageWidth && imageHeight) { - return true - } - } else { - return true - } - } - return false - }, - buildRequests(validBidRequests, {refererInfo, gdprConsent}) { - const payload = { - pageUrl: IS_DEV ? TEST_PAGE_URL : refererInfo.referer, - gdprConsent: gdprConsent, - bidRequests: validBidRequests.map(validBidRequest => { - const {bidId, transactionId, sizes, params: { - placeId, placeType, imageUrl, imageWidth, imageHeight - }} = validBidRequest - bidRequestMap[bidId] = validBidRequest - const bidRequest = { - bidId, - transactionId, - sizes, - placeId, - } - if (includes([IN_IMAGE_BANNER_TYPE, IN_IMAGE_MAX_BANNER_TYPE], placeType)) { - Object.assign(bidRequest, { - imageUrl, - imageWidth: Math.floor(imageWidth), - imageHeight: Math.floor(imageHeight), - }) - } - return bidRequest - }) - } - - return { - method: REQUEST_METHOD, - url: SSP_ENDPOINT, - data: payload, - options: { - contentType: 'application/json' - } - } - }, - interpretResponse(serverResponse) { - let bids = serverResponse.body && serverResponse.body.bids - bids = Array.isArray(bids) ? bids : [] - - return bids.map(({bidId, cpm, width, height, creativeId, currency, netRevenue, adSettings, placeSettings}, index) => { - const bid = { - requestId: bidId, - cpm, - width, - height, - creativeId, - currency, - netRevenue, - meta: { - mediaType: mediaTypeByPlaceType[placeSettings.placeType], - }, - ttl: TTL - } - - const bidRequest = bidRequestMap[bidId] - const placeContainer = bidRequest.params.placeContainer - const dataToCreatePlace = { adSettings, placeSettings, placeContainer, isPrebid: true } - - if (mediaTypeByPlaceType[placeSettings.placeType] === BANNER) { - bid.ad = wrapAd(dataToCreatePlace) - } else if (mediaTypeByPlaceType[placeSettings.placeType] === VIDEO) { - bid.vastXml = adSettings.content - bid.renderer = createRenderer(bid, dataToCreatePlace) - } - return bid - }) - } -} - -registerBidder(spec); diff --git a/modules/afpBidAdapter.md b/modules/afpBidAdapter.md deleted file mode 100644 index 75ebf2bce48..00000000000 --- a/modules/afpBidAdapter.md +++ /dev/null @@ -1,348 +0,0 @@ -# Overview - - -**Module Name**: AFP Bidder Adapter -**Module Type**: Bidder Adapter -**Maintainer**: devops@astraone.io - -# Description - -You can use this adapter to get a bid from AFP. -Please reach out to your AFP account team before using this plugin to get placeId. -The code below returns a demo ad. - -About us: https://afp.ai - -# Test Parameters -```js -var adUnits = [{ - code: 'iib-target', - mediaTypes: { - banner: { - sizes: [[0, 0]], - } - }, - bids: [{ - bidder: "afp", - params: { - placeType: "In-image", - placeId: "613221112871613d1517d181", // id from personal account - placeContainer: '#iib-container', - imageUrl: "https://rtbinsight.ru/content/images/size/w1000/2021/05/ximage-30.png.pagespeed.ic.IfuX4zAEPP.png", - imageWidth: 1000, - imageHeight: 524, - } - }] -}]; - -var adUnits = [{ - code: 'iimb-target', - mediaTypes: { - banner: { - sizes: [[0, 0]], - } - }, - bids: [{ - bidder: "afp", - params: { - placeType: "In-image Max", - placeId: "6139ae472871613d1517dedd", // id from personal account - placeContainer: '#iimb-container', - imageUrl: "https://rtbinsight.ru/content/images/size/w1000/2021/05/ximage-30.png.pagespeed.ic.IfuX4zAEPP.png", - imageWidth: 1000, - imageHeight: 524, - } - }] -}]; - -var adUnits = [{ - code: 'icb-target', - mediaTypes: { - banner: { - sizes: [[0, 0]], - } - }, - bids: [{ - bidder: "afp", - params: { - placeType: "In-content Banner", - placeId: "6139ae082871613d1517dec0", // id from personal account - placeContainer: '#icb-container', - } - }] -}]; - -var adUnits = [{ - code: 'ics-target', - mediaTypes: { - banner: { - sizes: [[0, 0]], - } - }, - bids: [{ - bidder: "afp", - params: { - placeType: "In-content Stories", - placeId: "6139ae292871613d1517ded3", // id from personal account - placeContainer: '#ics-container', - } - }] -}]; - -var adUnits = [{ - code: 'as-target', - mediaTypes: { - banner: { - sizes: [[0, 0]], - } - }, - bids: [{ - bidder: "afp", - params: { - placeType: "Action Scroller", - placeId: "6139adc12871613d1517deb0", // id from personal account - placeContainer: '#as-container', - } - }] -}]; - -var adUnits = [{ - code: 'asl-target', - mediaTypes: { - banner: { - sizes: [[0, 0]], - } - }, - bids: [{ - bidder: "afp", - params: { - placeType: "Action Scroller Light", - placeId: "6139adda2871613d1517deb8", // id from personal account - placeContainer: '#asl-container', - } - }] -}]; - -var adUnits = [{ - code: 'jb-target', - mediaTypes: { - banner: { - sizes: [[300, 250]], - } - }, - bids: [{ - bidder: "afp", - params: { - placeType: "Just Banner", - placeId: "6139ae832871613d1517dee9", // id from personal account - placeContainer: '#jb-container', - } - }] -}]; - -var adUnits = [{ - code: 'icv-target', - mediaTypes: { - video: { - playerSize: [[480, 320]], - } - }, - bids: [{ - bidder: "afp", - params: { - placeType: "In-content Video", - placeId: "6139ae182871613d1517deca", // id from personal account - placeContainer: '#icv-container', - } - }] -}]; - -var adUnits = [{ - code: 'ocv-target', - mediaTypes: { - video: { - playerSize: [[480, 320]], - } - }, - bids: [{ - bidder: "afp", - params: { - placeType: "Out-content Video", - placeId: "6139ae5b2871613d1517dee2", // id from personal account - placeContainer: '#ocv-container', // only the "body" tag is used as a container - } - }] -}]; -``` - -# Example page - -```html - - - - - Prebid.js In-image Example - - - - -

In-image

-
-
- -
- -
- -

Just Banner

-
-
- -
- - - -``` -# Example page with GPT - -```html - - - - - Prebid.js In-image Example - - - - - -

In-image

-
-
- -
-
- -
-
- - -``` diff --git a/modules/airgridRtdProvider.js b/modules/airgridRtdProvider.js index b2e78a7df78..8d212204da8 100644 --- a/modules/airgridRtdProvider.js +++ b/modules/airgridRtdProvider.js @@ -16,7 +16,7 @@ const SUBMODULE_NAME = 'airgrid'; const AG_TCF_ID = 782; export const AG_AUDIENCE_IDS_KEY = 'edkt_matched_audience_ids' -export const storage = getStorageManager({gvlid: AG_TCF_ID, moduleName: SUBMODULE_NAME}); +export const storage = getStorageManager(AG_TCF_ID, SUBMODULE_NAME); /** * Attach script tag to DOM @@ -33,7 +33,7 @@ export function attachScriptTagToDOM(rtdConfig) { edktInitializor.load = function(e) { var p = e || 'sdk'; var n = document.createElement('script'); - n.type = 'module'; + n.type = 'text/javascript'; n.async = true; n.src = 'https://cdn.edkt.io/' + p + '/edgekit.min.js'; document.getElementsByTagName('head')[0].appendChild(n); diff --git a/modules/ajaBidAdapter.js b/modules/ajaBidAdapter.js index a9364a7a05f..7b55ee7780a 100644 --- a/modules/ajaBidAdapter.js +++ b/modules/ajaBidAdapter.js @@ -1,5 +1,5 @@ -import { getBidIdParameter, tryAppendQueryString, createTrackPixelHtml, logError, logWarn } from '../src/utils.js'; import { Renderer } from '../src/Renderer.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { VIDEO, BANNER, NATIVE } from '../src/mediaTypes.js'; @@ -16,48 +16,23 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: [VIDEO, BANNER, NATIVE], - /** - * Determines whether or not the given bid has all the params needed to make a valid request. - * - * @param {BidRequest} bidRequest - * @returns {boolean} - */ - isBidRequestValid: function(bidRequest) { - return !!(bidRequest.params.asi); + isBidRequestValid: function(bid) { + return !!(bid.params.asi); }, - /** - * Build the request to the Server which requests Bids for the given array of Requests. - * Each BidRequest in the argument array is guaranteed to have passed the isBidRequestValid() test. - * - * @param {BidRequest[]} validBidRequests - * @param {*} bidderRequest - * @returns {ServerRequest|ServerRequest[]} - */ buildRequests: function(validBidRequests, bidderRequest) { const bidRequests = []; - const pageUrl = (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) || undefined; - for (let i = 0, len = validBidRequests.length; i < len; i++) { - const bidRequest = validBidRequests[i]; + const bid = validBidRequests[i]; let queryString = ''; - - const asi = getBidIdParameter('asi', bidRequest.params); - queryString = tryAppendQueryString(queryString, 'asi', asi); - queryString = tryAppendQueryString(queryString, 'skt', SDK_TYPE); - queryString = tryAppendQueryString(queryString, 'tid', bidRequest.transactionId) - queryString = tryAppendQueryString(queryString, 'prebid_id', bidRequest.bidId); - queryString = tryAppendQueryString(queryString, 'prebid_ver', '$prebid.version$'); - - if (pageUrl) { - queryString = tryAppendQueryString(queryString, 'page_url', pageUrl); - } - - const eids = bidRequest.userIdAsEids; - if (eids && eids.length) { - queryString = tryAppendQueryString(queryString, 'eids', JSON.stringify({ - 'eids': eids, - })) + const asi = utils.getBidIdParameter('asi', bid.params); + queryString = utils.tryAppendQueryString(queryString, 'asi', asi); + queryString = utils.tryAppendQueryString(queryString, 'skt', SDK_TYPE); + queryString = utils.tryAppendQueryString(queryString, 'prebid_id', bid.bidId); + queryString = utils.tryAppendQueryString(queryString, 'prebid_ver', '$prebid.version$'); + + if (bidderRequest && bidderRequest.refererInfo) { + queryString = utils.tryAppendQueryString(queryString, 'page_url', bidderRequest.refererInfo.referer); } bidRequests.push({ @@ -114,11 +89,11 @@ export const spec = { }); try { bannerAd.imps.forEach(impTracker => { - const tracker = createTrackPixelHtml(impTracker); + const tracker = utils.createTrackPixelHtml(impTracker); bid.ad += tracker; }); } catch (error) { - logError('Error appending tracking pixel', error); + utils.logError('Error appending tracking pixel', error); } Array.prototype.push.apply(bid.meta.advertiserDomains, bannerAd.adomain) @@ -207,7 +182,7 @@ function newRenderer(bidderResponse) { try { renderer.setRender(outstreamRender); } catch (err) { - logWarn('Prebid Error calling setRender on newRenderer', err); + utils.logWarn('Prebid Error calling setRender on newRenderer', err); } return renderer; diff --git a/modules/akamaiDAPIdSystem.js b/modules/akamaiDAPIdSystem.js index 5e3a607d5fd..a78d65b40a9 100644 --- a/modules/akamaiDAPIdSystem.js +++ b/modules/akamaiDAPIdSystem.js @@ -5,7 +5,7 @@ * @requires module:modules/userId */ -import { logMessage, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js' import { ajax } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; import { getStorageManager } from '../src/storageManager.js'; @@ -29,7 +29,7 @@ export const akamaiDAPIdSubmodule = { * @returns {{dapId:string}} */ decode(value) { - logMessage('akamaiDAPId [decode] value=', value); + utils.logMessage('akamaiDAPId [decode] value=', value); return { dapId: value }; }, @@ -43,23 +43,23 @@ export const akamaiDAPIdSubmodule = { getId(config, consentData) { const configParams = (config && config.params); if (!configParams) { - logError('User ID - akamaiDAPId submodule requires a valid configParams'); + utils.logError('User ID - akamaiDAPId submodule requires a valid configParams'); return; } else if (typeof configParams.apiHostname !== 'string') { - logError('User ID - akamaiDAPId submodule requires a valid configParams.apiHostname'); + utils.logError('User ID - akamaiDAPId submodule requires a valid configParams.apiHostname'); return; } else if (typeof configParams.domain !== 'string') { - logError('User ID - akamaiDAPId submodule requires a valid configParams.domain'); + utils.logError('User ID - akamaiDAPId submodule requires a valid configParams.domain'); return; } else if (typeof configParams.type !== 'string') { - logError('User ID - akamaiDAPId submodule requires a valid configParams.type'); + utils.logError('User ID - akamaiDAPId submodule requires a valid configParams.type'); return; } const hasGdpr = (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0; const gdprConsentString = hasGdpr ? consentData.consentString : ''; const uspConsent = uspDataHandler.getConsentData(); if (hasGdpr && (!gdprConsentString || gdprConsentString === '')) { - logError('User ID - akamaiDAPId submodule requires consent string to call API'); + utils.logError('User ID - akamaiDAPId submodule requires consent string to call API'); return; } // XXX: retrieve first-party data here if needed @@ -99,14 +99,14 @@ export const akamaiDAPIdSubmodule = { storage.setDataInLocalStorage(STORAGE_KEY, token); }, error: error => { - logError('akamaiDAPId [getId:ajax.error] failed to retrieve ' + tokenName, error); + utils.logError('akamaiDAPId [getId:ajax.error] failed to retrieve ' + tokenName, error); } }; ajax(url, cb, JSON.stringify(postData), { contentType: 'application/json' }); let token = storage.getDataFromLocalStorage(STORAGE_KEY); - logMessage('akamaiDAPId [getId] returning', token); + utils.logMessage('akamaiDAPId [getId] returning', token); return { id: token }; } diff --git a/modules/akamaiDapRtdProvider.js b/modules/akamaiDapRtdProvider.js deleted file mode 100644 index aca984d39c8..00000000000 --- a/modules/akamaiDapRtdProvider.js +++ /dev/null @@ -1,474 +0,0 @@ -/** - * This module adds the Akamai DAP RTD provider to the real time data module - * The {@link module:modules/realTimeData} module is required - * The module will fetch real-time data from DAP - * @module modules/akamaiDapRtdProvider - * @requires module:modules/realTimeData - */ -import {ajax} from '../src/ajax.js'; -import {config} from '../src/config.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {submodule} from '../src/hook.js'; -import {isPlainObject, mergeDeep, logMessage, logInfo, logError} from '../src/utils.js'; - -const MODULE_NAME = 'realTimeData'; -const SUBMODULE_NAME = 'dap'; - -export const SEGMENTS_STORAGE_KEY = 'akamaiDapSegments'; -export const storage = getStorageManager({gvlid: null, moduleName: SUBMODULE_NAME}); - -/** - * Lazy merge objects. - * @param {String} target - * @param {String} source - */ -function mergeLazy(target, source) { - if (!isPlainObject(target)) { - target = {}; - } - if (!isPlainObject(source)) { - source = {}; - } - return mergeDeep(target, source); -} - -/** - * Add real-time data & merge segments. - * @param {Object} bidConfig - * @param {Object} rtd - * @param {Object} rtdConfig - */ -export function addRealTimeData(rtd) { - logInfo('DEBUG(addRealTimeData) - ENTER'); - if (isPlainObject(rtd.ortb2)) { - let ortb2 = config.getConfig('ortb2') || {}; - logMessage('DEBUG(addRealTimeData): merging original: ', ortb2); - logMessage('DEBUG(addRealTimeData): merging in: ', rtd.ortb2); - config.setConfig({ortb2: mergeLazy(ortb2, rtd.ortb2)}); - } - logInfo('DEBUG(addRealTimeData) - EXIT'); -} - -/** - * Real-time data retrieval from Audigent - * @param {Object} reqBidsConfigObj - * @param {function} onDone - * @param {Object} rtdConfi - * @param {Object} userConsent - */ -export function getRealTimeData(bidConfig, onDone, rtdConfig, userConsent) { - logInfo('DEBUG(getRealTimeData) - ENTER'); - logMessage(' - apiHostname: ' + rtdConfig.params.apiHostname); - logMessage(' - apiVersion: ' + rtdConfig.params.apiVersion); - let jsonData = storage.getDataFromLocalStorage(SEGMENTS_STORAGE_KEY); - if (jsonData) { - let data = JSON.parse(jsonData); - if (data.rtd) { - addRealTimeData(data.rtd); - onDone(); - logInfo('DEBUG(getRealTimeData) - 1'); - // Don't return - ensure the data is always fresh. - } - } - - if (rtdConfig && isPlainObject(rtdConfig.params)) { - let config = { - api_hostname: rtdConfig.params.apiHostname, - api_version: rtdConfig.params.apiVersion, - domain: rtdConfig.params.domain, - segtax: rtdConfig.params.segtax - }; - let identity = { - type: rtdConfig.params.identityType - }; - let token = dapUtils.dapGetToken(config, identity, rtdConfig.params.tokenTtl); - if (token !== null) { - let membership = dapUtils.dapGetMembership(config, token); - let udSegment = dapUtils.dapMembershipToRtbSegment(membership, config); - logMessage('DEBUG(getRealTimeData) - token: ' + token + ', user.data.segment: ', udSegment); - let data = { - rtd: { - ortb2: { - user: { - data: [ - udSegment - ] - }, - site: { - ext: { - data: { - dapSAID: membership.said - } - } - } - } - } - }; - storage.setDataInLocalStorage(SEGMENTS_STORAGE_KEY, JSON.stringify(data)); - onDone(); - } - } -} - -/** - * Module init - * @param {Object} provider - * @param {Object} userConsent - * @return {boolean} - */ -function init(provider, userConsent) { - return true; -} - -/** @type {RtdSubmodule} */ -export const akamaiDapRtdSubmodule = { - name: SUBMODULE_NAME, - getBidRequestData: getRealTimeData, - init: init -}; - -submodule(MODULE_NAME, akamaiDapRtdSubmodule); - -export const dapUtils = { - - dapGetToken: function(config, identity, ttl) { - let now = Math.round(Date.now() / 1000.0); // in seconds - let storageName = 'async_dap_token'; - let token = null; - - if (ttl == 0) { - localStorage.removeItem(storageName); - } - - let item = JSON.parse(localStorage.getItem(storageName)); - if (item == null) { - item = { - expires_at: now - 1, - token: null - }; - } else { - token = item.token; - } - - if (now > item.expires_at) { - dapUtils.dapLog('Token missing or expired, fetching a new one...'); - // Trigger a refresh - let configAsync = {...config}; - dapUtils.dapTokenize(configAsync, identity, - function(token, status, xhr) { - item.expires_at = now + ttl; - item.token = token; - localStorage.setItem(storageName, JSON.stringify(item)); - dapUtils.dapLog('Successfully updated and stored token; expires in ' + ttl + ' seconds'); - let deviceId100 = xhr.getResponseHeader('Akamai-DAP-100'); - if (deviceId100 != null) { - localStorage.setItem('dap_deviceId100', deviceId100); - dapUtils.dapLog('Successfully stored DAP 100 Device ID: ' + deviceId100); - } - }, - function(xhr, status, error) { - logError('ERROR(' + error + '): failed to retrieve token! ' + status); - } - ); - } - - return token; - }, - - dapGetMembership: function(config, token) { - let now = Math.round(Date.now() / 1000.0); // in seconds - let storageName = 'async_dap_membership'; - let maxTtl = 3600; // if the cached membership is older than this, return null - let membership = null; - let item = JSON.parse(localStorage.getItem(storageName)); - if (item == null || (now - item.expires_at) > maxTtl) { - item = { - expires_at: now - 1, - said: null, - cohorts: null, - attributes: null - }; - } else { - membership = { - said: item.said, - cohorts: item.cohorts, - attributes: null - }; - } - - // Always refresh the cached membership. - let configAsync = {...config}; - dapUtils.dapMembership(configAsync, token, - function(membership, status, xhr) { - item.expires_at = now + maxTtl; - item.said = membership.said; - item.cohorts = membership.cohorts; - localStorage.setItem(storageName, JSON.stringify(item)); - dapUtils.dapLog('Successfully updated and stored membership:'); - dapUtils.dapLog(item); - }, - function(xhr, status, error) { - logError('ERROR(' + error + '): failed to retrieve membership! ' + status); - } - ); - - return membership; - }, - - /** - * DESCRIPTION - * - * Convert a DAP membership response to an OpenRTB2 segment object suitable - * for insertion into user.data.segment or site.data.segment. - */ - dapMembershipToRtbSegment: function(membership, config) { - let segment = { - name: 'dap.akamai.com', - ext: { - 'segtax': config.segtax - }, - segment: [] - }; - if (membership != null) { - for (const i of membership.cohorts) { - segment.segment.push({ id: i }); - } - } - return segment; - }, - - dapLog: function(args) { - let css = ''; - css += 'display: inline-block;'; - css += 'color: #fff;'; - css += 'background: #F28B20;'; - css += 'padding: 1px 4px;'; - css += 'border-radius: 3px'; - - logInfo('%cDAP Client', css, args); - }, - - /******************************************************************************* - * - * V2 (And Beyond) API - * - ******************************************************************************/ - - /** - * SYNOPSIS - * - * dapTokenize( config, identity ); - * - * DESCRIPTION - * - * Tokenize an identity into a secure, privacy safe pseudonymiziation. - * - * PARAMETERS - * - * config: an array of system configuration parameters - * - * identity: an array of identity parameters passed to the tokenizing system - * - * EXAMPLE - * - * config = { - * api_hostname: "prebid.dap.akadns.net", // required - * domain: "prebid.org", // required - * api_version: "x1", // optional, default "x1" - * }; - * - * token = null; - * identity_email = { - * type: "email", - * identity: "obiwan@jedi.com" - * attributes: { cohorts: [ "100:1641013200", "101:1641013200", "102":3:1641013200" ] }, - * }; - * dap_x1_tokenize( config, identity_email, - * function( response, status, xhr ) { token = response; }, - * function( xhr, status, error ) { ; } // handle error - * - * token = null; - * identity_signature = { type: "signature:1.0.0" }; - * dap_x1_tokenize( config, identity_signature, - * function( response, status, xhr } { token = response; }, - * function( xhr, status, error ) { ; } // handle error - */ - dapTokenize: function(config, identity, onSuccess = null, onError = null) { - if (onError == null) { - onError = function(xhr, status, error) {}; - } - - if (config == null || typeof (config) == typeof (undefined)) { - onError(null, 'Invalid config object', 'ClientError'); - return; - } - - if (typeof (config.domain) != 'string') { - onError(null, 'Invalid config.domain: must be a string', 'ClientError'); - return; - } - - if (config.domain.length <= 0) { - onError(null, 'Invalid config.domain: must have non-zero length', 'ClientError'); - return; - } - - if (!('api_version' in config) || (typeof (config.api_version) == 'string' && config.api_version.length == 0)) { - config.api_version = 'x1'; - } - - if (typeof (config.api_version) != 'string') { - onError(null, "Invalid api_version: must be a string like 'x1', etc.", 'ClientError'); - return; - } - - if (!(('api_hostname') in config) || typeof (config.api_hostname) != 'string' || config.api_hostname.length == 0) { - onError(null, 'Invalid api_hostname: must be a non-empty string', 'ClientError'); - return; - } - - if (identity == null || typeof (identity) == typeof (undefined)) { - onError(null, 'Invalid identity object', 'ClientError'); - return; - } - - if (!('type' in identity) || typeof (identity.type) != 'string' || identity.type.length <= 0) { - onError(null, "Identity must contain a valid 'type' field", 'ClientError'); - return; - } - - let apiParams = { - 'type': identity.type, - }; - - if (typeof (identity.identity) != typeof (undefined)) { - apiParams.identity = identity.identity; - } - if (typeof (identity.attributes) != typeof (undefined)) { - apiParams.attributes = identity.attributes; - } - - let method; - let body; - let path; - switch (config.api_version) { - case 'x1': - case 'x1-dev': - method = 'POST'; - path = '/data-activation/' + config.api_version + '/domain/' + config.domain + '/identity/tokenize'; - body = JSON.stringify(apiParams); - break; - default: - onError(null, 'Invalid api_version: ' + config.api_version, 'ClientError'); - return; - } - - let url = 'https://' + config.api_hostname + path; - let cb = { - success: (response, request) => { - let token = null; - switch (config.api_version) { - case 'x1': - case 'x1-dev': - token = request.getResponseHeader('Akamai-DAP-Token'); - break; - } - onSuccess(token, request.status, request); - }, - error: (request, error) => { - onError(request, request.statusText, error); - } - }; - - ajax(url, cb, body, { - method: method, - customHeaders: { - 'Content-Type': 'application/json', - 'Pragma': 'akamai-x-cache-on' - } - }); - }, - - /** - * SYNOPSIS - * - * dapMembership( config, token, onSuccess, onError ); - * - * DESCRIPTION - * - * Return the audience segment membership along with a new Secure Advertising - * ID for this token. - * - * PARAMETERS - * - * config: an array of system configuration parameters - * - * token: the token previously returned from the tokenize API - * - * EXAMPLE - * - * config = { - * api_hostname: 'api.dap.akadns.net', - * }; - * - * // token from dap_x1_tokenize - * - * dapMembership( config, token, - * function( membership, status, xhr ) { - * // Run auction with membership.segments and membership.said - * }, - * function( xhr, status, error ) { - * // error - * } ); - * - */ - dapMembership: function(config, token, onSuccess = null, onError = null) { - if (onError == null) { - onError = function(xhr, status, error) {}; - } - - if (config == null || typeof (config) == typeof (undefined)) { - onError(null, 'Invalid config object', 'ClientError'); - return; - } - - if (!('api_version' in config) || (typeof (config.api_version) == 'string' && config.api_version.length == 0)) { - config.api_version = 'x1'; - } - - if (typeof (config.api_version) != 'string') { - onError(null, "Invalid api_version: must be a string like 'x1', etc.", 'ClientError'); - return; - } - - if (!(('api_hostname') in config) || typeof (config.api_hostname) != 'string' || config.api_hostname.length == 0) { - onError(null, 'Invalid api_hostname: must be a non-empty string', 'ClientError'); - return; - } - - if (token == null || typeof (token) != 'string') { - onError(null, 'Invalid token: must be a non-null string', 'ClientError'); - return; - } - let path = '/data-activation/' + - config.api_version + - '/token/' + token + - '/membership'; - - let url = 'https://' + config.api_hostname + path; - - let cb = { - success: (response, request) => { - onSuccess(JSON.parse(response), request.status, request); - }, - error: (error, request) => { - onError(request, request.status, error); - } - }; - - ajax(url, cb, undefined, { - method: 'GET', - customHeaders: {} - }); - } -} diff --git a/modules/akamaiDapRtdProvider.md b/modules/akamaiDapRtdProvider.md deleted file mode 100644 index ade11b88602..00000000000 --- a/modules/akamaiDapRtdProvider.md +++ /dev/null @@ -1,47 +0,0 @@ -### Overview - - Akamai DAP Real time data Provider automatically invokes the DAP APIs and submit audience segments and the SAID to the bid-stream. - -### Integration - - 1) Build the akamaiDapRTD module into the Prebid.js package with: - - ``` - gulp build --modules=akamaiDapRtdProvider,... - ``` - - 2) Use `setConfig` to instruct Prebid.js to initilaize the akamaiDapRtdProvider module, as specified below. - -### Configuration - -``` - pbjs.setConfig({ - realTimeData: { - dataProviders: [ - { - name: "dap", - waitForIt: true, - params: { - apiHostname: '', - apiVersion: "x1", - domain: 'your-domain.com', - identityType: 'email' | 'mobile' | ... | 'dap-signature:1.0.0', - segtax: , - tokenTtl: 5, - } - } - ] - } - }); - ``` - -Please reach out to your Akamai account representative(Prebid@akamai.com) to get provisioned on the DAP platform. - - -### Testing -To view an example of available segments returned by dap: -``` -‘gulp serve --modules=rtdModule,akamaiDapRtdProvider,appnexusBidAdapter,sovrnBidAdapter’ -``` -and then point your browser at: -"http://localhost:9999/integrationExamples/gpt/akamaidap_segments_example.html" diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js deleted file mode 100644 index 261fd9dee68..00000000000 --- a/modules/alkimiBidAdapter.js +++ /dev/null @@ -1,119 +0,0 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { deepClone, deepAccess } from '../src/utils.js'; -import { ajax } from '../src/ajax.js'; -import { VIDEO } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; - -const BIDDER_CODE = 'alkimi'; -export const ENDPOINT = 'https://exchange.alkimi-onboarding.com/bid?prebid=true'; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: ['banner', 'video'], - - isBidRequestValid: function (bid) { - return !!(bid.params && bid.params.bidFloor && bid.params.token); - }, - - buildRequests: function (validBidRequests, bidderRequest) { - let bids = []; - let bidIds = []; - validBidRequests.forEach(bidRequest => { - let sizes = prepareSizes(bidRequest.sizes) - - bids.push({ - token: bidRequest.params.token, - pos: bidRequest.params.pos, - bidFloor: bidRequest.params.bidFloor, - width: sizes[0].width, - height: sizes[0].height, - impMediaType: getFormatType(bidRequest) - }) - bidIds.push(bidRequest.bidId) - }) - - const alkimiConfig = config.getConfig('alkimi'); - - let payload = { - requestId: bidderRequest.auctionId, - signRequest: { bids, randomUUID: alkimiConfig && alkimiConfig.randomUUID }, - bidIds, - referer: bidderRequest.refererInfo.referer, - signature: alkimiConfig && alkimiConfig.signature - } - - const options = { - contentType: 'application/json', - customHeaders: { - 'Rtb-Direct': true - } - } - - return { - method: 'POST', - url: ENDPOINT, - data: payload, - options - }; - }, - - interpretResponse: function (serverResponse, request) { - const serverBody = serverResponse.body; - if (!serverBody || typeof serverBody !== 'object') { - return []; - } - - const { prebidResponse } = serverBody; - if (!prebidResponse || typeof prebidResponse !== 'object') { - return []; - } - - let bids = []; - prebidResponse.forEach(bidResponse => { - let bid = deepClone(bidResponse); - bid.cpm = parseFloat(bidResponse.cpm); - - // banner or video - if (VIDEO === bid.mediaType) { - bid.vastXml = bid.ad; - } - - bid.meta = {}; - bid.meta.advertiserDomains = bid.adomain || []; - - bids.push(bid); - }) - - return bids; - }, - - onBidWon: function (bid) { - let winUrl; - if (bid.winUrl || bid.vastUrl) { - winUrl = bid.winUrl ? bid.winUrl : bid.vastUrl; - winUrl = winUrl.replace(/\$\{AUCTION_PRICE\}/, bid.cpm); - } else if (bid.ad) { - let trackImg = bid.ad.match(/(?!^)/); - bid.ad = bid.ad.replace(trackImg[0], ''); - winUrl = trackImg[0].split('"')[1]; - winUrl = winUrl.replace(/\$%7BAUCTION_PRICE%7D/, bid.cpm); - } else { - return false; - } - - ajax(winUrl, null); - return true; - } -} - -function prepareSizes(sizes) { - return sizes && sizes.map(size => ({ width: size[0], height: size[1] })); -} - -const getFormatType = bidRequest => { - if (deepAccess(bidRequest, 'mediaTypes.banner')) return 'Banner' - if (deepAccess(bidRequest, 'mediaTypes.video')) return 'Video' - if (deepAccess(bidRequest, 'mediaTypes.audio')) return 'Audio' -} - -registerBidder(spec); diff --git a/modules/alkimiBidAdapter.md b/modules/alkimiBidAdapter.md deleted file mode 100644 index 92a7c2aefe1..00000000000 --- a/modules/alkimiBidAdapter.md +++ /dev/null @@ -1,29 +0,0 @@ -# Overview - -``` -Module Name: Alkimi Bidder Adapter -Module Type: Bidder Adapter -Maintainer: abogdanov@asteriosoft.com -``` - -# Description - -Connects to Alkimi Bidder for bids. -Alkimi bid adapter supports Banner and Video ads. - -# Test Parameters -``` -const adUnits = [ - { - bids: [ - { - bidder: 'alkimi', - params: { - bidFloor: 0.1, - token: '?????????????????????', // Publisher Token provided by Alkimi - } - } - ] - } -]; -``` diff --git a/modules/amxBidAdapter.js b/modules/amxBidAdapter.js index d1754936d7f..d48245e9604 100644 --- a/modules/amxBidAdapter.js +++ b/modules/amxBidAdapter.js @@ -5,7 +5,7 @@ import { config } from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; const BIDDER_CODE = 'amx'; -const storage = getStorageManager({gvlid: 737, bidderCode: BIDDER_CODE}); +const storage = getStorageManager(737, BIDDER_CODE); const SIMPLE_TLD_TEST = /\.com?\.\w{2,4}$/; const DEFAULT_ENDPOINT = 'https://prebid.a-mo.net/a/c'; const VERSION = 'pba1.3.1'; diff --git a/modules/aniviewBidAdapter.js b/modules/aniviewBidAdapter.js index 7760aa2b47b..83a1ab20bb4 100644 --- a/modules/aniviewBidAdapter.js +++ b/modules/aniviewBidAdapter.js @@ -1,7 +1,7 @@ import { VIDEO, BANNER } from '../src/mediaTypes.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { Renderer } from '../src/Renderer.js'; -import { logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'aniview'; const GVLID = 780; @@ -224,7 +224,7 @@ function interpretResponse(serverResponse, bidRequest) { }); bidResponse.vastUrl = window.URL.createObjectURL(blob); } catch (ex) { - logError('Aniview Debug create vastXml error:\n\n' + ex); + utils.logError('Aniview Debug create vastXml error:\n\n' + ex); } bidResponse.vastXml = xmlStr; if (bidRequest.bidRequest && bidRequest.bidRequest.mediaTypes && bidRequest.bidRequest.mediaTypes.video && bidRequest.bidRequest.mediaTypes.video.context === 'outstream') { @@ -309,7 +309,7 @@ function getUserSyncs(syncOptions, serverResponses) { export const spec = { code: BIDDER_CODE, gvlid: GVLID, - aliases: ['avantisvideo', 'selectmediavideo', 'vidcrunch', 'openwebvideo', 'didnavideo', 'ottadvisors'], + aliases: ['avantisvideo', 'selectmediavideo', 'vidcrunch', 'openwebvideo'], supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid, buildRequests, diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index c9f64ab66b0..4ab6f53ebdc 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -1,4 +1,4 @@ -import { isInteger, logError, isEmpty, logWarn, getUniqueIdentifierStr, _each, deepSetValue } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; @@ -38,8 +38,7 @@ const SUPPORTED_USER_ID_SOURCES = [ 'liveintent.com', 'quantcast.com', 'verizonmedia.com', - 'liveramp.com', - 'yahoo.com' + 'liveramp.com' ]; const pubapiTemplate = template`${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'};misc=${'misc'};${'dynamicParams'}`; @@ -65,7 +64,7 @@ function template(strings, ...keys) { let dict = values[values.length - 1] || {}; let result = [strings[0]]; keys.forEach(function (key, i) { - let value = isInteger(key) ? values[key] : dict[key]; + let value = utils.isInteger(key) ? values[key] : dict[key]; result.push(value, strings[i + 1]); }); return result.join(''); @@ -148,7 +147,7 @@ export const spec = { }, interpretResponse({ body }, bidRequest) { if (!body) { - logError('Empty bid response', bidRequest.bidderCode, body); + utils.logError('Empty bid response', bidRequest.bidderCode, body); } else { let bid = this._parseBidResponse(body, bidRequest); @@ -158,7 +157,7 @@ export const spec = { } }, getUserSyncs(options, serverResponses) { - const bidResponse = !isEmpty(serverResponses) && serverResponses[0].body; + const bidResponse = !utils.isEmpty(serverResponses) && serverResponses[0].body; if (bidResponse && bidResponse.ext && bidResponse.ext.pixels) { return this.parsePixelItems(bidResponse.ext.pixels); @@ -216,7 +215,7 @@ export const spec = { let server; if (!MP_SERVER_MAP.hasOwnProperty(regionParam)) { - logWarn(`Unknown region '${regionParam}' for AOL bidder.`); + utils.logWarn(`Unknown region '${regionParam}' for AOL bidder.`); regionParam = 'us'; // Default region. } @@ -235,7 +234,7 @@ export const spec = { placement: parseInt(params.placement), pageid: params.pageId || 0, sizeid: params.sizeId || 0, - alias: params.alias || getUniqueIdentifierStr(), + alias: params.alias || utils.getUniqueIdentifierStr(), misc: new Date().getTime(), // cache busting dynamicParams: this.formatMarketplaceDynamicParams(params, consentData) })); @@ -274,7 +273,7 @@ export const spec = { Object.assign(queryParams, this.formatConsentData(consentData)); let paramsFormatted = ''; - _each(queryParams, (value, key) => { + utils._each(queryParams, (value, key) => { paramsFormatted += `${key}=${encodeURIComponent(value)};`; }); @@ -288,7 +287,7 @@ export const spec = { Object.assign(params, this.formatConsentData(consentData)); let paramsFormatted = ''; - _each(params, (value, key) => { + utils._each(params, (value, key) => { paramsFormatted += `&${key}=${encodeURIComponent(value)}`; }); @@ -301,14 +300,14 @@ export const spec = { }; if (this.isEUConsentRequired(consentData)) { - deepSetValue(openRtbObject, 'regs.ext.gdpr', NUMERIC_VALUES.TRUE); + utils.deepSetValue(openRtbObject, 'regs.ext.gdpr', NUMERIC_VALUES.TRUE); if (consentData.gdpr.consentString) { - deepSetValue(openRtbObject, 'user.ext.consent', consentData.gdpr.consentString); + utils.deepSetValue(openRtbObject, 'user.ext.consent', consentData.gdpr.consentString); } } if (consentData.uspConsent) { - deepSetValue(openRtbObject, 'regs.ext.us_privacy', consentData.uspConsent); + utils.deepSetValue(openRtbObject, 'regs.ext.us_privacy', consentData.uspConsent); } if (typeof bid.userId === 'object') { @@ -329,7 +328,7 @@ export const spec = { formatKeyValues(keyValues) { let keyValuesHash = {}; - _each(keyValues, (value, key) => { + utils._each(keyValues, (value, key) => { keyValuesHash[`kv${key}`] = value; }); @@ -395,7 +394,7 @@ export const spec = { cpm = bidData.price; if (cpm === null || isNaN(cpm)) { - logError('Invalid price in bid response', AOL_BIDDERS_CODES.AOL, bidData); + utils.logError('Invalid price in bid response', AOL_BIDDERS_CODES.AOL, bidData); return; } } diff --git a/modules/apacdexBidAdapter.js b/modules/apacdexBidAdapter.js index d7b6b7c4020..6c1c350b800 100644 --- a/modules/apacdexBidAdapter.js +++ b/modules/apacdexBidAdapter.js @@ -1,10 +1,23 @@ -import { deepAccess, isPlainObject, isArray, replaceAuctionPrice, isFn } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'apacdex'; -const ENDPOINT = 'https://useast.quantumdex.io/auction/pbjs' -const USERSYNC = 'https://sync.quantumdex.io/usersync/pbjs' +const CONFIG = { + 'apacdex': { + 'ENDPOINT': 'https://useast.quantumdex.io/auction/apacdex', + 'USERSYNC': 'https://sync.quantumdex.io/usersync/apacdex' + }, + 'quantumdex': { + 'ENDPOINT': 'https://useast.quantumdex.io/auction/quantumdex', + 'USERSYNC': 'https://sync.quantumdex.io/usersync/quantumdex' + }, + 'valueimpression': { + 'ENDPOINT': 'https://useast.quantumdex.io/auction/adapter', + 'USERSYNC': 'https://sync.quantumdex.io/usersync/adapter' + } +}; +var bidderConfig = CONFIG[BIDDER_CODE]; var bySlotTargetKey = {}; var bySlotSizesCount = {} @@ -19,16 +32,16 @@ export const spec = { if (!bid.params.siteId && !bid.params.placementId) { return false; } - if (!deepAccess(bid, 'mediaTypes.banner') && !deepAccess(bid, 'mediaTypes.video')) { + if (!utils.deepAccess(bid, 'mediaTypes.banner') && !utils.deepAccess(bid, 'mediaTypes.video')) { return false; } - if (deepAccess(bid, 'mediaTypes.banner')) { // Not support multi type bids, favor banner over video - if (!deepAccess(bid, 'mediaTypes.banner.sizes')) { + if (utils.deepAccess(bid, 'mediaTypes.banner')) { // Not support multi type bids, favor banner over video + if (!utils.deepAccess(bid, 'mediaTypes.banner.sizes')) { // sizes at the banner is required. return false; } - } else if (deepAccess(bid, 'mediaTypes.video')) { - if (!deepAccess(bid, 'mediaTypes.video.playerSize')) { + } else if (utils.deepAccess(bid, 'mediaTypes.video')) { + if (!utils.deepAccess(bid, 'mediaTypes.video.playerSize')) { // playerSize is required for instream adUnits. return false; } @@ -43,6 +56,8 @@ export const spec = { let test; let bids = []; + bidderConfig = CONFIG[validBidRequests[0].bidder]; + test = config.getConfig('debug'); validBidRequests.forEach(bidReq => { @@ -141,14 +156,13 @@ export const spec = { transactionId: bid.transactionId, sizes: bid.sizes, bidId: bid.bidId, - adUnitCode: bid.adUnitCode, bidFloor: bid.bidFloor } }); return { method: 'POST', - url: ENDPOINT, + url: bidderConfig.ENDPOINT, data: payload, withCredentials: true, bidderRequests: bids @@ -156,12 +170,12 @@ export const spec = { }, interpretResponse: function (serverResponse, bidRequest) { const serverBody = serverResponse.body; - if (!serverBody || !isPlainObject(serverBody)) { + if (!serverBody || !utils.isPlainObject(serverBody)) { return []; } const serverBids = serverBody.bids; - if (!serverBids || !isArray(serverBids)) { + if (!serverBids || !utils.isArray(serverBids)) { return []; } @@ -183,59 +197,44 @@ export const spec = { bidResponse.dealId = dealId; } if (bid.vastXml) { - bidResponse.vastXml = replaceAuctionPrice(bid.vastXml, bid.cpm); + bidResponse.vastXml = utils.replaceAuctionPrice(bid.vastXml, bid.cpm); } else { - bidResponse.ad = replaceAuctionPrice(bid.ad, bid.cpm); + bidResponse.ad = utils.replaceAuctionPrice(bid.ad, bid.cpm); } bidResponse.meta = {}; - if (bid.meta && bid.meta.advertiserDomains && isArray(bid.meta.advertiserDomains)) { + if (bid.meta && bid.meta.advertiserDomains && utils.isArray(bid.meta.advertiserDomains)) { bidResponse.meta.advertiserDomains = bid.meta.advertiserDomains; } bidResponses.push(bidResponse); }); return bidResponses; }, - getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) { + getUserSyncs: function (syncOptions, serverResponses) { const syncs = []; - if (hasPurpose1Consent(gdprConsent)) { - let params = ''; - if (gdprConsent && typeof gdprConsent.consentString === 'string') { - // add 'gdpr' only if 'gdprApplies' is defined - if (typeof gdprConsent.gdprApplies === 'boolean') { - params = `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - params = `?gdpr_consent=${gdprConsent.consentString}`; - } + try { + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: bidderConfig.USERSYNC + }); } - if (uspConsent) { - params += `${params ? '&' : '?'}us_privacy=${encodeURIComponent(uspConsent)}`; + if (serverResponses.length > 0 && serverResponses[0].body && serverResponses[0].body.pixel) { + serverResponses[0].body.pixel.forEach(px => { + if (px.type === 'image' && syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: px.url + }); + } + if (px.type === 'iframe' && syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: px.url + }); + } + }); } - - try { - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: USERSYNC + params - }); - } - if (serverResponses.length > 0 && serverResponses[0].body && serverResponses[0].body.pixel) { - serverResponses[0].body.pixel.forEach(px => { - if (px.type === 'image' && syncOptions.pixelEnabled) { - syncs.push({ - type: 'image', - url: px.url + params - }); - } - if (px.type === 'iframe' && syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: px.url + params - }); - } - }); - } - } catch (e) { } - } + } catch (e) { } return syncs; } }; @@ -286,7 +285,7 @@ function _extractTopWindowUrlFromBidderRequest(bidderRequest) { if (config.getConfig('pageUrl')) { return config.getConfig('pageUrl'); } - if (deepAccess(bidderRequest, 'refererInfo.referer')) { + if (utils.deepAccess(bidderRequest, 'refererInfo.referer')) { return bidderRequest.refererInfo.referer; } @@ -304,7 +303,7 @@ function _extractTopWindowUrlFromBidderRequest(bidderRequest) { * @returns {string} */ function _extractTopWindowReferrerFromBidderRequest(bidderRequest) { - if (bidderRequest && deepAccess(bidderRequest, 'refererInfo.referer')) { + if (bidderRequest && utils.deepAccess(bidderRequest, 'refererInfo.referer')) { return bidderRequest.refererInfo.referer; } @@ -341,7 +340,7 @@ export function getDomain(pageUrl) { * @returns {boolean} */ export function validateGeoObject(geo) { - if (!isPlainObject(geo)) { + if (!utils.isPlainObject(geo)) { return false; } if (!geo.lat) { @@ -363,7 +362,7 @@ export function validateGeoObject(geo) { * @returns {float||null} */ function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { + if (!utils.isFn(bid.getFloor)) { return (bid.params.floorPrice) ? bid.params.floorPrice : null; } @@ -372,20 +371,10 @@ function getBidFloor(bid) { mediaType: '*', size: '*' }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { + if (utils.isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { return floor.floor; } return null; } -function hasPurpose1Consent(gdprConsent) { - let result = true; - if (gdprConsent) { - if (gdprConsent.gdprApplies && gdprConsent.apiVersion === 2) { - result = !!(deepAccess(gdprConsent, 'vendorData.purpose.consents.1') === true); - } - } - return result; -} - registerBidder(spec); diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 41fad3caba3..72cf0baa3bd 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -1,38 +1,13 @@ -import { - chunk, - convertCamelToUnderscore, - convertTypes, - createTrackPixelHtml, - deepAccess, - deepClone, - fill, - getBidRequest, - getMaxValueFromArray, - getMinValueFromArray, - getParameterByName, - isArray, - isArrayOfNums, - isEmpty, - isFn, - isNumber, - isPlainObject, - isStr, - logError, - logInfo, - logMessage, - logWarn, - transformBidderParamKeywords, - getWindowFromDocument -} from '../src/utils.js'; -import {Renderer} from '../src/Renderer.js'; -import {config} from '../src/config.js'; -import {getIabSubCategory, registerBidder} from '../src/adapters/bidderFactory.js'; -import {ADPOD, BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {auctionManager} from '../src/auctionManager.js'; -import {find, includes} from '../src/polyfill.js'; -import {INSTREAM, OUTSTREAM} from '../src/video.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {bidderSettings} from '../src/bidderSettings.js'; +import { Renderer } from '../src/Renderer.js'; +import * as utils from '../src/utils.js'; +import { config } from '../src/config.js'; +import { registerBidder, getIabSubCategory } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO, ADPOD } from '../src/mediaTypes.js'; +import { auctionManager } from '../src/auctionManager.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import { OUTSTREAM, INSTREAM } from '../src/video.js'; +import { getStorageManager } from '../src/storageManager.js'; const BIDDER_CODE = 'appnexus'; const URL = 'https://ib.adnxs.com/ut/v3/prebid'; @@ -85,7 +60,7 @@ const SCRIPT_TAG_START = ' includes(USER_PARAMS, param)) .forEach((param) => { - let uparam = convertCamelToUnderscore(param); - if (param === 'segments' && isArray(userObjBid.params.user[param])) { + let uparam = utils.convertCamelToUnderscore(param); + if (param === 'segments' && utils.isArray(userObjBid.params.user[param])) { let segs = []; userObjBid.params.user[param].forEach(val => { - if (isNumber(val)) { + if (utils.isNumber(val)) { segs.push({'id': val}); - } else if (isPlainObject(val)) { + } else if (utils.isPlainObject(val)) { segs.push(val); } }); @@ -176,7 +151,7 @@ export const spec = { try { debugObj = JSON.parse(debugCookie); } catch (e) { - logError('AppNexus Debug Auction Cookie Error:\n\n' + e); + utils.logError('AppNexus Debug Auction Cookie Error:\n\n' + e); } } else { const debugBidRequest = find(bidRequests, hasDebug); @@ -226,24 +201,13 @@ export const spec = { payload.app = appIdObj; } - let auctionKeywords = config.getConfig('appnexusAuctionKeywords'); - if (isPlainObject(auctionKeywords)) { - let aucKeywords = transformBidderParamKeywords(auctionKeywords); - - if (aucKeywords.length > 0) { - aucKeywords.forEach(deleteValues); - } - - payload.keywords = aucKeywords; - } - if (config.getConfig('adpod.brandCategoryExclusion')) { payload.brand_category_uniqueness = true; } if (debugObjParams.enabled) { payload.debug = debugObjParams; - logInfo('AppNexus Debug Auction Settings:\n\n' + JSON.stringify(debugObjParams, null, 4)); + utils.logInfo('AppNexus Debug Auction Settings:\n\n' + JSON.stringify(debugObjParams, null, 4)); } if (bidderRequest && bidderRequest.gdprConsent) { @@ -272,10 +236,6 @@ export const spec = { rd_ifs: bidderRequest.refererInfo.numIframes, rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') } - let pubPageUrl = config.getConfig('pageUrl'); - if (isStr(pubPageUrl) && pubPageUrl !== '') { - refererinfo.rd_can = pubPageUrl; - } payload.referrer_detection = refererinfo; } @@ -292,19 +252,12 @@ export const spec = { if (bidRequests[0].userId) { let eids = []; - addUserId(eids, deepAccess(bidRequests[0], `userId.flocId.id`), 'chrome.com', null); - addUserId(eids, deepAccess(bidRequests[0], `userId.criteoId`), 'criteo.com', null); - addUserId(eids, deepAccess(bidRequests[0], `userId.netId`), 'netid.de', null); - addUserId(eids, deepAccess(bidRequests[0], `userId.idl_env`), 'liveramp.com', null); - addUserId(eids, deepAccess(bidRequests[0], `userId.tdid`), 'adserver.org', 'TDID'); - addUserId(eids, deepAccess(bidRequests[0], `userId.uid2.id`), 'uidapi.com', 'UID2'); - if (bidRequests[0].userId.pubProvidedId) { - bidRequests[0].userId.pubProvidedId.forEach(ppId => { - ppId.uids.forEach(uid => { - eids.push({ source: ppId.source, id: uid.id }); - }); - }); - } + addUserId(eids, utils.deepAccess(bidRequests[0], `userId.flocId.id`), 'chrome.com', null); + addUserId(eids, utils.deepAccess(bidRequests[0], `userId.criteoId`), 'criteo.com', null); + addUserId(eids, utils.deepAccess(bidRequests[0], `userId.netId`), 'netid.de', null); + addUserId(eids, utils.deepAccess(bidRequests[0], `userId.idl_env`), 'liveramp.com', null); + addUserId(eids, utils.deepAccess(bidRequests[0], `userId.tdid`), 'adserver.org', 'TDID'); + addUserId(eids, utils.deepAccess(bidRequests[0], `userId.uid2.id`), 'uidapi.com', 'UID2'); if (eids.length) { payload.eids = eids; @@ -331,7 +284,7 @@ export const spec = { if (!serverResponse || serverResponse.error) { let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } - logError(errorMessage); + utils.logError(errorMessage); return bids; } @@ -339,8 +292,7 @@ export const spec = { serverResponse.tags.forEach(serverBid => { const rtbBid = getRtbBid(serverBid); if (rtbBid) { - const cpmCheck = (bidderSettings.get(bidderRequest.bidderCode, 'allowZeroCpmBids') === true) ? rtbBid.cpm >= 0 : rtbBid.cpm > 0; - if (cpmCheck && includes(this.supportedMediaTypes, rtbBid.ad_type)) { + if (rtbBid.cpm !== 0 && includes(this.supportedMediaTypes, rtbBid.ad_type)) { const bid = newBid(serverBid, rtbBid, bidderRequest); bid.mediaType = parseMediaType(rtbBid); bids.push(bid); @@ -360,8 +312,8 @@ export const spec = { .replace(/

(.*)<\/h1>/gm, '\n\n===== $1 =====\n\n') // Header H1 .replace(/(.*)<\/h[2-6]>/gm, '\n\n*** $1 ***\n\n') // Headers .replace(/(<([^>]+)>)/igm, ''); // Remove any other tags - logMessage('https://console.appnexus.com/docs/understanding-the-debug-auction'); - logMessage(debugText); + utils.logMessage('https://console.appnexus.com/docs/understanding-the-debug-auction'); + utils.logMessage(debugText); } return bids; @@ -395,20 +347,11 @@ export const spec = { }, transformBidParams: function (params, isOpenRtb) { - let conversionFn = transformBidderParamKeywords; - if (isOpenRtb === true) { - let s2sConfig = config.getConfig('s2sConfig'); - let s2sEndpointUrl = deepAccess(s2sConfig, 'endpoint.p1Consent'); - if (s2sEndpointUrl && s2sEndpointUrl.match('/openrtb2/prebid')) { - conversionFn = convertKeywordsToString; - } - } - - params = convertTypes({ + params = utils.convertTypes({ 'member': 'string', 'invCode': 'string', 'placementId': 'number', - 'keywords': conversionFn, + 'keywords': utils.transformBidderParamKeywords, 'publisherId': 'number' }, params); @@ -421,7 +364,7 @@ export const spec = { } Object.keys(params).forEach(paramKey => { - let convertedKey = convertCamelToUnderscore(paramKey); + let convertedKey = utils.convertCamelToUnderscore(paramKey); if (convertedKey !== paramKey) { params[convertedKey] = params[paramKey]; delete params[paramKey]; @@ -444,7 +387,7 @@ export const spec = { } function isPopulatedArray(arr) { - return !!(isArray(arr) && arr.length > 0); + return !!(utils.isArray(arr) && arr.length > 0); } function deleteValues(keyPairObj) { @@ -516,9 +459,9 @@ function strIsAppnexusViewabilityScript(str) { function getAppnexusViewabilityScriptFromJsTrackers(jsTrackerArray) { let viewJsPayload; - if (isStr(jsTrackerArray) && strIsAppnexusViewabilityScript(jsTrackerArray)) { + if (utils.isStr(jsTrackerArray) && strIsAppnexusViewabilityScript(jsTrackerArray)) { viewJsPayload = jsTrackerArray; - } else if (isArray(jsTrackerArray)) { + } else if (utils.isArray(jsTrackerArray)) { for (let i = 0; i < jsTrackerArray.length; i++) { let currentJsTracker = jsTrackerArray[i]; if (strIsAppnexusViewabilityScript(currentJsTracker)) { @@ -542,7 +485,7 @@ function hasPurpose1Consent(bidderRequest) { let result = true; if (bidderRequest && bidderRequest.gdprConsent) { if (bidderRequest.gdprConsent.gdprApplies && bidderRequest.gdprConsent.apiVersion === 2) { - result = !!(deepAccess(bidderRequest.gdprConsent, 'vendorData.purpose.consents.1') === true); + result = !!(utils.deepAccess(bidderRequest.gdprConsent, 'vendorData.purpose.consents.1') === true); } } return result; @@ -560,16 +503,16 @@ function formatRequest(payload, bidderRequest) { endpointUrl = URL_SIMPLE; } - if (getParameterByName('apn_test').toUpperCase() === 'TRUE' || config.getConfig('apn_test') === true) { + if (utils.getParameterByName('apn_test').toUpperCase() === 'TRUE' || config.getConfig('apn_test') === true) { options.customHeaders = { 'X-Is-Test': 1 } } if (payload.tags.length > MAX_IMPS_PER_REQUEST) { - const clonedPayload = deepClone(payload); + const clonedPayload = utils.deepClone(payload); - chunk(payload.tags, MAX_IMPS_PER_REQUEST).forEach(tags => { + utils.chunk(payload.tags, MAX_IMPS_PER_REQUEST).forEach(tags => { clonedPayload.tags = tags; const payloadString = JSON.stringify(clonedPayload); request.push({ @@ -606,14 +549,14 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { try { renderer.setRender(outstreamRender); } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); + utils.logWarn('Prebid Error calling setRender on renderer', err); } renderer.setEventHandlers({ - impression: () => logMessage('AppNexus outstream video impression event'), - loaded: () => logMessage('AppNexus outstream video loaded event'), + impression: () => utils.logMessage('AppNexus outstream video impression event'), + loaded: () => utils.logMessage('AppNexus outstream video loaded event'), ended: () => { - logMessage('AppNexus outstream renderer video event'); + utils.logMessage('AppNexus outstream renderer video event'); document.querySelector(`#${adUnitCode}`).style.display = 'none'; } }); @@ -628,7 +571,7 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { * @return Bid */ function newBid(serverBid, rtbBid, bidderRequest) { - const bidRequest = getBidRequest(serverBid.uuid, [bidderRequest]); + const bidRequest = utils.getBidRequest(serverBid.uuid, [bidderRequest]); const bid = { requestId: serverBid.uuid, cpm: rtbBid.cpm, @@ -654,26 +597,6 @@ function newBid(serverBid, rtbBid, bidderRequest) { bid.meta = Object.assign({}, bid.meta, { advertiserId: rtbBid.advertiser_id }); } - // temporary function; may remove at later date if/when adserver fully supports dchain - function setupDChain(rtbBid) { - let dchain = { - ver: '1.0', - complete: 0, - nodes: [{ - bsid: rtbBid.buyer_member_id.toString() - }], - }; - - return dchain; - } - if (rtbBid.buyer_member_id) { - bid.meta = Object.assign({}, bid.meta, {dchain: setupDChain(rtbBid)}); - } - - if (rtbBid.brand_id) { - bid.meta = Object.assign({}, bid.meta, { brandId: rtbBid.brand_id }); - } - if (rtbBid.rtb.video) { // shared video properties used for all 3 contexts Object.assign(bid, { @@ -683,7 +606,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { ttl: 3600 }); - const videoContext = deepAccess(bidRequest, 'mediaTypes.video.context'); + const videoContext = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); switch (videoContext) { case ADPOD: const primaryCatId = getIabSubCategory(bidRequest.bidder, rtbBid.brand_category_id); @@ -704,10 +627,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { if (rtbBid.renderer_url) { const videoBid = find(bidderRequest.bids, bid => bid.bidId === serverBid.uuid); - let rendererOptions = deepAccess(videoBid, 'mediaTypes.video.renderer.options'); // mediaType definition has preference (shouldn't options be .config?) - if (!rendererOptions) { - rendererOptions = deepAccess(videoBid, 'renderer.options'); // second the adUnit definition has preference (shouldn't options be .config?) - } + const rendererOptions = utils.deepAccess(videoBid, 'renderer.options'); bid.renderer = newRenderer(bid.adUnitCode, rtbBid, rendererOptions); } break; @@ -727,7 +647,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { if (jsTrackers == undefined) { jsTrackers = jsTrackerDisarmed; - } else if (isStr(jsTrackers)) { + } else if (utils.isStr(jsTrackers)) { jsTrackers = [jsTrackers, jsTrackerDisarmed]; } else { jsTrackers.push(jsTrackerDisarmed); @@ -775,14 +695,12 @@ function newBid(serverBid, rtbBid, bidderRequest) { }); try { if (rtbBid.rtb.trackers) { - for (let i = 0; i < rtbBid.rtb.trackers[0].impression_urls.length; i++) { - const url = rtbBid.rtb.trackers[0].impression_urls[i]; - const tracker = createTrackPixelHtml(url); - bid.ad += tracker; - } + const url = rtbBid.rtb.trackers[0].impression_urls[0]; + const tracker = utils.createTrackPixelHtml(url); + bid.ad += tracker; } } catch (error) { - logError('Error appending tracking pixel', error); + utils.logError('Error appending tracking pixel', error); } } @@ -810,13 +728,6 @@ function bidToTag(bid) { } if (bid.params.position) { tag.position = { 'above': 1, 'below': 2 }[bid.params.position] || 0; - } else { - let mediaTypePos = deepAccess(bid, `mediaTypes.banner.pos`) || deepAccess(bid, `mediaTypes.video.pos`); - // only support unknown, atf, and btf values for position at this time - if (mediaTypePos === 0 || mediaTypePos === 1 || mediaTypePos === 3) { - // ortb spec treats btf === 3, but our system interprets btf === 2; so converting the ortb value here for consistency - tag.position = (mediaTypePos === 3) ? 2 : mediaTypePos; - } } if (bid.params.trafficSourceCode) { tag.traffic_source_code = bid.params.trafficSourceCode; @@ -839,8 +750,8 @@ function bidToTag(bid) { if (bid.params.externalImpId) { tag.external_imp_id = bid.params.externalImpId; } - if (!isEmpty(bid.params.keywords)) { - let keywords = transformBidderParamKeywords(bid.params.keywords); + if (!utils.isEmpty(bid.params.keywords)) { + let keywords = utils.transformBidderParamKeywords(bid.params.keywords); if (keywords.length > 0) { keywords.forEach(deleteValues); @@ -848,12 +759,12 @@ function bidToTag(bid) { tag.keywords = keywords; } - let gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); + let gpid = utils.deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); if (gpid) { tag.gpid = gpid; } - if (bid.mediaType === NATIVE || deepAccess(bid, `mediaTypes.${NATIVE}`)) { + if (bid.mediaType === NATIVE || utils.deepAccess(bid, `mediaTypes.${NATIVE}`)) { tag.ad_types.push(NATIVE); if (tag.sizes.length === 0) { tag.sizes = transformSizes([1, 1]); @@ -865,8 +776,8 @@ function bidToTag(bid) { } } - const videoMediaType = deepAccess(bid, `mediaTypes.${VIDEO}`); - const context = deepAccess(bid, 'mediaTypes.video.context'); + const videoMediaType = utils.deepAccess(bid, `mediaTypes.${VIDEO}`); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); if (videoMediaType && context === 'adpod') { tag.hb_source = 7; @@ -892,7 +803,7 @@ function bidToTag(bid) { case 'context': case 'playback_method': let type = bid.params.video[param]; - type = (isArray(type)) ? type[0] : type; + type = (utils.isArray(type)) ? type[0] : type; tag.video[param] = VIDEO_MAPPING[param][type]; break; // Deprecating tags[].video.frameworks in favor of tags[].video_frameworks @@ -903,7 +814,7 @@ function bidToTag(bid) { } }); - if (bid.params.video.frameworks && isArray(bid.params.video.frameworks)) { + if (bid.params.video.frameworks && utils.isArray(bid.params.video.frameworks)) { tag['video_frameworks'] = bid.params.video.frameworks; } } @@ -928,7 +839,7 @@ function bidToTag(bid) { case 'playbackmethod': if (typeof tag.video['playback_method'] !== 'number') { let type = videoMediaType[param]; - type = (isArray(type)) ? type[0] : type; + type = (utils.isArray(type)) ? type[0] : type; // we only support iab's options 1-4 at this time. if (type >= 1 && type <= 4) { @@ -937,7 +848,7 @@ function bidToTag(bid) { } break; case 'api': - if (!tag['video_frameworks'] && isArray(videoMediaType[param])) { + if (!tag['video_frameworks'] && utils.isArray(videoMediaType[param])) { // need to read thru array; remove 6 (we don't support it), swap 4 <> 5 if found (to match our adserver mapping for these specific values) let apiTmp = videoMediaType[param].map(val => { let v = (val === 4) ? 5 : (val === 5) ? 4 : val; @@ -957,7 +868,7 @@ function bidToTag(bid) { tag.video = Object.assign({}, tag.video, { custom_renderer_present: true }); } - if (bid.params.frameworks && isArray(bid.params.frameworks)) { + if (bid.params.frameworks && utils.isArray(bid.params.frameworks)) { tag['banner_frameworks'] = bid.params.frameworks; } @@ -978,8 +889,8 @@ function transformSizes(requestSizes) { let sizes = []; let sizeObj = {}; - if (isArray(requestSizes) && requestSizes.length === 2 && - !isArray(requestSizes[0])) { + if (utils.isArray(requestSizes) && requestSizes.length === 2 && + !utils.isArray(requestSizes[0])) { sizeObj.width = parseInt(requestSizes[0], 10); sizeObj.height = parseInt(requestSizes[1], 10); sizes.push(sizeObj); @@ -1033,10 +944,10 @@ function hasOmidSupport(bid) { let hasOmid = false; const bidderParams = bid.params; const videoParams = bid.params.video; - if (bidderParams.frameworks && isArray(bidderParams.frameworks)) { + if (bidderParams.frameworks && utils.isArray(bidderParams.frameworks)) { hasOmid = includes(bid.params.frameworks, 6); } - if (!hasOmid && videoParams && videoParams.frameworks && isArray(videoParams.frameworks)) { + if (!hasOmid && videoParams && videoParams.frameworks && utils.isArray(videoParams.frameworks)) { hasOmid = includes(bid.params.video.frameworks, 6); } return hasOmid; @@ -1051,14 +962,14 @@ function createAdPodRequest(tags, adPodBid) { const { durationRangeSec, requireExactDuration } = adPodBid.mediaTypes.video; const numberOfPlacements = getAdPodPlacementNumber(adPodBid.mediaTypes.video); - const maxDuration = getMaxValueFromArray(durationRangeSec); + const maxDuration = utils.getMaxValueFromArray(durationRangeSec); const tagToDuplicate = tags.filter(tag => tag.uuid === adPodBid.bidId); - let request = fill(...tagToDuplicate, numberOfPlacements); + let request = utils.fill(...tagToDuplicate, numberOfPlacements); if (requireExactDuration) { const divider = Math.ceil(numberOfPlacements / durationRangeSec.length); - const chunked = chunk(request, divider); + const chunked = utils.chunk(request, divider); // each configured duration is set as min/maxduration for a subset of requests durationRangeSec.forEach((duration, index) => { @@ -1077,7 +988,7 @@ function createAdPodRequest(tags, adPodBid) { function getAdPodPlacementNumber(videoParams) { const { adPodDurationSec, durationRangeSec, requireExactDuration } = videoParams; - const minAllowedDuration = getMinValueFromArray(durationRangeSec); + const minAllowedDuration = utils.getMinValueFromArray(durationRangeSec); const numberOfPlacements = Math.floor(adPodDurationSec / minAllowedDuration); return requireExactDuration @@ -1086,7 +997,7 @@ function getAdPodPlacementNumber(videoParams) { } function setVideoProperty(tag, key, value) { - if (isEmpty(tag.video)) { tag.video = {}; } + if (utils.isEmpty(tag.video)) { tag.video = {}; } tag.video[key] = value; } @@ -1117,7 +1028,7 @@ function buildNativeRequest(params) { const isImageAsset = !!(requestKey === NATIVE_MAPPING.image.serverName || requestKey === NATIVE_MAPPING.icon.serverName); if (isImageAsset && request[requestKey].sizes) { let sizes = request[requestKey].sizes; - if (isArrayOfNums(sizes) || (isArray(sizes) && sizes.length > 0 && sizes.every(sz => isArrayOfNums(sz)))) { + if (utils.isArrayOfNums(sizes) || (utils.isArray(sizes) && sizes.length > 0 && sizes.every(sz => utils.isArrayOfNums(sz)))) { request[requestKey].sizes = transformSizes(request[requestKey].sizes); } } @@ -1135,13 +1046,9 @@ function buildNativeRequest(params) { * @param {string} elementId element id */ function hidedfpContainer(elementId) { - try { - const el = document.getElementById(elementId).querySelectorAll("div[id^='google_ads']"); - if (el[0]) { - el[0].style.setProperty('display', 'none'); - } - } catch (e) { - // element not found! + var el = document.getElementById(elementId).querySelectorAll("div[id^='google_ads']"); + if (el[0]) { + el[0].style.setProperty('display', 'none'); } } @@ -1157,13 +1064,12 @@ function hideSASIframe(elementId) { } } -function outstreamRender(bid, doc) { +function outstreamRender(bid) { hidedfpContainer(bid.adUnitCode); hideSASIframe(bid.adUnitCode); // push to render queue because ANOutstreamVideo may not be loaded yet bid.renderer.push(() => { - const win = getWindowFromDocument(doc) || window; - win.ANOutstreamVideo.renderAd({ + window.ANOutstreamVideo.renderAd({ tagId: bid.adResponse.tag_id, sizes: [bid.getSize().split('x')], targetId: bid.adUnitCode, // target div id to render video @@ -1201,7 +1107,7 @@ function addUserId(eids, id, source, rti) { } function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { + if (!utils.isFn(bid.getFloor)) { return (bid.params.reserve) ? bid.params.reserve : null; } @@ -1210,37 +1116,10 @@ function getBidFloor(bid) { mediaType: '*', size: '*' }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { + if (utils.isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { return floor.floor; } return null; } -// keywords: { 'genre': ['rock', 'pop'], 'pets': ['dog'] } goes to 'genre=rock,genre=pop,pets=dog' -function convertKeywordsToString(keywords) { - let result = ''; - Object.keys(keywords).forEach(key => { - // if 'text' or '' - if (isStr(keywords[key])) { - if (keywords[key] !== '') { - result += `${key}=${keywords[key]},` - } else { - result += `${key},`; - } - } else if (isArray(keywords[key])) { - if (keywords[key][0] === '') { - result += `${key},` - } else { - keywords[key].forEach(val => { - result += `${key}=${val},` - }); - } - } - }); - - // remove last trailing comma - result = result.substring(0, result.length - 1); - return result; -} - registerBidder(spec); diff --git a/modules/apstreamBidAdapter.js b/modules/apstreamBidAdapter.js index b69fffb8b6b..4fb89b9c720 100644 --- a/modules/apstreamBidAdapter.js +++ b/modules/apstreamBidAdapter.js @@ -1,6 +1,6 @@ -import { generateUUID, deepAccess, createTrackPixelHtml, getDNT } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; +import * as utils from '../src/utils.js'; import { getStorageManager } from '../src/storageManager.js'; const CONSTANTS = { @@ -8,7 +8,7 @@ const CONSTANTS = { BIDDER_CODE: 'apstream', GVLID: 394 }; -const storage = getStorageManager({gvlid: CONSTANTS.GVLID, bidderCode: CONSTANTS.BIDDER_CODE}); +const storage = getStorageManager(CONSTANTS.GVLID, CONSTANTS.BIDDER_CODE); var dsuModule = (function() { 'use strict'; @@ -221,7 +221,7 @@ var dsuModule = (function() { } function generateDsu() { - var dsuId = generateUUID(); + var dsuId = utils.generateUUID(); var loc = location(); var dsuIdSuffix = hashWithKey(dsuId + loc.toString()); @@ -303,7 +303,7 @@ function getConsentStringFromPrebid(gdprConsentConfig) { } function getIabConsentString(bidderRequest) { - if (deepAccess(bidderRequest, 'gdprConsent')) { + if (utils.deepAccess(bidderRequest, 'gdprConsent')) { return getConsentStringFromPrebid(bidderRequest.gdprConsent); } @@ -318,7 +318,7 @@ function injectPixels(ad, pixels, scripts) { let trackedAd = ad; if (pixels) { pixels.forEach(pixel => { - const tracker = createTrackPixelHtml(pixel); + const tracker = utils.createTrackPixelHtml(pixel); trackedAd += tracker; }); } @@ -420,7 +420,7 @@ function buildRequests(bidRequests, bidderRequest) { med: encodeURIComponent(window.location.href), auid: bidderRequest.auctionId, ref: document.referrer, - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, sr: getScreenParams() }; diff --git a/modules/asealBidAdapter.js b/modules/asealBidAdapter.js deleted file mode 100644 index 855aee65f34..00000000000 --- a/modules/asealBidAdapter.js +++ /dev/null @@ -1,106 +0,0 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; -import { generateUUID, getWindowTop, getWindowSelf } from '../src/utils.js'; -import { getStorageManager } from '../src/storageManager.js'; - -export const BIDDER_CODE = 'aseal'; -export const SUPPORTED_AD_TYPES = [BANNER]; -export const API_ENDPOINT = 'https://tkprebid.aotter.net/prebid/adapter'; -export const WEB_SESSION_ID_KEY = '__tkwsid'; -export const HEADER_AOTTER_VERSION = 'prebid_0.0.2'; - -export const storage = getStorageManager({ bidderCode: BIDDER_CODE }); - -const getTrekWebSessionId = () => { - let wsid = - storage.localStorageIsEnabled() && - storage.getDataFromLocalStorage(WEB_SESSION_ID_KEY); - - if (!wsid) { - wsid = generateUUID(); - setTrekWebSessionId(wsid); - } - - return wsid; -}; - -const setTrekWebSessionId = (wsid) => { - if (storage.localStorageIsEnabled()) { - storage.setDataInLocalStorage(WEB_SESSION_ID_KEY, wsid); - } -}; - -const canAccessTopWindow = () => { - try { - return !!getWindowTop().location.href; - } catch (errro) { - return false; - } -}; - -export const spec = { - code: BIDDER_CODE, - aliases: ['aotter', 'trek'], - supportedMediaTypes: SUPPORTED_AD_TYPES, - isBidRequestValid: (bid) => - !!bid.params.placeUid && typeof bid.params.placeUid === 'string', - buildRequests: (validBidRequests, bidderRequest) => { - if (validBidRequests.length === 0) { - return []; - } - - const clientId = config.getConfig('aseal.clientId') || ''; - - const windowTop = getWindowTop(); - const windowSelf = getWindowSelf(); - - const w = canAccessTopWindow() ? windowTop : windowSelf; - - const data = { - bids: validBidRequests, - refererInfo: bidderRequest.refererInfo, - device: { - webSessionId: getTrekWebSessionId(), - }, - payload: { - meta: { - dr: w.document.referrer, - drs: windowSelf.document.referrer, - drt: (canAccessTopWindow() && windowTop.document.referrer) || '', - dt: w.document.title, - dl: w.location.href, - }, - }, - }; - - const options = { - contentType: 'application/json', - withCredentials: true, - customHeaders: { - 'x-aotter-clientid': clientId, - 'x-aotter-version': HEADER_AOTTER_VERSION, - }, - }; - - return [ - { - method: 'POST', - url: API_ENDPOINT, - data, - options, - }, - ]; - }, - interpretResponse: (serverResponse, bidRequest) => { - if (!Array.isArray(serverResponse.body)) { - return []; - } - - const bidResponses = serverResponse.body; - - return bidResponses; - }, -}; - -registerBidder(spec); diff --git a/modules/asealBidAdapter.md b/modules/asealBidAdapter.md deleted file mode 100644 index d13b802f736..00000000000 --- a/modules/asealBidAdapter.md +++ /dev/null @@ -1,52 +0,0 @@ -# Overview - -``` -Module Name: Aseal Bid Adapter -Module Type: Bidder Adapter -Maintainer: tech-service@aotter.net -``` - -# Description - -Module that connects to Aseal server for bids. -Supported Ad Formats: - -- Banner - -# Configuration - -Following configuration is required: - -```js -pbjs.setConfig({ - aseal: { - clientId: "YOUR_CLIENT_ID" - } -}); -``` - -# Ad Unit Example - -```js -var adUnits = [ - { - code: "banner-div", - mediaTypes: { - banner: { - sizes: [ - [300, 250], - [300, 600] - ] - } - }, - bids: [ - { - bidder: "aseal", - params: { - placeUid: "f4a74f73-9a74-4a87-91c9-545c6316c23d" - } - } - ] - } -]; -``` diff --git a/modules/asoBidAdapter.js b/modules/asoBidAdapter.js index bf45b9ee48f..8f06b8ed856 100644 --- a/modules/asoBidAdapter.js +++ b/modules/asoBidAdapter.js @@ -1,5 +1,5 @@ -import { _each, deepAccess, logWarn, tryAppendQueryString, inIframe, getWindowTop, parseUrl, parseSizesInput, isFn, getDNT, deepSetValue } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {Renderer} from '../src/Renderer.js'; @@ -22,16 +22,16 @@ export const spec = { buildRequests: (validBidRequests, bidderRequest) => { let serverRequests = []; - _each(validBidRequests, bidRequest => { + utils._each(validBidRequests, bidRequest => { const payload = createBasePayload(bidRequest, bidderRequest); - const bannerParams = deepAccess(bidRequest, 'mediaTypes.banner'); - const videoParams = deepAccess(bidRequest, 'mediaTypes.video'); + const bannerParams = utils.deepAccess(bidRequest, 'mediaTypes.banner'); + const videoParams = utils.deepAccess(bidRequest, 'mediaTypes.video'); let imp; if (bannerParams && videoParams) { - logWarn('Please note, multiple mediaTypes are not supported. The only banner will be used.') + utils.logWarn('Please note, multiple mediaTypes are not supported. The only banner will be used.') } if (bannerParams) { @@ -93,7 +93,7 @@ export const spec = { bid.ad = serverBid.adm; } else if (bid.mediaType === VIDEO) { bid.vastXml = serverBid.adm; - if (deepAccess(bidRequest, 'mediaTypes.video.context') === 'outstream') { + if (utils.deepAccess(bidRequest, 'mediaTypes.video.context') === 'outstream') { bid.adResponse = { content: bid.vastXml, }; @@ -112,25 +112,25 @@ export const spec = { if (serverResponses && serverResponses.length !== 0) { let query = ''; if (gdprConsent) { - query = tryAppendQueryString(query, 'gdpr', (gdprConsent.gdprApplies ? 1 : 0)); - query = tryAppendQueryString(query, 'consents_str', gdprConsent.consentString); + query = utils.tryAppendQueryString(query, 'gdpr', (gdprConsent.gdprApplies ? 1 : 0)); + query = utils.tryAppendQueryString(query, 'consents_str', gdprConsent.consentString); const consentsIds = getConsentsIds(gdprConsent); if (consentsIds) { - query = tryAppendQueryString(query, 'consents', consentsIds); + query = utils.tryAppendQueryString(query, 'consents', consentsIds); } } if (uspConsent) { - query = tryAppendQueryString(query, 'us_privacy', uspConsent); + query = utils.tryAppendQueryString(query, 'us_privacy', uspConsent); } - _each(serverResponses, resp => { - const userSyncs = deepAccess(resp, 'body.ext.user_syncs'); + utils._each(serverResponses, resp => { + const userSyncs = utils.deepAccess(resp, 'body.ext.user_syncs'); if (!userSyncs) { return; } - _each(userSyncs, us => { + utils._each(userSyncs, us => { urls.push({ type: us.type, url: us.url + (query ? '?' + query : '') @@ -159,7 +159,7 @@ function createRenderer(bid, url) { id: bid.bidId, url: url, loaded: false, - config: deepAccess(bid, 'renderer.options'), + config: utils.deepAccess(bid, 'renderer.options'), adUnitCode: bid.adUnitCode }); renderer.setRender(outstreamRender); @@ -172,16 +172,16 @@ function getUrlsInfo(bidderRequest) { const {refererInfo} = bidderRequest; - if (inIframe()) { + if (utils.inIframe()) { page = refererInfo.referer; } else { - const w = getWindowTop(); + const w = utils.getWindowTop(); page = w.location.href; referrer = w.document.referrer || ''; } page = config.getConfig('pageUrl') || page; - const url = parseUrl(page); + const url = utils.parseUrl(page); const domain = url.hostname; return { @@ -192,7 +192,7 @@ function getUrlsInfo(bidderRequest) { } function getSize(paramSizes) { - const parsedSizes = parseSizesInput(paramSizes); + const parsedSizes = utils.parseSizesInput(paramSizes); const sizes = parsedSizes.map(size => { const [width, height] = size.split('x'); const w = parseInt(width, 10); @@ -204,7 +204,7 @@ function getSize(paramSizes) { } function getBidFloor(bidRequest, size) { - if (!isFn(bidRequest.getFloor)) { + if (!utils.isFn(bidRequest.getFloor)) { return null; } @@ -245,7 +245,7 @@ function createBannerImp(bidRequest, bannerParams) { imp.banner = { w: size.w, h: size.h, - topframe: inIframe() ? 0 : 1 + topframe: utils.inIframe() ? 0 : 1 } return imp; @@ -284,7 +284,7 @@ function getEnpoint(bidRequest) { } function getConsentsIds(gdprConsent) { - const consents = deepAccess(gdprConsent, 'vendorData.purpose.consents', []); + const consents = utils.deepAccess(gdprConsent, 'vendorData.purpose.consents', []); let consentsIds = []; Object.keys(consents).forEach(function (key) { @@ -310,7 +310,7 @@ function createBasePayload(bidRequest, bidderRequest) { ref: urlsInfo.referrer }, device: { - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, h: window.innerHeight, w: window.innerWidth, }, @@ -320,29 +320,29 @@ function createBasePayload(bidRequest, bidderRequest) { }; if (bidRequest.params.attr) { - deepSetValue(payload, 'site.ext.attr', bidRequest.params.attr); + utils.deepSetValue(payload, 'site.ext.attr', bidRequest.params.attr); } if (bidderRequest.gdprConsent) { - deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); const consentsIds = getConsentsIds(bidderRequest.gdprConsent); if (consentsIds) { - deepSetValue(payload, 'user.ext.consents', consentsIds); + utils.deepSetValue(payload, 'user.ext.consents', consentsIds); } - deepSetValue(payload, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies & 1); + utils.deepSetValue(payload, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies & 1); } if (bidderRequest.uspConsent) { - deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); } if (config.getConfig('coppa')) { - deepSetValue(payload, 'regs.coppa', 1); + utils.deepSetValue(payload, 'regs.coppa', 1); } - const eids = deepAccess(bidRequest, 'userIdAsEids'); + const eids = utils.deepAccess(bidRequest, 'userIdAsEids'); if (eids && eids.length) { - deepSetValue(payload, 'user.ext.eids', eids); + utils.deepSetValue(payload, 'user.ext.eids', eids); } return payload; diff --git a/modules/astraoneBidAdapter.js b/modules/astraoneBidAdapter.js index c233e665499..2fec3892d27 100644 --- a/modules/astraoneBidAdapter.js +++ b/modules/astraoneBidAdapter.js @@ -1,4 +1,4 @@ -import { _map } from '../src/utils.js'; +import * as utils from '../src/utils.js' import { registerBidder } from '../src/adapters/bidderFactory.js' import { BANNER } from '../src/mediaTypes.js' @@ -7,7 +7,7 @@ const SSP_ENDPOINT = 'https://ssp.astraone.io/auction/prebid'; const TTL = 60; function buildBidRequests(validBidRequests) { - return _map(validBidRequests, function(validBidRequest) { + return utils._map(validBidRequests, function(validBidRequest) { const params = validBidRequest.params; const bidRequest = { bidId: validBidRequest.bidId, diff --git a/modules/atsAnalyticsAdapter.js b/modules/atsAnalyticsAdapter.js index f45d2e80055..0cff7bbd68f 100644 --- a/modules/atsAnalyticsAdapter.js +++ b/modules/atsAnalyticsAdapter.js @@ -1,7 +1,7 @@ -import { logError, logInfo } from '../src/utils.js'; import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adaptermanager from '../src/adapterManager.js'; +import * as utils from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import {getStorageManager} from '../src/storageManager.js'; @@ -13,6 +13,9 @@ export const storage = getStorageManager(); */ const analyticsType = 'endpoint'; +// dev endpoints +// const preflightUrl = 'https://analytics-check.publishersite.xyz/check/'; +// export const analyticsUrl = 'https://analyticsv2.publishersite.xyz'; const preflightUrl = 'https://check.analytics.rlcdn.com/check/'; export const analyticsUrl = 'https://analytics.rlcdn.com'; @@ -20,7 +23,7 @@ export const analyticsUrl = 'https://analytics.rlcdn.com'; let handlerRequest = []; let handlerResponse = []; -let atsAnalyticsAdapterVersion = 3; +let atsAnalyticsAdapterVersion = 1; let browsersList = [ /* Googlebot */ @@ -204,6 +207,12 @@ let browsersList = [ }, ]; +function setSamplingCookie(samplRate) { + let now = new Date(); + now.setTime(now.getTime() + 3600000); + storage.setCookie('_lr_sampling_rate', samplRate, now.toUTCString()); +} + let listOfSupportedBrowsers = ['Safari', 'Chrome', 'Firefox', 'Microsoft Edge']; function bidRequestedHandler(args) { @@ -222,8 +231,7 @@ function bidRequestedHandler(args) { auction_start: new Date(args.auctionStart).toJSON(), domain: window.location.hostname, pid: atsAnalyticsAdapter.context.pid, - adapter_version: atsAnalyticsAdapterVersion, - bid_won: false + adapter_version: atsAnalyticsAdapterVersion }; }); return requests; @@ -248,45 +256,59 @@ export function parseBrowser() { let browserName = result && result.length ? result[0].name : ''; return (listOfSupportedBrowsers.indexOf(browserName) >= 0) ? browserName : 'Unknown'; } catch (err) { - logError('ATS Analytics - Error while checking user browser!', err); + utils.logError('ATS Analytics - Error while checking user browser!', err); } } -function sendDataToAnalytic (events) { +function sendDataToAnalytic () { // send data to ats analytic endpoint try { - let dataToSend = {'Data': events}; + let dataToSend = {'Data': atsAnalyticsAdapter.context.events}; let strJSON = JSON.stringify(dataToSend); - logInfo('ATS Analytics - tried to send analytics data!'); + utils.logInfo('ATS Analytics - tried to send analytics data!'); ajax(analyticsUrl, function () { - logInfo('ATS Analytics - events sent successfully!'); }, strJSON, {method: 'POST', contentType: 'application/json'}); } catch (err) { - logError('ATS Analytics - request encounter an error: ', err); + utils.logError('ATS Analytics - request encounter an error: ', err); } } // preflight request, to check did publisher have permission to send data to analytics endpoint -function preflightRequest (envelopeSourceCookieValue, events) { - logInfo('ATS Analytics - preflight request!'); - ajax(preflightUrl + atsAnalyticsAdapter.context.pid, - { - success: function (data) { - let samplingRateObject = JSON.parse(data); - logInfo('ATS Analytics - Sampling Rate: ', samplingRateObject); - let samplingRate = samplingRateObject.samplingRate; - atsAnalyticsAdapter.setSamplingCookie(samplingRate); - let samplingRateNumber = Number(samplingRate); - if (data && samplingRate && atsAnalyticsAdapter.shouldFireRequest(samplingRateNumber) && envelopeSourceCookieValue != null) { - logInfo('ATS Analytics - events to send: ', events); - sendDataToAnalytic(events); - } - }, - error: function () { - atsAnalyticsAdapter.setSamplingCookie(0); - logInfo('ATS Analytics - Sampling Rate Request Error!'); +function preflightRequest (envelopeSourceCookieValue) { + utils.logInfo('ATS Analytics - preflight request!'); + ajax(preflightUrl + atsAnalyticsAdapter.context.pid, function (data) { + let samplingRateObject = JSON.parse(data); + utils.logInfo('ATS Analytics - Sampling Rate: ', samplingRateObject); + let samplingRate = samplingRateObject['samplingRate']; + setSamplingCookie(samplingRate); + let samplingRateNumber = Number(samplingRate); + if (data && samplingRate && atsAnalyticsAdapter.shouldFireRequest(samplingRateNumber) && envelopeSourceCookieValue != null) { + sendDataToAnalytic(); + } + }, undefined, { method: 'GET', crossOrigin: true }); +} + +function callHandler(evtype, args) { + if (evtype === CONSTANTS.EVENTS.BID_REQUESTED) { + handlerRequest = handlerRequest.concat(bidRequestedHandler(args)); + } else if (evtype === CONSTANTS.EVENTS.BID_RESPONSE) { + handlerResponse.push(bidResponseHandler(args)); + } + if (evtype === CONSTANTS.EVENTS.AUCTION_END) { + if (handlerRequest.length) { + let events = []; + if (handlerResponse.length) { + events = handlerRequest.filter(request => handlerResponse.filter(function(response) { + if (request.bid_id === response.bid_id) { + Object.assign(request, response); + } + })); + } else { + events = handlerRequest; } - }, undefined, {method: 'GET', crossOrigin: true}); + atsAnalyticsAdapter.context.events = events; + } + } } let atsAnalyticsAdapter = Object.assign(adapter( @@ -296,7 +318,22 @@ let atsAnalyticsAdapter = Object.assign(adapter( { track({eventType, args}) { if (typeof args !== 'undefined') { - atsAnalyticsAdapter.callHandler(eventType, args); + callHandler(eventType, args); + } + if (eventType === CONSTANTS.EVENTS.AUCTION_END) { + let envelopeSourceCookieValue = storage.getCookie('_lr_env_src_ats'); + try { + let samplingRateCookie = storage.getCookie('_lr_sampling_rate'); + if (!samplingRateCookie) { + preflightRequest(envelopeSourceCookieValue); + } else { + if (atsAnalyticsAdapter.shouldFireRequest(parseInt(samplingRateCookie)) && envelopeSourceCookieValue != null) { + sendDataToAnalytic(); + } + } + } catch (err) { + utils.logError('ATS Analytics - preflight request encounter an error: ', err); + } } } }); @@ -308,10 +345,10 @@ atsAnalyticsAdapter.originEnableAnalytics = atsAnalyticsAdapter.enableAnalytics; atsAnalyticsAdapter.shouldFireRequest = function (samplingRate) { if (samplingRate !== 0) { let shouldFireRequestValue = (Math.floor((Math.random() * 100 + 1)) === 100); - logInfo('ATS Analytics - Should Fire Request: ', shouldFireRequestValue); + utils.logInfo('ATS Analytics - Should Fire Request: ', shouldFireRequestValue); return shouldFireRequestValue; } else { - logInfo('ATS Analytics - Should Fire Request: ', false); + utils.logInfo('ATS Analytics - Should Fire Request: ', false); return false; } }; @@ -319,84 +356,21 @@ atsAnalyticsAdapter.shouldFireRequest = function (samplingRate) { atsAnalyticsAdapter.getUserAgent = function () { return window.navigator.userAgent; }; - -atsAnalyticsAdapter.setSamplingCookie = function (samplRate) { - const now = new Date(); - now.setTime(now.getTime() + 86400000); - storage.setCookie('_lr_sampling_rate', samplRate, now.toUTCString()); -} - // override enableAnalytics so we can get access to the config passed in from the page atsAnalyticsAdapter.enableAnalytics = function (config) { if (!config.options.pid) { - logError('ATS Analytics - Publisher ID (pid) option is not defined. Analytics won\'t work'); + utils.logError('ATS Analytics - Publisher ID (pid) option is not defined. Analytics won\'t work'); return; } atsAnalyticsAdapter.context = { events: [], - pid: config.options.pid, - bidWonTimeout: config.options.bidWonTimeout + pid: config.options.pid }; let initOptions = config.options; - logInfo('ATS Analytics - adapter enabled! '); + utils.logInfo('ATS Analytics - adapter enabled! '); atsAnalyticsAdapter.originEnableAnalytics(initOptions); // call the base class function }; -atsAnalyticsAdapter.callHandler = function (evtype, args) { - if (evtype === CONSTANTS.EVENTS.BID_REQUESTED) { - handlerRequest = handlerRequest.concat(bidRequestedHandler(args)); - } else if (evtype === CONSTANTS.EVENTS.BID_RESPONSE) { - handlerResponse.push(bidResponseHandler(args)); - } - if (evtype === CONSTANTS.EVENTS.AUCTION_END) { - let bidWonTimeout = atsAnalyticsAdapter.context.bidWonTimeout ? atsAnalyticsAdapter.context.bidWonTimeout : 2000; - let events = []; - setTimeout(() => { - let winningBids = $$PREBID_GLOBAL$$.getAllWinningBids(); - logInfo('ATS Analytics - winning bids: ', winningBids) - // prepare format data for sending to analytics endpoint - if (handlerRequest.length) { - let wonEvent = {}; - if (handlerResponse.length) { - events = handlerRequest.filter(request => handlerResponse.filter(function (response) { - if (request.bid_id === response.bid_id) { - Object.assign(request, response); - } - })); - if (winningBids.length) { - events = events.filter(event => winningBids.filter(function (won) { - wonEvent.bid_id = won.requestId; - wonEvent.bid_won = true; - if (event.bid_id === wonEvent.bid_id) { - Object.assign(event, wonEvent); - } - })) - } - } else { - events = handlerRequest; - } - // check should we send data to analytics or not, check first cookie value _lr_sampling_rate - try { - let envelopeSourceCookieValue = storage.getCookie('_lr_env_src_ats'); - let samplingRateCookie = storage.getCookie('_lr_sampling_rate'); - if (!samplingRateCookie) { - preflightRequest(envelopeSourceCookieValue, events); - } else { - if (atsAnalyticsAdapter.shouldFireRequest(parseInt(samplingRateCookie)) && envelopeSourceCookieValue != null) { - logInfo('ATS Analytics - events to send: ', events); - sendDataToAnalytic(events); - } - } - // empty events array to not send duplicate events - events = []; - } catch (err) { - logError('ATS Analytics - preflight request encounter an error: ', err); - } - } - }, bidWonTimeout); - } -} - adaptermanager.registerAnalyticsAdapter({ adapter: atsAnalyticsAdapter, code: 'atsAnalytics', diff --git a/modules/atsAnalyticsAdapter.md b/modules/atsAnalyticsAdapter.md index 17819ac61b3..7c634f39ae2 100644 --- a/modules/atsAnalyticsAdapter.md +++ b/modules/atsAnalyticsAdapter.md @@ -17,7 +17,6 @@ Analytics adapter for Authenticated Traffic Solution(ATS), provided by LiveRamp. provider: 'atsAnalytics', options: { pid: '999', // publisher ID - bidWonTimeout: 2000 // on auction end for how long to wait for bid_won events, by default it's 2000 miliseconds, if it's not set it will be 2000 miliseconds. } } ``` diff --git a/modules/audiencerunBidAdapter.js b/modules/audiencerunBidAdapter.js index 2744e38e820..da0cbb39925 100644 --- a/modules/audiencerunBidAdapter.js +++ b/modules/audiencerunBidAdapter.js @@ -1,37 +1,39 @@ -import { - deepAccess, - isFn, - logError, - getValue, - getBidIdParameter, - _each, - isArray, - triggerPixel, - formatQS, -} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; -import { createEidsArray } from './userId/eids.js'; const BIDDER_CODE = 'audiencerun'; const BASE_URL = 'https://d.audiencerun.com'; const AUCTION_URL = `${BASE_URL}/prebid`; const TIMEOUT_EVENT_URL = `${BASE_URL}/ps/pbtimeout`; -const ERROR_EVENT_URL = `${BASE_URL}/js_log`; const DEFAULT_CURRENCY = 'USD'; let requestedBids = []; /** - * Returns bidfloor through floors module if available. + * Gets bidder request referer + * + * @param {Object} bidderRequest + * @return {string} + */ +function getPageUrl(bidderRequest) { + return ( + config.getConfig('pageUrl') || + utils.deepAccess(bidderRequest, 'refererInfo.referer') || + null + ); +} + +/** + * Returns bidfloor through floors module if available * * @param {Object} bid * @returns {number} */ function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidfloor', 0); + if (!utils.isFn(bid.getFloor)) { + return utils.deepAccess(bid, 'params.bidfloor', 0); } try { @@ -42,59 +44,25 @@ function getBidFloor(bid) { }); return bidFloor.floor; } catch (_) { - return 0; + return 0 } } -/** - * Returns the most top page referer. - * - * @returns {string} - */ -function getPageReferer() { - let t, e; - do { - t = t ? t.parent : window; - try { - e = t.document.referrer; - } catch (_) { - break; - } - } while (t !== window.top); - return e; -} - -/** - * Returns bidder request page url. - * - * @param {Object} bidderRequest - * @return {string} - */ -function getPageUrl(bidderRequest) { - return ( - config.getConfig('pageUrl') || - deepAccess(bidderRequest, 'refererInfo.referer') || - getPageReferer() || - null - ); -} - export const spec = { - version: '1.2.0', + version: '1.1.0', code: BIDDER_CODE, - gvlid: 944, supportedMediaTypes: [BANNER], /** * Determines whether or not the given bid request is valid. * - * @param {BidRequest} bid The bid params to validate. + * @param {object} bid The bid to validate. * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { let isValid = true; - if (!deepAccess(bid, 'params.zoneId')) { - logError('AudienceRun zoneId parameter is required. Bid aborted.'); + if (!utils.deepAccess(bid, 'params.zoneId')) { + utils.logError('AudienceRun zoneId parameter is required. Bid aborted.'); isValid = false; } return isValid; @@ -109,37 +77,30 @@ export const spec = { */ buildRequests: function (bidRequests, bidderRequest) { const bids = bidRequests.map((bid) => { - const sizes = deepAccess(bid, 'mediaTypes.banner.sizes', []); + const sizes = utils.deepAccess(bid, 'mediaTypes.banner.sizes', []); return { - zoneId: getValue(bid.params, 'zoneId'), + zoneId: utils.getValue(bid.params, 'zoneId'), sizes: sizes.map((size) => ({ w: size[0], h: size[1], })), bidfloor: getBidFloor(bid), bidId: bid.bidId, - bidderRequestId: getBidIdParameter('bidderRequestId', bid), - adUnitCode: getBidIdParameter('adUnitCode', bid), - auctionId: getBidIdParameter('auctionId', bid), - transactionId: getBidIdParameter('transactionId', bid), + bidderRequestId: utils.getBidIdParameter('bidderRequestId', bid), + adUnitCode: utils.getBidIdParameter('adUnitCode', bid), + auctionId: utils.getBidIdParameter('auctionId', bid), + transactionId: utils.getBidIdParameter('transactionId', bid), }; }); const payload = { libVersion: this.version, - pageUrl: config.getConfig('pageUrl'), - pageReferer: getPageReferer(), - referer: deepAccess(bidderRequest, 'refererInfo.referer'), - refererInfo: deepAccess(bidderRequest, 'refererInfo'), + referer: getPageUrl(bidderRequest), currencyCode: config.getConfig('currency.adServerCurrency'), timeout: config.getConfig('bidderTimeout'), bids, }; - payload.uspConsent = deepAccess(bidderRequest, 'uspConsent'); - payload.schain = deepAccess(bidRequests, '0.schain'); - payload.userId = deepAccess(bidRequests, '0.userId') ? createEidsArray(bidRequests[0].userId) : []; - if (bidderRequest && bidderRequest.gdprConsent) { payload.gdpr = { consent: bidderRequest.gdprConsent.consentString, @@ -156,7 +117,7 @@ export const spec = { return { method: 'POST', - url: deepAccess(bidRequests, '0.params.auctionUrl', AUCTION_URL), + url: AUCTION_URL, data: JSON.stringify(payload), options: { withCredentials: true, @@ -172,7 +133,7 @@ export const spec = { */ interpretResponse: function (serverResponse, bidRequest) { const bids = []; - _each(serverResponse.body.bid, function (bidObject) { + utils._each(serverResponse.body.bid, function (bidObject) { if (!bidObject.cpm || bidObject.cpm === null || !bidObject.adm) { return; } @@ -235,34 +196,20 @@ export const spec = { * @param {Array} timeoutData timeout specific data */ onTimeout: function (timeoutData) { - if (!isArray(timeoutData)) { + if (!utils.isArray(timeoutData)) { return; } timeoutData.forEach((bid) => { - const bidOnTimeout = requestedBids.find( - (requestedBid) => requestedBid.bidId === bid.bidId - ); + const bidOnTimeout = requestedBids.find((requestedBid) => requestedBid.bidId === bid.bidId); if (bidOnTimeout) { - triggerPixel( + utils.triggerPixel( `${TIMEOUT_EVENT_URL}/${bidOnTimeout.zoneId}/${bidOnTimeout.bidId}` ); } }); }, - - /** - * Registers bidder specific code, which will execute if the bidder responded with an error. - * @param {{bidderRequest: object}} args An object from which we extract bidderRequest object. - */ - onBidderError: function ({ bidderRequest }) { - const queryString = formatQS({ - message: `Prebid.js: Server call for ${bidderRequest.bidderCode} failed.`, - url: encodeURIComponent(getPageUrl(bidderRequest)), - }); - triggerPixel(`${ERROR_EVENT_URL}/?${queryString}`); - }, }; registerBidder(spec); diff --git a/modules/automatadBidAdapter.js b/modules/automatadBidAdapter.js index e3d0d87783a..415c52ba6d3 100644 --- a/modules/automatadBidAdapter.js +++ b/modules/automatadBidAdapter.js @@ -1,11 +1,11 @@ -import { logInfo } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js' +import * as utils from '../src/utils.js' import {BANNER} from '../src/mediaTypes.js' import {ajax} from '../src/ajax.js' const BIDDER = 'automatad' -const ENDPOINT_URL = 'https://bid.atmtd.com' +const ENDPOINT_URL = 'https://rtb2.automatad.com/ortb2' const DEFAULT_BID_TTL = 30 const DEFAULT_CURRENCY = 'USD' @@ -18,7 +18,7 @@ export const spec = { isBidRequestValid: function (bid) { // will receive request bid. check if have necessary params for bidding - return (bid && bid.hasOwnProperty('params') && bid.params.hasOwnProperty('siteId') && bid.params.siteId != null && bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty('banner') && typeof bid.mediaTypes.banner == 'object') + return (bid && bid.hasOwnProperty('params') && bid.params.hasOwnProperty('siteId') && bid.params.hasOwnProperty('placementId') && bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty('banner')) }, buildRequests: function (validBidRequests, bidderRequest) { @@ -29,29 +29,16 @@ export const spec = { const siteId = validBidRequests[0].params.siteId const impressions = validBidRequests.map(bidRequest => { - if (bidRequest.params.hasOwnProperty('placementId')) { - return { - id: bidRequest.bidId, - adUnitCode: bidRequest.adUnitCode, - placement: bidRequest.params.placementId, - banner: { - format: bidRequest.sizes.map(sizeArr => ({ - w: sizeArr[0], - h: sizeArr[1], - })) - }, - } - } else { - return { - id: bidRequest.bidId, - adUnitCode: bidRequest.adUnitCode, - banner: { - format: bidRequest.sizes.map(sizeArr => ({ - w: sizeArr[0], - h: sizeArr[1], - })) - }, - } + return { + id: bidRequest.bidId, + adUnitCode: bidRequest.adUnitCode, + placement: bidRequest.params.placementId, + banner: { + format: bidRequest.sizes.map(sizeArr => ({ + w: sizeArr[0], + h: sizeArr[1], + })) + }, } }) @@ -70,7 +57,7 @@ export const spec = { const payloadString = JSON.stringify(openrtbRequest) return { method: 'POST', - url: ENDPOINT_URL + '/request', + url: ENDPOINT_URL + '/resp', data: payloadString, options: { contentType: 'application/json', @@ -85,7 +72,6 @@ export const spec = { const response = (serverResponse || {}).body if (response && response.seatbid && response.seatbid[0].bid && response.seatbid[0].bid.length) { - var bidid = response.bidid response.seatbid.forEach(bidObj => { bidObj.bid.forEach(bid => { bidResponses.push({ @@ -102,19 +88,20 @@ export const spec = { height: bid.h, netRevenue: DEFAULT_NET_REVENUE, nurl: bid.nurl, - bidId: bidid }) }) }) } else { - logInfo('automatad :: no valid responses to interpret') + utils.logInfo('automatad :: no valid responses to interpret') } return bidResponses }, - onTimeout: function(timeoutData) { - const timeoutUrl = ENDPOINT_URL + '/timeout' - ajax(timeoutUrl, null, JSON.stringify(timeoutData)) + getUserSyncs: function(syncOptions, serverResponse) { + return [{ + type: 'iframe', + url: 'https://rtb2.automatad.com/ortb2/async_usersync' + }] }, onBidWon: function(bid) { if (!bid.nurl) { return } @@ -129,9 +116,6 @@ export const spec = { ).replace( /\$\{AUCTION_CURRENCY\}/, winCurr - ).replace( - /\$\{AUCTON_BID_ID\}/, - bid.bidId ).replace( /\$\{AUCTION_ID\}/, bid.auctionId diff --git a/modules/automatadBidAdapter.md b/modules/automatadBidAdapter.md index 94bc707c75b..56a4b53c067 100644 --- a/modules/automatadBidAdapter.md +++ b/modules/automatadBidAdapter.md @@ -25,8 +25,8 @@ var adUnits = [ bids: [{ bidder: 'automatad', params: { - siteId: 'someValue', // required - placementId: 'someValue' // optional + siteId: 'someValue', + placementId: 'someValue' } }] } diff --git a/modules/axonixBidAdapter.js b/modules/axonixBidAdapter.js index a790a89a0c1..daaac27e6a4 100644 --- a/modules/axonixBidAdapter.js +++ b/modules/axonixBidAdapter.js @@ -1,7 +1,7 @@ -import { isArray, logError, deepAccess, isEmpty, triggerPixel, replaceAuctionPrice } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; +import * as utils from '../src/utils.js'; import { ajax } from '../src/ajax.js'; const BIDDER_CODE = 'axonix'; @@ -68,9 +68,9 @@ export const spec = { // video bid request validation if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(VIDEO)) { if (!bid.mediaTypes[VIDEO].hasOwnProperty('mimes') || - !isArray(bid.mediaTypes[VIDEO].mimes) || + !utils.isArray(bid.mediaTypes[VIDEO].mimes) || bid.mediaTypes[VIDEO].mimes.length === 0) { - logError('mimes are mandatory for video bid request. Ad Unit: ', JSON.stringify(bid)); + utils.logError('mimes are mandatory for video bid request. Ad Unit: ', JSON.stringify(bid)); return false; } @@ -142,7 +142,7 @@ export const spec = { interpretResponse: function(serverResponse) { const response = serverResponse ? serverResponse.body : []; - if (!isArray(response)) { + if (!utils.isArray(response)) { return []; } @@ -160,9 +160,9 @@ export const spec = { }, onTimeout: function(timeoutData) { - const params = deepAccess(timeoutData, '0.params.0'); + const params = utils.deepAccess(timeoutData, '0.params.0'); - if (!isEmpty(params)) { + if (!utils.isEmpty(params)) { ajax(getURL(params, 'prebid/timeout'), null, timeoutData[0], { method: 'POST', options: { @@ -177,7 +177,7 @@ export const spec = { const { nurl } = bid || {}; if (bid.nurl) { - triggerPixel(replaceAuctionPrice(nurl, bid.originalCpm || bid.cpm)); + utils.triggerPixel(utils.replaceAuctionPrice(nurl, bid.cpm)); }; } } diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 1c341e4dc51..d633359eb8e 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -1,21 +1,12 @@ -import { - deepAccess, - deepClone, - deepSetValue, - getUniqueIdentifierStr, - isArray, - isFn, - logWarn, - parseSizesInput, - parseUrl -} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {Renderer} from '../src/Renderer.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {find, includes} from '../src/polyfill.js'; - -const ADAPTER_VERSION = '1.19'; +import * as utils from '../src/utils.js'; +import { config } from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { Renderer } from '../src/Renderer.js'; +import { VIDEO, BANNER } from '../src/mediaTypes.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; + +const ADAPTER_VERSION = '1.17'; const ADAPTER_NAME = 'BFIO_PREBID'; const OUTSTREAM = 'outstream'; const CURRENCY = 'USD'; @@ -41,27 +32,7 @@ export const spec = { supportedMediaTypes: [ VIDEO, BANNER ], isBidRequestValid(bid) { - if (isVideoBid(bid)) { - if (!getVideoBidParam(bid, 'appId')) { - logWarn('Beachfront: appId param is required for video bids.'); - return false; - } - if (!getVideoBidParam(bid, 'bidfloor')) { - logWarn('Beachfront: bidfloor param is required for video bids.'); - return false; - } - } - if (isBannerBid(bid)) { - if (!getBannerBidParam(bid, 'appId')) { - logWarn('Beachfront: appId param is required for banner bids.'); - return false; - } - if (!getBannerBidParam(bid, 'bidfloor')) { - logWarn('Beachfront: bidfloor param is required for banner bids.'); - return false; - } - } - return true; + return !!(isVideoBidValid(bid) || isBannerBidValid(bid)); }, buildRequests(bids, bidderRequest) { @@ -94,12 +65,12 @@ export const spec = { if (isVideoBid(bidRequest)) { if (!response || !response.bidPrice) { - logWarn(`No valid video bids from ${spec.code} bidder`); + utils.logWarn(`No valid video bids from ${spec.code} bidder`); return []; } let sizes = getVideoSizes(bidRequest); let firstSize = getFirstSize(sizes); - let context = deepAccess(bidRequest, 'mediaTypes.video.context'); + let context = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); let responseType = getVideoBidParam(bidRequest, 'responseType') || 'both'; let responseMeta = Object.assign({ mediaType: VIDEO, advertiserDomains: [] }, response.meta); let bidResponse = { @@ -128,7 +99,7 @@ export const spec = { return bidResponse; } else { if (!response || !response.length) { - logWarn(`No valid banner bids from ${spec.code} bidder`); + utils.logWarn(`No valid banner bids from ${spec.code} bidder`); return []; } return response @@ -157,7 +128,7 @@ export const spec = { getUserSyncs(syncOptions, serverResponses = [], gdprConsent = {}, uspConsent = '') { let syncs = []; let { gdprApplies, consentString = '' } = gdprConsent; - let bannerResponse = find(serverResponses, (res) => isArray(res.body)); + let bannerResponse = find(serverResponses, (res) => utils.isArray(res.body)); if (bannerResponse) { if (syncOptions.iframeEnabled) { @@ -215,7 +186,7 @@ function getFirstSize(sizes) { } function parseSizes(sizes) { - return parseSizesInput(sizes).map(size => { + return utils.parseSizesInput(sizes).map(size => { let [ width, height ] = size.split('x'); return { w: parseInt(width, 10) || undefined, @@ -225,11 +196,11 @@ function parseSizes(sizes) { } function getVideoSizes(bid) { - return parseSizes(deepAccess(bid, 'mediaTypes.video.playerSize') || bid.sizes); + return parseSizes(utils.deepAccess(bid, 'mediaTypes.video.playerSize') || bid.sizes); } function getBannerSizes(bid) { - return parseSizes(deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes); + return parseSizes(utils.deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes); } function getOsVersion() { @@ -266,33 +237,33 @@ function getDoNotTrack() { } function isVideoBid(bid) { - return deepAccess(bid, 'mediaTypes.video'); + return utils.deepAccess(bid, 'mediaTypes.video'); } function isBannerBid(bid) { - return deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid); + return utils.deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid); } function getVideoBidParam(bid, key) { - return deepAccess(bid, 'params.video.' + key) || deepAccess(bid, 'params.' + key); + return utils.deepAccess(bid, 'params.video.' + key) || utils.deepAccess(bid, 'params.' + key); } function getBannerBidParam(bid, key) { - return deepAccess(bid, 'params.banner.' + key) || deepAccess(bid, 'params.' + key); + return utils.deepAccess(bid, 'params.banner.' + key) || utils.deepAccess(bid, 'params.' + key); } function getPlayerBidParam(bid, key, defaultValue) { - let param = deepAccess(bid, 'params.player.' + key); + let param = utils.deepAccess(bid, 'params.player.' + key); return param === undefined ? defaultValue : param; } function getBannerBidFloor(bid) { - let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: CURRENCY, mediaType: 'banner', size: '*' }) : {}; + let floorInfo = utils.isFn(bid.getFloor) ? bid.getFloor({ currency: CURRENCY, mediaType: 'banner', size: '*' }) : {}; return floorInfo.floor || getBannerBidParam(bid, 'bidfloor'); } function getVideoBidFloor(bid) { - let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: CURRENCY, mediaType: 'video', size: '*' }) : {}; + let floorInfo = utils.isFn(bid.getFloor) ? bid.getFloor({ currency: CURRENCY, mediaType: 'video', size: '*' }) : {}; return floorInfo.floor || getVideoBidParam(bid, 'bidfloor'); } @@ -306,7 +277,7 @@ function isBannerBidValid(bid) { function getTopWindowLocation(bidderRequest) { let url = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; - return parseUrl(config.getConfig('pageUrl') || url, { decodeSearchAsString: true }); + return utils.parseUrl(config.getConfig('pageUrl') || url, { decodeSearchAsString: true }); } function getTopWindowReferrer() { @@ -325,7 +296,7 @@ function getEids(bid) { function getUserId(bid) { return ({ key, source, rtiPartner, atype }) => { - let id = deepAccess(bid, `userId.${key}`); + let id = utils.deepAccess(bid, `userId.${key}`); return id ? formatEid(id, source, rtiPartner, atype) : null; }; } @@ -369,12 +340,11 @@ function createVideoRequestData(bid, bidderRequest) { let tagid = getVideoBidParam(bid, 'tagid'); let topLocation = getTopWindowLocation(bidderRequest); let eids = getEids(bid); - let ortb2 = deepClone(config.getConfig('ortb2')); let payload = { isPrebid: true, appId: appId, domain: document.location.hostname, - id: getUniqueIdentifierStr(), + id: utils.getUniqueIdentifierStr(), imp: [{ video: Object.assign({ w: firstSize.w, @@ -388,7 +358,6 @@ function createVideoRequestData(bid, bidderRequest) { displaymanagerver: ADAPTER_VERSION }], site: { - ...deepAccess(ortb2, 'site', {}), page: topLocation.href, domain: topLocation.hostname }, @@ -400,32 +369,39 @@ function createVideoRequestData(bid, bidderRequest) { js: 1, geo: {} }, - app: deepAccess(ortb2, 'app'), - user: deepAccess(ortb2, 'user'), + regs: { + ext: {} + }, + source: { + ext: {} + }, + user: { + ext: {} + }, cur: [CURRENCY] }; if (bidderRequest && bidderRequest.uspConsent) { - deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); + payload.regs.ext.us_privacy = bidderRequest.uspConsent; } if (bidderRequest && bidderRequest.gdprConsent) { let { gdprApplies, consentString } = bidderRequest.gdprConsent; - deepSetValue(payload, 'regs.ext.gdpr', gdprApplies ? 1 : 0); - deepSetValue(payload, 'user.ext.consent', consentString); + payload.regs.ext.gdpr = gdprApplies ? 1 : 0; + payload.user.ext.consent = consentString; } if (bid.schain) { - deepSetValue(payload, 'source.ext.schain', bid.schain); + payload.source.ext.schain = bid.schain; } if (eids.length > 0) { - deepSetValue(payload, 'user.ext.eids', eids); + payload.user.ext.eids = eids; } let connection = navigator.connection || navigator.webkitConnection; if (connection && connection.effectiveType) { - deepSetValue(payload, 'device.connectiontype', connection.effectiveType); + payload.device.connectiontype = connection.effectiveType; } return payload; @@ -443,10 +419,8 @@ function createBannerRequestData(bids, bidderRequest) { sizes: getBannerSizes(bid) }; }); - let ortb2 = deepClone(config.getConfig('ortb2')); let payload = { slots: slots, - ortb2: ortb2, page: topLocation.href, domain: topLocation.hostname, search: topLocation.search, @@ -475,7 +449,7 @@ function createBannerRequestData(bids, bidderRequest) { } SUPPORTED_USER_IDS.forEach(({ key, queryParam }) => { - let id = deepAccess(bids, `0.userId.${key}`) + let id = utils.deepAccess(bids, `0.userId.${key}`) if (id) { payload[queryParam] = id; } diff --git a/modules/beopBidAdapter.js b/modules/beopBidAdapter.js index 2e74170fcaf..b7e6708f701 100644 --- a/modules/beopBidAdapter.js +++ b/modules/beopBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, isArray, logWarn, triggerPixel, buildUrl, logInfo, getValue, getBidIdParameter } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; const BIDDER_CODE = 'beop'; @@ -36,7 +36,7 @@ export const spec = { */ buildRequests: function(validBidRequests, bidderRequest) { const slots = validBidRequests.map(beOpRequestSlotsMaker); - let pageUrl = deepAccess(window, 'location.href') || deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || config.getConfig('pageUrl'); + let pageUrl = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href'); let fpd = config.getLegacyFpd(config.getConfig('ortb2')); let gdpr = bidderRequest.gdprConsent; let firstSlot = slots[0]; @@ -50,7 +50,7 @@ export const spec = { kwds: (fpd && fpd.site && fpd.site.keywords) || [], dbg: false, slts: slots, - is_amp: deepAccess(bidderRequest, 'referrerInfo.isAmp'), + is_amp: utils.deepAccess(bidderRequest, 'referrerInfo.isAmp'), tc_string: (gdpr && gdpr.gdprApplies) ? gdpr.consentString : null, }; const payloadString = JSON.stringify(payloadObject); @@ -61,7 +61,7 @@ export const spec = { } }, interpretResponse: function(serverResponse, request) { - if (serverResponse && serverResponse.body && isArray(serverResponse.body.bids) && serverResponse.body.bids.length > 0) { + if (serverResponse && serverResponse.body && utils.isArray(serverResponse.body.bids) && serverResponse.body.bids.length > 0) { return serverResponse.body.bids; } return []; @@ -73,8 +73,8 @@ export const spec = { let trackingParams = buildTrackingParams(timeoutData, 'timeout', timeoutData.timeout); - logWarn(BIDDER_CODE + ': timed out request'); - triggerPixel(buildUrl({ + utils.logWarn(BIDDER_CODE + ': timed out request'); + utils.triggerPixel(utils.buildUrl({ protocol: 'https', hostname: 't.beop.io', pathname: '/bid', @@ -87,8 +87,8 @@ export const spec = { } let trackingParams = buildTrackingParams(bid, 'won', bid.cpm); - logInfo(BIDDER_CODE + ': won request'); - triggerPixel(buildUrl({ + utils.logInfo(BIDDER_CODE + ': won request'); + utils.triggerPixel(utils.buildUrl({ protocol: 'https', hostname: 't.beop.io', pathname: '/bid', @@ -99,24 +99,22 @@ export const spec = { } function buildTrackingParams(data, info, value) { - const accountId = data.params.accountId; return { - pid: accountId === undefined ? data.ad.match(/account: \“([a-f\d]{24})\“/)[1] : accountId, + pid: data.params.accountId, nid: data.params.networkId, nptnid: data.params.networkPartnerId, - bid: data.bidId || data.requestId, + bid: data.bidId, sl_n: data.adUnitCode, aid: data.auctionId, se_ca: 'bid', se_ac: info, - se_va: value, - url: window.location.href + se_va: value }; } function beOpRequestSlotsMaker(bid) { - const bannerSizes = deepAccess(bid, 'mediaTypes.banner.sizes'); - const publisherCurrency = config.getConfig('currency.adServerCurrency') || getValue(bid.params, 'currency') || 'EUR'; + const bannerSizes = utils.deepAccess(bid, 'mediaTypes.banner.sizes'); + const publisherCurrency = utils.getValue(bid.params, 'currency') || 'EUR'; let floor; if (typeof bid.getFloor === 'function') { const floorInfo = bid.getFloor({currency: publisherCurrency, mediaType: 'banner', size: [1, 1]}); @@ -125,19 +123,19 @@ function beOpRequestSlotsMaker(bid) { } } return { - sizes: isArray(bannerSizes) ? bannerSizes : bid.sizes, + sizes: utils.isArray(bannerSizes) ? bannerSizes : bid.sizes, flr: floor, - pid: getValue(bid.params, 'accountId'), - nid: getValue(bid.params, 'networkId'), - nptnid: getValue(bid.params, 'networkPartnerId'), - bid: getBidIdParameter('bidId', bid), - brid: getBidIdParameter('bidderRequestId', bid), - name: getBidIdParameter('adUnitCode', bid), - aid: getBidIdParameter('auctionId', bid), - tid: getBidIdParameter('transactionId', bid), - brc: getBidIdParameter('bidRequestsCount', bid), - bdrc: getBidIdParameter('bidderRequestCount', bid), - bwc: getBidIdParameter('bidderWinsCount', bid), + pid: utils.getValue(bid.params, 'accountId'), + nid: utils.getValue(bid.params, 'networkId'), + nptnid: utils.getValue(bid.params, 'networkPartnerId'), + bid: utils.getBidIdParameter('bidId', bid), + brid: utils.getBidIdParameter('bidderRequestId', bid), + name: utils.getBidIdParameter('adUnitCode', bid), + aid: utils.getBidIdParameter('auctionId', bid), + tid: utils.getBidIdParameter('transactionId', bid), + brc: utils.getBidIdParameter('bidRequestsCount', bid), + bdrc: utils.getBidIdParameter('bidderRequestCount', bid), + bwc: utils.getBidIdParameter('bidderWinsCount', bid), } } diff --git a/modules/betweenBidAdapter.js b/modules/betweenBidAdapter.js index e4907c15974..5a351def958 100644 --- a/modules/betweenBidAdapter.js +++ b/modules/betweenBidAdapter.js @@ -1,16 +1,14 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; -import { getAdUnitSizes, parseSizesInput } from '../src/utils.js'; +import { getAdUnitSizes, parseSizesInput, deepAccess } from '../src/utils.js'; import { getRefererInfo } from '../src/refererDetection.js'; -import {includes} from '../src/polyfill.js' const BIDDER_CODE = 'between'; -let ENDPOINT = 'https://ads.betweendigital.com/adjson?t=prebid'; -const CODE_TYPES = ['inpage', 'preroll', 'midroll', 'postroll']; +const ENDPOINT = 'https://ads.betweendigital.com/adjson?t=prebid'; export const spec = { code: BIDDER_CODE, aliases: ['btw'], - supportedMediaTypes: ['banner', 'video'], + supportedMediaTypes: ['banner'], /** * Determines whether or not the given bid request is valid. * @@ -23,7 +21,7 @@ export const spec = { /** * Make a server request from the list of BidRequests. * - * @param {validBidRequest?pbjs_debug=trues[]} - an array of bids + * @param {validBidRequests[]} - an array of bids * @return ServerRequest Info describing the request to the server. */ buildRequests: function(validBidRequests, bidderRequest) { @@ -31,32 +29,21 @@ export const spec = { const gdprConsent = bidderRequest && bidderRequest.gdprConsent; const refInfo = getRefererInfo(); - validBidRequests.forEach((i) => { - const video = i.mediaTypes && i.mediaTypes.video; - + validBidRequests.forEach(i => { let params = { - eids: getUsersIds(i), sizes: parseSizesInput(getAdUnitSizes(i)), jst: 'hb', ord: Math.random() * 10000000000000000, tz: getTz(), fl: getFl(), rr: getRr(), - s: i.params && i.params.s, + shid: getSharedId(i)('id'), + shid3: getSharedId(i)('third'), + s: i.params.s, bidid: i.bidId, transactionid: i.transactionId, auctionid: i.auctionId }; - - if (video) { - params.mediaType = 2; - params.maxd = video.maxd; - params.mind = video.mind; - params.pos = 'atf'; - params.jst = 'pvc'; - params.codeType = includes(CODE_TYPES, video.codeType) ? video.codeType : 'inpage'; - } - if (i.params.itu !== undefined) { params.itu = i.params.itu; } @@ -107,25 +94,21 @@ export const spec = { */ interpretResponse: function(serverResponse, bidRequest) { const bidResponses = []; - for (var i = 0; i < serverResponse.body.length; i++) { let bidResponse = { requestId: serverResponse.body[i].bidid, cpm: serverResponse.body[i].cpm || 0, width: serverResponse.body[i].w, height: serverResponse.body[i].h, - vastXml: serverResponse.body[i].vastXml, - mediaType: serverResponse.body[i].mediaType, ttl: serverResponse.body[i].ttl, creativeId: serverResponse.body[i].creativeid, - currency: serverResponse.body[i].currency || 'USD', + currency: serverResponse.body[i].currency || 'RUB', netRevenue: serverResponse.body[i].netRevenue || true, ad: serverResponse.body[i].ad, meta: { advertiserDomains: serverResponse.body[i].adomain ? serverResponse.body[i].adomain : [] } }; - bidResponses.push(bidResponse); } return bidResponses; @@ -158,22 +141,21 @@ export const spec = { // type: 'iframe', // url: 'https://acdn.adnxs.com/dmp/async_usersync.html' // }); - syncs.push( - { - type: 'iframe', - url: 'https://ads.betweendigital.com/sspmatch-iframe' - }, - { - type: 'image', - url: 'https://ads.betweendigital.com/sspmatch' - } - ); + syncs.push({ + type: 'iframe', + url: 'https://ads.betweendigital.com/sspmatch-iframe' + }); return syncs; } } -function getUsersIds({ userIdAsEids }) { - return (userIdAsEids && userIdAsEids.length !== 0) ? userIdAsEids : []; +function getSharedId(bid) { + const id = deepAccess(bid, 'userId.sharedid.id'); + const third = deepAccess(bid, 'userId.sharedid.third'); + return function(kind) { + if (kind === 'id') return id || ''; + return third || ''; + } } function getRr() { diff --git a/modules/bidViewability.js b/modules/bidViewability.js index 837eccd00c1..c3b72cda8d4 100644 --- a/modules/bidViewability.js +++ b/modules/bidViewability.js @@ -2,13 +2,13 @@ // GPT API is used to find when a bid is viewable, https://developers.google.com/publisher-tag/reference#googletag.events.impressionviewableevent // Does not work with other than GPT integration -import {config} from '../src/config.js'; +import { config } from '../src/config.js'; import * as events from '../src/events.js'; -import CONSTANTS from '../src/constants.json'; -import {isFn, logWarn, triggerPixel} from '../src/utils.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import adapterManager, {gdprDataHandler, uspDataHandler} from '../src/adapterManager.js'; -import {find} from '../src/polyfill.js'; +import { EVENTS } from '../src/constants.json'; +import { logWarn, isFn, triggerPixel } from '../src/utils.js'; +import { getGlobal } from '../src/prebidGlobal.js'; +import adapterManager, { gdprDataHandler, uspDataHandler } from '../src/adapterManager.js'; +import find from 'core-js-pure/features/array/find.js'; const MODULE_NAME = 'bidViewability'; const CONFIG_ENABLED = 'enabled'; @@ -70,12 +70,12 @@ export let impressionViewableHandler = (globalModuleConfig, slot, event) => { // trigger respective bidder's onBidViewable handler adapterManager.callBidViewableBidder(respectiveBid.bidder, respectiveBid); // emit the BID_VIEWABLE event with bid details, this event can be consumed by bidders and analytics pixels - events.emit(CONSTANTS.EVENTS.BID_VIEWABLE, respectiveBid); + events.emit(EVENTS.BID_VIEWABLE, respectiveBid); } }; export let init = () => { - events.on(CONSTANTS.EVENTS.AUCTION_INIT, () => { + events.on(EVENTS.AUCTION_INIT, () => { // read the config for the module const globalModuleConfig = config.getConfig(MODULE_NAME) || {}; // do nothing if module-config.enabled is not set to true diff --git a/modules/bidViewabilityIO.js b/modules/bidViewabilityIO.js index ff7ec70e32c..4651e424d00 100644 --- a/modules/bidViewabilityIO.js +++ b/modules/bidViewabilityIO.js @@ -1,7 +1,7 @@ -import { logMessage } from '../src/utils.js'; import { config } from '../src/config.js'; import * as events from '../src/events.js'; -import CONSTANTS from '../src/constants.json'; +import { EVENTS } from '../src/constants.json'; +import * as utils from '../src/utils.js'; const MODULE_NAME = 'bidViewabilityIO'; const CONFIG_ENABLED = 'enabled'; @@ -23,8 +23,8 @@ export let isSupportedMediaType = (bid) => { return supportedMediaTypes.indexOf(bid.mediaType) > -1; } -let _logMessage = (message) => { - return logMessage(`${MODULE_NAME}: ${message}`); +let logMessage = (message) => { + return utils.logMessage(`${MODULE_NAME}: ${message}`); } // returns options for the iO that detects if the ad is viewable @@ -42,8 +42,8 @@ export let getViewableOptions = (bid) => { export let markViewed = (bid, entry, observer) => { return () => { observer.unobserve(entry.target); - events.emit(CONSTANTS.EVENTS.BID_VIEWABLE, bid); - _logMessage(`id: ${entry.target.getAttribute('id')} code: ${bid.adUnitCode} was viewed`); + events.emit(EVENTS.BID_VIEWABLE, bid); + logMessage(`id: ${entry.target.getAttribute('id')} code: ${bid.adUnitCode} was viewed`); } } @@ -59,13 +59,13 @@ export let viewCallbackFactory = (bid) => { return (entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { - _logMessage(`viewable timer starting for id: ${entry.target.getAttribute('id')} code: ${bid.adUnitCode}`); + logMessage(`viewable timer starting for id: ${entry.target.getAttribute('id')} code: ${bid.adUnitCode}`); entry.target.view_tracker = setTimeout(markViewed(bid, entry, observer), IAB_VIEWABLE_DISPLAY_TIME); } else { - _logMessage(`id: ${entry.target.getAttribute('id')} code: ${bid.adUnitCode} is out of view`); + logMessage(`id: ${entry.target.getAttribute('id')} code: ${bid.adUnitCode} is out of view`); if (entry.target.view_tracker) { clearTimeout(entry.target.view_tracker); - _logMessage(`viewable timer stopped for id: ${entry.target.getAttribute('id')} code: ${bid.adUnitCode}`); + logMessage(`viewable timer stopped for id: ${entry.target.getAttribute('id')} code: ${bid.adUnitCode}`); } } }); @@ -77,7 +77,7 @@ export let init = () => { if (conf[MODULE_NAME][CONFIG_ENABLED] && CLIENT_SUPPORTS_IO) { // if the module is enabled and the browser supports Intersection Observer, // then listen to AD_RENDER_SUCCEEDED to setup IO's for supported mediaTypes - events.on(CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED, ({doc, bid, id}) => { + events.on(EVENTS.AD_RENDER_SUCCEEDED, ({doc, bid, id}) => { if (isSupportedMediaType(bid)) { let viewable = new IntersectionObserver(viewCallbackFactory(bid), getViewableOptions(bid)); let element = document.getElementById(bid.adUnitCode); diff --git a/modules/biddoBidAdapter.js b/modules/biddoBidAdapter.js deleted file mode 100644 index 5512ca60f8e..00000000000 --- a/modules/biddoBidAdapter.js +++ /dev/null @@ -1,92 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER} from '../src/mediaTypes.js'; - -const BIDDER_CODE = 'biddo'; -const ENDPOINT_URL = 'https://ad.adopx.net/delivery/impress'; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER], - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bidRequest The bid request params to validate. - * @return boolean True if this is a valid bid request, and false otherwise. - */ - isBidRequestValid: function(bidRequest) { - return !!bidRequest.params.zoneId; - }, - /** - * Make a server request from the list of BidRequests. - * - * @param {Array} validBidRequests an array of bid requests - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function(validBidRequests) { - let serverRequests = []; - - validBidRequests.forEach(bidRequest => { - const sizes = bidRequest.mediaTypes.banner.sizes; - - sizes.forEach(([width, height]) => { - bidRequest.params.requestedSizes = [width, height]; - - const payload = { - ctype: 'div', - pzoneid: bidRequest.params.zoneId, - width, - height, - }; - - const payloadString = Object.keys(payload).map(k => k + '=' + encodeURIComponent(payload[k])).join('&'); - - serverRequests.push({ - method: 'GET', - url: ENDPOINT_URL, - data: payloadString, - bidderRequest: bidRequest, - }); - }); - }); - - return serverRequests; - }, - /** - * Unpack the response from the server into a list of bids. - * - * @param {ServerResponse} serverResponse A successful response from the server. - * @param {BidRequest} bidderRequest A matched bid request for this response. - * @return Array An array of bids which were nested inside the server. - */ - interpretResponse: function(serverResponse, {bidderRequest}) { - const response = serverResponse.body; - const bidResponses = []; - - if (response && response.template && response.template.html) { - const {bidId} = bidderRequest; - const [width, height] = bidderRequest.params.requestedSizes; - - const bidResponse = { - requestId: bidId, - cpm: response.hb.cpm, - creativeId: response.banner.hash, - currency: 'USD', - netRevenue: response.hb.netRevenue, - ttl: 600, - ad: response.template.html, - mediaType: 'banner', - meta: { - advertiserDomains: response.hb.adomains || [], - }, - width, - height, - }; - - bidResponses.push(bidResponse); - } - - return bidResponses; - }, -} - -registerBidder(spec); diff --git a/modules/biddoBidAdapter.md b/modules/biddoBidAdapter.md deleted file mode 100644 index baea44b22f2..00000000000 --- a/modules/biddoBidAdapter.md +++ /dev/null @@ -1,30 +0,0 @@ -# Overview - -``` -Module Name: Biddo Bidder Adapter -Module Type: Bidder Adapter -Maintainer: contact@biddo.net -``` - -# Description - -Module that connects to Invamia demand sources. - -# Test Parameters - -``` - const adUnits = [{ - code: 'test-div', - mediaTypes: { - banner: { - sizes: [[300, 250]], - }, - }, - bids: [{ - bidder: 'biddo', - params: { - zoneId: 7254, - }, - }], - }]; -``` diff --git a/modules/bidglassBidAdapter.js b/modules/bidglassBidAdapter.js index 3184372881b..b77ca474e13 100644 --- a/modules/bidglassBidAdapter.js +++ b/modules/bidglassBidAdapter.js @@ -1,4 +1,4 @@ -import { _each, isArray, getBidIdParameter, deepClone, getUniqueIdentifierStr } from '../src/utils.js'; +import * as utils from '../src/utils.js'; // import {config} from 'src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; @@ -69,12 +69,12 @@ export const spec = { let bidglass = window['bidglass']; - _each(validBidRequests, function(bid) { - bid.sizes = ((isArray(bid.sizes) && isArray(bid.sizes[0])) ? bid.sizes : [bid.sizes]); - bid.sizes = bid.sizes.filter(size => isArray(size)); + utils._each(validBidRequests, function(bid) { + bid.sizes = ((utils.isArray(bid.sizes) && utils.isArray(bid.sizes[0])) ? bid.sizes : [bid.sizes]); + bid.sizes = bid.sizes.filter(size => utils.isArray(size)); - var adUnitId = getBidIdParameter('adUnitId', bid.params); - var options = deepClone(bid.params); + var adUnitId = utils.getBidIdParameter('adUnitId', bid.params); + var options = utils.deepClone(bid.params); delete options.adUnitId; @@ -96,7 +96,7 @@ export const spec = { // Stuff to send: page URL const bidReq = { - reqId: getUniqueIdentifierStr(), + reqId: utils.getUniqueIdentifierStr(), imps: imps, ref: getReferer(), ori: getOrigins() @@ -125,7 +125,7 @@ export const spec = { interpretResponse: function(serverResponse) { const bidResponses = []; - _each(serverResponse.body.bidResponses, function(serverBid) { + utils._each(serverResponse.body.bidResponses, function(serverBid) { const bidResponse = { requestId: serverBid.requestId, cpm: parseFloat(serverBid.cpm), diff --git a/modules/bidscubeBidAdapter.js b/modules/bidscubeBidAdapter.js index 951bd97d255..d3f27a5ac6d 100644 --- a/modules/bidscubeBidAdapter.js +++ b/modules/bidscubeBidAdapter.js @@ -1,6 +1,6 @@ -import { logMessage, getWindowLocation } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js' import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js' +import * as utils from '../src/utils.js' const BIDDER_CODE = 'bidscube' const URL = 'https://supply.bidscube.com/?c=o&m=multi' @@ -20,9 +20,9 @@ export const spec = { try { window.top.location.toString() winTop = window.top - } catch (e) { logMessage(e) } + } catch (e) { utils.logMessage(e) } - const location = getWindowLocation() + const location = utils.getWindowLocation() const placements = [] for (let i = 0; i < validBidRequests.length; i++) { diff --git a/modules/bidwatchAnalyticsAdapter.js b/modules/bidwatchAnalyticsAdapter.js deleted file mode 100644 index 26a8c370af3..00000000000 --- a/modules/bidwatchAnalyticsAdapter.js +++ /dev/null @@ -1,90 +0,0 @@ -import adapter from '../src/AnalyticsAdapter.js'; -import adapterManager from '../src/adapterManager.js'; -import CONSTANTS from '../src/constants.json'; -import { ajax } from '../src/ajax.js'; - -const analyticsType = 'endpoint'; -const url = 'URL_TO_SERVER_ENDPOINT'; - -const { - EVENTS: { - AUCTION_END, - BID_WON, - } -} = CONSTANTS; - -let allEvents = {} -let initOptions = {} -let endpoint = 'https://default' -let objectToSearchForBidderCode = ['bidderRequests', 'bidsReceived', 'noBids'] - -function getAdapterNameForAlias(aliasName) { - return adapterManager.aliasRegistry[aliasName] || aliasName; -} - -function setOriginalBidder(arg) { - Object.keys(arg).forEach(key => { - arg[key]['originalBidder'] = getAdapterNameForAlias(arg[key]['bidderCode']); - if (typeof arg[key]['creativeId'] == 'number') { arg[key]['creativeId'] = arg[key]['creativeId'].toString(); } - }); - return arg -} - -function checkBidderCode(args) { - if (typeof args == 'object') { - for (let i = 0; i < objectToSearchForBidderCode.length; i++) { - if (typeof args[objectToSearchForBidderCode[i]] == 'object') { args[objectToSearchForBidderCode[i]] = setOriginalBidder(args[objectToSearchForBidderCode[i]]) } - } - } - if (typeof args['bidderCode'] == 'string') { args['originalBidder'] = getAdapterNameForAlias(args['bidderCode']); } else if (typeof args['bidder'] == 'string') { args['originalBidder'] = getAdapterNameForAlias(args['bidder']); } - if (typeof args['creativeId'] == 'number') { args['creativeId'] = args['creativeId'].toString(); } - return args -} - -function addEvent(eventType, args) { - if (allEvents[eventType] == undefined) { allEvents[eventType] = [] } - if (eventType && args) { args = checkBidderCode(args); } - allEvents[eventType].push(args); -} - -function handleBidWon(args) { - if (typeof allEvents.bidRequested == 'object' && allEvents.bidRequested.length > 0 && allEvents.bidRequested[0].gdprConsent) { args.gdpr = allEvents.bidRequested[0].gdprConsent; } - ajax(endpoint + '.bidwatch.io/analytics/bid_won', null, JSON.stringify(args), {method: 'POST', withCredentials: true}); -} - -function handleAuctionEnd() { - ajax(endpoint + '.bidwatch.io/analytics/auctions', null, JSON.stringify(allEvents), {method: 'POST', withCredentials: true}); -} - -let bidwatchAnalytics = Object.assign(adapter({url, analyticsType}), { - track({ - eventType, - args - }) { - addEvent(eventType, args); - switch (eventType) { - case AUCTION_END: - handleAuctionEnd(); - break; - case BID_WON: - handleBidWon(args); - break; - } - }}); - -// save the base class function -bidwatchAnalytics.originEnableAnalytics = bidwatchAnalytics.enableAnalytics; - -// override enableAnalytics so we can get access to the config passed in from the page -bidwatchAnalytics.enableAnalytics = function (config) { - bidwatchAnalytics.originEnableAnalytics(config); // call the base class function - initOptions = config.options; - if (initOptions.domain) { endpoint = 'https://' + initOptions.domain; } -}; - -adapterManager.registerAnalyticsAdapter({ - adapter: bidwatchAnalytics, - code: 'bidwatch' -}); - -export default bidwatchAnalytics; diff --git a/modules/bidwatchAnalyticsAdapter.md b/modules/bidwatchAnalyticsAdapter.md deleted file mode 100644 index bfa453640b8..00000000000 --- a/modules/bidwatchAnalyticsAdapter.md +++ /dev/null @@ -1,21 +0,0 @@ -# Overview -Module Name: bidwatch Analytics Adapter - -Module Type: Analytics Adapter - -Maintainer: tech@bidwatch.io - -# Description - -Analytics adapter for bidwatch.io. - -# Test Parameters - -``` -{ - provider: 'bidwatch', - options : { - domain: 'test.endpoint' - } -} -``` diff --git a/modules/big-richmediaBidAdapter.js b/modules/big-richmediaBidAdapter.js deleted file mode 100644 index 2ee31e8cfd6..00000000000 --- a/modules/big-richmediaBidAdapter.js +++ /dev/null @@ -1,125 +0,0 @@ -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {spec as baseAdapter} from './appnexusBidAdapter.js'; // eslint-disable-line prebid/validate-imports - -const BIDDER_CODE = 'big-richmedia'; - -const metadataByRequestId = {}; - -export const spec = { - version: '1.5.0', - code: BIDDER_CODE, - gvlid: baseAdapter.GVLID, // use base adapter gvlid - supportedMediaTypes: [ BANNER, VIDEO ], - - /** - * Determines whether or not the given bid request is valid. - * - * @param {object} bid The bid to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function (bid) { - if (!baseAdapter.isBidRequestValid) { return true; } - return baseAdapter.isBidRequestValid(bid); - }, - - /** - * Make a server request from the list of BidRequests. - * - * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function (bidRequests, bidderRequest) { - if (!baseAdapter.buildRequests) { return []; } - - const publisherId = config.getConfig('bigRichmedia.publisherId'); - if (typeof publisherId !== 'string') { return []; } - - bidRequests.forEach(bidRequest => { - if (bidRequest.params.format === 'skin' && bidRequest.mediaTypes.banner) { - bidRequest.mediaTypes.banner.sizes.push([1800, 1000]); - } - metadataByRequestId[bidRequest.bidId] = { placementId: bidRequest.adUnitCode, bidder: bidRequest.bidder }; - }); - return baseAdapter.buildRequests(bidRequests, bidderRequest); - }, - - /** - * Unpack the response from the server into a list of bids. - * - * @param {*} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function (serverResponse, params) { - const publisherId = config.getConfig('bigRichmedia.publisherId'); - if (typeof publisherId !== 'string') { return []; } - - const bids = baseAdapter.interpretResponse(serverResponse, params); - bids.forEach(bid => { - const { placementId, bidder } = metadataByRequestId[bid.requestId] || {}; - const { width = 1, height = 1, ad, creativeId = '', cpm, vastXml, vastUrl } = bid; - const bidRequest = params.bidderRequest.bids.find(({ bidId }) => bidId === bid.requestId); - const format = (bidRequest && bidRequest.params && bidRequest.params.format) || 'video-sticky-footer'; - const isReplayable = bidRequest && bidRequest.params && bidRequest.params.isReplayable; - const customSelector = bidRequest && bidRequest.params && bidRequest.params.customSelector; - const renderParams = { - adm: ad, - vastXml, - vastUrl, - width, - height, - placementId, - bidId: bid.requestId, - creativeId: `${creativeId}`, - bidder, - cpm, - format, - customSelector, - isReplayable - }; - - // This is a workaround needed for the rendering step (so that the adserver iframe does not get resized to 1800x1000 - // when there is skin demand - if (format === 'skin') { - renderParams.width = 1 - renderParams.height = 1 - } - - const encoded = window.btoa(JSON.stringify(renderParams)); - bid.ad = ` - `; - - if (bid.mediaType !== 'banner') { // in case this is a video - bid.mediaType = 'banner'; - delete bid.renderer; - delete bid.vastUrl; - delete bid.vastXml; - bid.width = 1; - bid.height = 1; - } - }); - return bids; - }, - - getUserSyncs: function (syncOptions, responses, gdprConsent) { - if (!baseAdapter.getUserSyncs) { return []; } - return baseAdapter.getUserSyncs(syncOptions, responses, gdprConsent); - }, - - transformBidParams: function (params, isOpenRtb) { - if (!baseAdapter.transformBidParams) { return params; } - return baseAdapter.transformBidParams(params, isOpenRtb); - }, - - /** - * Add element selector to javascript tracker to improve native viewability - * @param {Bid} bid - */ - onBidWon: function (bid) { - if (!baseAdapter.onBidWon) { return; } - baseAdapter.onBidWon(bid); - } -} - -registerBidder(spec); diff --git a/modules/big-richmediaBidAdapter.md b/modules/big-richmediaBidAdapter.md deleted file mode 100644 index 26f77e527fb..00000000000 --- a/modules/big-richmediaBidAdapter.md +++ /dev/null @@ -1,82 +0,0 @@ -# Overview - -``` -Module Name: BI.Garage Rich Media -Module Type: Bidder Adapter -Maintainer: mediaconsortium-develop@bi.garage.co.jp -``` - -# Description - -Module which renders richmedia demand from a Xandr seat - -### Global configuration - -```javascript -pbjs.setConfig({ - debug: false, - // …, - bigRichmedia: { - publisherId: 'A7FN99NZ98F5ZD4G', // Required - }, -}); -``` - -# AdUnit Configuration -```javascript -var adUnits = [ - // Skin adUnit - { - code: 'banner-div', - mediaTypes: { - banner: { - sizes: [[300, 250], [300,600]] - } - }, - bids: [{ - bidder: 'big-richmedia', - params: { - placementId: 12345, - format: 'skin' // This will automatically add 1800x1000 size to banner mediaType - } - }] - }, - // Video outstream adUnit - { - code: 'video-outstream', - sizes: [[300, 250]], - mediaTypes: { - video: { - playerSize: [[300, 250]], - context: 'outstream', - // Certain ORTB 2.5 video values can be read from the mediatypes object; below are examples of supported params. - // To note - appnexus supports additional values for our system that are not part of the ORTB spec. If you want - // to use these values, they will have to be declared in the bids[].params.video object instead using the appnexus syntax. - // Between the corresponding values of the mediaTypes.video and params.video objects, the properties in params.video will - // take precedence if declared; eg in the example below, the `skippable: true` setting will be used instead of the `skip: 0`. - minduration: 1, - maxduration: 60, - skip: 0, // 1 - true, 0 - false - skipafter: 5, - playbackmethod: [2], // note - we only support options 1-4 at this time - api: [1,2,3] // note - option 6 is not supported at this time - } - }, - bids: [ - { - bidder: 'big-richmedia', - params: { - placementId: 12345, - video: { - skippable: true, - playback_method: 'auto_play_sound_off' - }, - format: 'video-sticky-footer', // or 'video-sticky-top' - isReplayable: true // Default to false - choose if the video should be replayable or not. - customSelector: '#nav-bar' // custom selector for navbar - } - } - ] - } -]; -``` diff --git a/modules/bizzclickBidAdapter.js b/modules/bizzclickBidAdapter.js index a798671cbaf..95c53b78de2 100644 --- a/modules/bizzclickBidAdapter.js +++ b/modules/bizzclickBidAdapter.js @@ -1,6 +1,6 @@ -import { logMessage, getDNT, deepSetValue, deepAccess, _map, logWarn } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; const BIDDER_CODE = 'bizzclick'; const ACCOUNTID_MACROS = '[account_id]'; @@ -67,7 +67,7 @@ export const spec = { winTop = window.top; } catch (e) { location = winTop.location; - logMessage(e); + utils.logMessage(e); }; let bids = []; for (let bidRequest of validBidRequests) { @@ -80,7 +80,7 @@ export const spec = { device: { w: winTop.screen.width, h: winTop.screen.height, - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, language: (navigator && navigator.language) ? navigator.language.indexOf('-') != -1 ? navigator.language.split('-')[0] : navigator.language : '', }, site: { @@ -88,10 +88,7 @@ export const spec = { host: location.host }, source: { - tid: bidRequest.transactionId, - ext: { - schain: {} - } + tid: bidRequest.transactionId }, regs: { coppa: config.getConfig('coppa') === true ? 1 : 0, @@ -107,22 +104,32 @@ export const spec = { imp: [impObject], }; + if (bidderRequest && bidderRequest.uspConsent) { + data.regs.ext.us_privacy = bidderRequest.uspConsent; + } + + if (bidderRequest && bidderRequest.gdprConsent) { + let { gdprApplies, consentString } = bidderRequest.gdprConsent; + data.regs.ext.gdpr = gdprApplies ? 1 : 0; + data.user.ext.consent = consentString; + } + + if (bidRequest.schain) { + data.source.ext.schain = bidRequest.schain; + } + let connection = navigator.connection || navigator.webkitConnection; if (connection && connection.effectiveType) { data.device.connectiontype = connection.effectiveType; } if (bidRequest) { - if (bidRequest.schain) { - deepSetValue(data, 'source.ext.schain', bidRequest.schain); - } - if (bidRequest.gdprConsent && bidRequest.gdprConsent.gdprApplies) { - deepSetValue(data, 'regs.ext.gdpr', bidRequest.gdprConsent.gdprApplies ? 1 : 0); - deepSetValue(data, 'user.ext.consent', bidRequest.gdprConsent.consentString); + utils.deepSetValue(data, 'regs.ext.gdpr', bidRequest.gdprConsent.gdprApplies ? 1 : 0); + utils.deepSetValue(data, 'user.ext.consent', bidRequest.gdprConsent.consentString); } if (bidRequest.uspConsent !== undefined) { - deepSetValue(data, 'regs.ext.us_privacy', bidRequest.uspConsent); + utils.deepSetValue(data, 'regs.ext.us_privacy', bidRequest.uspConsent); } } bids.push(data) @@ -187,7 +194,7 @@ export const spec = { * @returns {boolean} */ const checkRequestType = (bidRequest, type) => { - return (typeof deepAccess(bidRequest, `mediaTypes.${type}`) !== 'undefined'); + return (typeof utils.deepAccess(bidRequest, `mediaTypes.${type}`) !== 'undefined'); } const parseNative = admObject => { const { assets, link, imptrackers, jstracker } = admObject.native; @@ -233,7 +240,7 @@ const addNativeParameters = bidRequest => { id: bidRequest.transactionId, ver: NATIVE_VERSION, }; - const assets = _map(bidRequest.mediaTypes.native, (bidParams, key) => { + const assets = utils._map(bidRequest.mediaTypes.native, (bidParams, key) => { const props = NATIVE_PARAMS[key]; const asset = { required: bidParams.required & 1, @@ -279,7 +286,7 @@ const parseSizes = (bid, mediaType) => { mediaTypes.video.w, mediaTypes.video.h ]; - } else if (Array.isArray(deepAccess(bid, 'mediaTypes.video.playerSize')) && bid.mediaTypes.video.playerSize.length === 1) { + } else if (Array.isArray(utils.deepAccess(bid, 'mediaTypes.video.playerSize')) && bid.mediaTypes.video.playerSize.length === 1) { size = bid.mediaTypes.video.playerSize[0]; } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0 && Array.isArray(bid.sizes[0]) && bid.sizes[0].length > 1) { size = bid.sizes[0]; @@ -292,7 +299,7 @@ const parseSizes = (bid, mediaType) => { } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) { sizes = bid.sizes } else { - logWarn('no sizes are setup or found'); + utils.logWarn('no sizes are setup or found'); } return sizes } diff --git a/modules/bliinkBidAdapter.js b/modules/bliinkBidAdapter.js deleted file mode 100644 index 45b6c46c2df..00000000000 --- a/modules/bliinkBidAdapter.js +++ /dev/null @@ -1,336 +0,0 @@ -// eslint-disable-next-line prebid/validate-imports -// eslint-disable-next-line prebid/validate-imports -import {registerBidder} from '../src/adapters/bidderFactory.js' -export const BIDDER_CODE = 'bliink' -export const BLIINK_ENDPOINT_ENGINE = 'https://engine.bliink.io/delivery' -export const BLIINK_ENDPOINT_ENGINE_VAST = 'https://engine.bliink.io/vast' -export const BLIINK_ENDPOINT_COOKIE_SYNC = 'https://cookiesync.api.bliink.io' -export const META_KEYWORDS = 'keywords' -export const META_DESCRIPTION = 'description' - -const VIDEO = 'video' -const BANNER = 'banner' - -const supportedMediaTypes = [BANNER, VIDEO] -const aliasBidderCode = ['bk'] - -export function getMetaList(name) { - if (!name || name.length === 0) return [] - - return [ - { - key: 'name', - value: name, - }, - { - key: 'name*', - value: name, - }, - { - key: 'itemprop*', - value: name, - }, - { - key: 'property', - value: `'og:${name}'`, - }, - { - key: 'property', - value: `'twitter:${name}'`, - }, - { - key: 'property', - value: `'article:${name}'`, - }, - ] -} - -export function getOneMetaValue(query) { - const metaEl = document.querySelector(query) - - if (metaEl && metaEl.content) { - return metaEl.content - } - - return null -} - -export function getMetaValue(name) { - const metaList = getMetaList(name) - for (let i = 0; i < metaList.length; i++) { - const meta = metaList[i]; - const metaValue = getOneMetaValue(`meta[${meta.key}=${meta.value}]`); - if (metaValue) { - return metaValue - } - } - return '' -} - -export function getKeywords() { - const metaKeywords = getMetaValue(META_KEYWORDS) - if (metaKeywords) { - const keywords = [ - ...metaKeywords.split(','), - ] - - if (keywords && keywords.length > 0) { - return keywords - .filter((value) => value) - .map((value) => value.trim()) - } - } - - return [] -} - -export const parseXML = (content) => { - if (typeof content !== 'string' || content.length === 0) return null - - const parser = new DOMParser() - let xml; - - try { - xml = parser.parseFromString(content, 'text/xml') - } catch (e) {} - - if (xml && - xml.getElementsByTagName('VAST')[0] && - xml.getElementsByTagName('VAST')[0].tagName === 'VAST') { - return xml - } - - return null -} - -/** - * @param bidRequest - * @param bliinkCreative - * @return {{cpm, netRevenue: boolean, requestId, width: (*|number), currency, ttl: number, creativeId, height: (*|number)} & {mediaType: string, vastXml}} - */ -export const buildBid = (bidRequest, bliinkCreative) => { - if (!bidRequest && !bliinkCreative) return null - - const body = { - requestId: bidRequest.bidId, - currency: bliinkCreative.currency, - cpm: bliinkCreative.price, - creativeId: bliinkCreative.creativeId, - width: (bidRequest.sizes && bidRequest.sizes[0][0]) || 1, - height: (bidRequest.sizes && bidRequest.sizes[0][1]) || 1, - netRevenue: false, - ttl: 3600, - } - - // eslint-disable-next-line no-mixed-operators - if ((bliinkCreative) && bidRequest && - // eslint-disable-next-line no-mixed-operators - !bidRequest.bidId || - !bidRequest.sizes || - !bidRequest.params || - !(bidRequest.params.placement) - ) return null - - delete bidRequest['bids'] - - switch (bliinkCreative.media_type) { - case VIDEO: - return Object.assign(body, { - mediaType: VIDEO, - vastXml: bliinkCreative.content, - }) - case BANNER: - return Object.assign(body, { - mediaType: BANNER, - ad: (bliinkCreative && bliinkCreative.content && bliinkCreative.content.creative && bliinkCreative.content.creative.adm) || '', - }) - default: - break; - } -} - -/** - * @description Verify the the AdUnits.bids, respond with true (valid) or false (invalid). - * - * @param bid - * @return boolean - */ -export const isBidRequestValid = (bid) => { - return !(!bid || !bid.params || !bid.params.placement || !bid.params.tagId) -} - -/** - * @description Takes an array of valid bid requests, all of which are guaranteed to have passed the isBidRequestValid() test. - * - * @param _[] - * @param bidderRequest - * @return {{ method: string, url: string } | null} - */ -export const buildRequests = (_, bidderRequest) => { - if (!bidderRequest) return null - - let data = { - pageUrl: bidderRequest.refererInfo.referer, - pageDescription: getMetaValue(META_DESCRIPTION), - keywords: getKeywords().join(','), - gdpr: false, - gdpr_consent: '', - pageTitle: document.title, - } - - const endPoint = bidderRequest.bids[0].params.placement === VIDEO ? BLIINK_ENDPOINT_ENGINE_VAST : BLIINK_ENDPOINT_ENGINE - - const params = { - bidderRequestId: bidderRequest.bidderRequestId, - bidderCode: bidderRequest.bidderCode, - bids: bidderRequest.bids, - refererInfo: bidderRequest.refererInfo, - } - - if (bidderRequest.gdprConsent) { - data = Object.assign(data, { - gdpr: bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies, - gdpr_consent: bidderRequest.gdprConsent.consentString - }) - } - - if (bidderRequest.bids && bidderRequest.bids.length > 0 && bidderRequest.bids[0].sizes && bidderRequest.bids[0].sizes[0]) { - data = Object.assign(data, { - width: bidderRequest.bids[0].sizes[0][0], - height: bidderRequest.bids[0].sizes[0][1] - }) - - return { - method: 'GET', - url: `${endPoint}/${bidderRequest.bids[0].params.tagId}`, - data: data, - params: params, - } - } - - return null -} - -/** - * @description Parse the response (from buildRequests) and generate one or more bid objects. - * - * @param serverResponse - * @param request - * @return - */ -const interpretResponse = (serverResponse, request) => { - if ((serverResponse && serverResponse.mode === 'no-ad')) { - return [] - } - - const body = serverResponse.body - const serverBody = request.params - - const xml = parseXML(body) - - let creative; - - switch (serverBody.bids[0].params.placement) { - case xml && VIDEO: - const price = xml.getElementsByTagName('Price') && xml.getElementsByTagName('Price')[0] - const currency = xml.getElementsByTagName('Currency') && xml.getElementsByTagName('Currency')[0] - const creativeId = xml.getElementsByTagName('CreativeId') && xml.getElementsByTagName('CreativeId')[0] - - creative = { - content: body, - price: (price && price.textContent) || 0, - currency: (currency && currency.textContent) || 'EUR', - creativeId: creativeId || 0, - media_type: 'video', - } - - return buildBid(serverBody.bids[0], creative) - case BANNER: - if (body) { - creative = { - content: body, - price: body.price, - currency: body.currency, - creativeId: 0, - media_type: 'banner', - } - - return buildBid(serverBody.bids[0], creative) - } - - break - default: - break - } -} - -/** - * @description If the publisher allows user-sync activity, the platform will call this function and the adapter may register pixels and/or iframe user syncs. For more information, see Registering User Syncs below - * @param syncOptions - * @param serverResponses - * @param gdprConsent - * @return {[{type: string, url: string}]|*[]} - */ -const getUserSyncs = (syncOptions, serverResponses, gdprConsent) => { - let syncs = [] - - if (syncOptions.pixelEnabled && serverResponses.length > 0) { - if (gdprConsent) { - const gdprParams = `consentString=${gdprConsent.consentString}` - const smartCallbackURL = encodeURIComponent(`${BLIINK_ENDPOINT_COOKIE_SYNC}/cookiesync?partner=smart&uid=[sas_uid]`) - const azerionCallbackURL = encodeURIComponent(`${BLIINK_ENDPOINT_COOKIE_SYNC}/cookiesync?partner=azerion&uid={PUB_USER_ID}`) - const appnexusCallbackURL = encodeURIComponent(`${BLIINK_ENDPOINT_COOKIE_SYNC}/cookiesync?partner=azerion&uid=$UID`) - return [ - { - type: 'script', - url: 'https://prg.smartadserver.com/ac?out=js&nwid=3392&siteid=305791&pgname=rg&fmtid=81127&tgt=[sas_target]&visit=m&tmstp=[timestamp]&clcturl=[countgo]' - }, - { - type: 'image', - url: `https://sync.smartadserver.com/getuid?nwid=3392&${gdprParams}&url=${smartCallbackURL}`, - }, - { - type: 'image', - url: `https://ad.360yield.com/server_match?partner_id=1531&${gdprParams}&r=${azerionCallbackURL}`, - }, - { - type: 'image', - url: `https://ads.stickyadstv.com/auto-user-sync?${gdprParams}`, - }, - { - type: 'image', - url: `https://cookiesync.api.bliink.io/getuid?url=https%3A%2F%2Fvisitor.omnitagjs.com%2Fvisitor%2Fsync%3Fuid%3D1625272249969090bb9d544bd6d8d645%26name%3DBLIINK%26visitor%3D%24UID%26external%3Dtrue&${gdprParams}`, - }, - { - type: 'image', - url: `https://cookiesync.api.bliink.io/getuid?url=https://pixel.advertising.com/ups/58444/sync?&gdpr=1&gdpr_consent=${gdprConsent.consentString}&redir=true&uid=$UID`, - }, - { - type: 'image', - url: `https://ups.analytics.yahoo.com/ups/58499/occ?gdpr=1&gdpr_consent=${gdprConsent.consentString}`, - }, - { - type: 'image', - url: `https://secure.adnxs.com/getuid?${appnexusCallbackURL}`, - }, - ] - } - } - - return syncs; -} - -/** - * @type {{interpretResponse: interpretResponse, code: string, aliases: string[], getUserSyncs: getUserSyncs, buildRequests: buildRequests, onTimeout: onTimeout, onSetTargeting: onSetTargeting, isBidRequestValid: isBidRequestValid, onBidWon: onBidWon}} - */ -export const spec = { - code: BIDDER_CODE, - aliases: aliasBidderCode, - supportedMediaTypes: supportedMediaTypes, - isBidRequestValid, - buildRequests, - interpretResponse, - getUserSyncs, -} - -registerBidder(spec) diff --git a/modules/bliinkBidAdapter.md b/modules/bliinkBidAdapter.md deleted file mode 100644 index af7aee3a1ae..00000000000 --- a/modules/bliinkBidAdapter.md +++ /dev/null @@ -1,94 +0,0 @@ -# Overview - -``` -Module Name: BLIINK Bidder Adapter -Module Type: Bidder Adapter -Maintainer: samuel@bliink.io | jonathan@bliink.io -gdpr_supported: true -tcf2_supported: true -media_types: banner, native, video -``` - -# Description - -Module that connects to BLIINK demand sources to fetch bids. - -# Test Parameters - -## Sample Banner Ad Unit - -```js -const adUnits = [ - { - code: '/19968336/test', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - bids: [ - { - bidder: 'bliink', - params: { - placement: 'banner', - tagId: '41' - } - } - ] - } -] -``` - -## Sample Instream Video Ad Unit - -```js -const adUnits = [ - { - code: '/19968336/prebid_cache_video_adunit', - sizes: [[640,480]], - mediaType: 'video', - mediaTypes: { - video: { - context: 'instream', - playerSize: [[640,480]], - } - }, - bids: [ - { - bidder: 'bliink', - params: { - tagId: '41', - placement: 'video', - } - } - ] - } -] -``` - -## Sample outstream Video Ad Unit - -```js -const adUnits = [ - { - code: '/19968336/prebid_cache_video_adunit', - sizes: [[640,480]], - mediaType: 'video', - mediaTypes: { - video: { - context: 'outstream', - playerSize: [[640,480]], - } - }, - bids: [ - { - bidder: 'bliink', - params: { - tagId: '41', - placement: 'video', - } - } - ] - } -] -``` diff --git a/modules/bluebillywigBidAdapter.js b/modules/bluebillywigBidAdapter.js index d362dfa5fdb..3d4eeb058b3 100644 --- a/modules/bluebillywigBidAdapter.js +++ b/modules/bluebillywigBidAdapter.js @@ -1,10 +1,10 @@ -import {deepAccess, deepClone, deepSetValue, logError, logWarn} from '../src/utils.js'; -import {find} from '../src/polyfill.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {Renderer} from '../src/Renderer.js'; -import {createEidsArray} from './userId/eids.js'; +import * as utils from '../src/utils.js'; +import find from 'core-js-pure/features/array/find.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { VIDEO } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import { Renderer } from '../src/Renderer.js'; +import { createEidsArray } from './userId/eids.js'; const DEV_MODE = window.location.search.match(/bbpbs_debug=true/); @@ -43,7 +43,7 @@ const BB_HELPERS = { if (!request.device.h) request.device.h = window.innerHeight; }, addSchain: function(request, validBidRequests) { - const schain = deepAccess(validBidRequests, '0.schain'); + const schain = utils.deepAccess(validBidRequests, '0.schain'); if (schain) request.source.ext = { schain: schain }; }, addCurrency: function(request) { @@ -52,11 +52,11 @@ const BB_HELPERS = { else if (Array.isArray(adServerCur) && adServerCur.length) request.cur = [adServerCur[0]]; }, addUserIds: function(request, validBidRequests) { - const bidUserId = deepAccess(validBidRequests, '0.userId'); + const bidUserId = utils.deepAccess(validBidRequests, '0.userId'); const eids = createEidsArray(bidUserId); if (eids.length) { - deepSetValue(request, 'user.ext.eids', eids); + utils.deepSetValue(request, 'user.ext.eids', eids); } }, substituteUrl: function (url, publication, renderer) { @@ -72,7 +72,7 @@ const BB_HELPERS = { return BB_HELPERS.substituteUrl(BB_CONSTANTS.RENDERER_URL, publication, renderer); }, transformVideoParams: function(videoParams, videoParamsExt) { - videoParams = deepClone(videoParams); + videoParams = utils.deepClone(videoParams); let playerSize = videoParams.playerSize || [BB_CONSTANTS.DEFAULT_WIDTH, BB_CONSTANTS.DEFAULT_HEIGHT]; if (Array.isArray(playerSize[0])) playerSize = playerSize[0]; @@ -105,8 +105,8 @@ const BB_HELPERS = { ttl: BB_CONSTANTS.DEFAULT_TTL }; - const extPrebidTargeting = deepAccess(bid, 'ext.prebid.targeting'); - const extPrebidCache = deepAccess(bid, 'ext.prebid.cache'); + const extPrebidTargeting = utils.deepAccess(bid, 'ext.prebid.targeting'); + const extPrebidCache = utils.deepAccess(bid, 'ext.prebid.cache'); if (extPrebidCache && typeof extPrebidCache.vastXml === 'object' && extPrebidCache.vastXml.cacheId && extPrebidCache.vastXml.url) { bidObject.videoCacheKey = extPrebidCache.vastXml.cacheId; @@ -139,12 +139,12 @@ const BB_RENDERER = { else if (bid.vastUrl) config.vastUrl = bid.vastUrl; if (!bid.vastXml && !bid.vastUrl) { - logWarn(`${BB_CONSTANTS.BIDDER_CODE}: No vastXml or vastUrl on bid, bailing...`); + utils.logWarn(`${BB_CONSTANTS.BIDDER_CODE}: No vastXml or vastUrl on bid, bailing...`); return; } if (!(window.bluebillywig && window.bluebillywig.renderers)) { - logWarn(`${BB_CONSTANTS.BIDDER_CODE}: renderer code failed to initialize...`); + utils.logWarn(`${BB_CONSTANTS.BIDDER_CODE}: renderer code failed to initialize...`); return; } @@ -153,7 +153,7 @@ const BB_RENDERER = { const renderer = find(window.bluebillywig.renderers, r => r._id === rendererId); if (renderer) renderer.bootstrap(config, ele, bid.rendererSettings || {}); - else logWarn(`${BB_CONSTANTS.BIDDER_CODE}: Couldn't find a renderer with ${rendererId}`); + else utils.logWarn(`${BB_CONSTANTS.BIDDER_CODE}: Couldn't find a renderer with ${rendererId}`); }, newRenderer: function(rendererUrl, adUnitCode) { const renderer = Renderer.install({ @@ -165,7 +165,7 @@ const BB_RENDERER = { try { renderer.setRender(BB_RENDERER.outstreamRender); } catch (err) { - logWarn(`${BB_CONSTANTS.BIDDER_CODE}: Error tying to setRender on renderer`, err); + utils.logWarn(`${BB_CONSTANTS.BIDDER_CODE}: Error tying to setRender on renderer`, err); } return renderer; @@ -189,70 +189,70 @@ export const spec = { const rendererRegex = /^[\w+_]+$/; if (!bid.params) { - logError(`${BB_CONSTANTS.BIDDER_CODE}: no params set on bid. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: no params set on bid. Rejecting bid: `, bid); return false; } if (!bid.params.hasOwnProperty('publicationName') || typeof bid.params.publicationName !== 'string') { - logError(`${BB_CONSTANTS.BIDDER_CODE}: no publicationName specified in bid params, or it's not a string. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: no publicationName specified in bid params, or it's not a string. Rejecting bid: `, bid); return false; } else if (!publicationNameRegex.test(bid.params.publicationName)) { - logError(`${BB_CONSTANTS.BIDDER_CODE}: publicationName must be in format 'publication' or 'publication.environment'. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: publicationName must be in format 'publication' or 'publication.environment'. Rejecting bid: `, bid); return false; } if ((!bid.params.hasOwnProperty('rendererCode') || typeof bid.params.rendererCode !== 'string')) { - logError(`${BB_CONSTANTS.BIDDER_CODE}: no rendererCode was specified in bid params. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: no rendererCode was specified in bid params. Rejecting bid: `, bid); return false; } else if (!rendererRegex.test(bid.params.rendererCode)) { - logError(`${BB_CONSTANTS.BIDDER_CODE}: rendererCode must be alphanumeric, including underscores. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: rendererCode must be alphanumeric, including underscores. Rejecting bid: `, bid); return false; } if (!bid.params.accountId) { - logError(`${BB_CONSTANTS.BIDDER_CODE}: no accountId specified in bid params. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: no accountId specified in bid params. Rejecting bid: `, bid); return false; } if (bid.params.hasOwnProperty('connections')) { if (!Array.isArray(bid.params.connections)) { - logError(`${BB_CONSTANTS.BIDDER_CODE}: connections is not of type array. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: connections is not of type array. Rejecting bid: `, bid); return false; } else { for (let i = 0; i < bid.params.connections.length; i++) { if (!bid.params.hasOwnProperty(bid.params.connections[i])) { - logError(`${BB_CONSTANTS.BIDDER_CODE}: connection specified in params.connections, but not configured in params. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: connection specified in params.connections, but not configured in params. Rejecting bid: `, bid); return false; } } } } else { - logError(`${BB_CONSTANTS.BIDDER_CODE}: no connections specified in bid. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: no connections specified in bid. Rejecting bid: `, bid); return false; } if (bid.params.hasOwnProperty('video') && (bid.params.video === null || typeof bid.params.video !== 'object')) { - logError(`${BB_CONSTANTS.BIDDER_CODE}: params.video must be of type object. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: params.video must be of type object. Rejecting bid: `, bid); return false; } if (bid.params.hasOwnProperty('rendererSettings') && (bid.params.rendererSettings === null || typeof bid.params.rendererSettings !== 'object')) { - logError(`${BB_CONSTANTS.BIDDER_CODE}: params.rendererSettings must be of type object. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: params.rendererSettings must be of type object. Rejecting bid: `, bid); return false; } if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(VIDEO)) { if (!bid.mediaTypes[VIDEO].hasOwnProperty('context')) { - logError(`${BB_CONSTANTS.BIDDER_CODE}: no context specified in bid. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: no context specified in bid. Rejecting bid: `, bid); return false; } if (bid.mediaTypes[VIDEO].context !== 'outstream') { - logError(`${BB_CONSTANTS.BIDDER_CODE}: video.context is invalid, must be "outstream". Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: video.context is invalid, must be "outstream". Rejecting bid: `, bid); return false; } } else { - logError(`${BB_CONSTANTS.BIDDER_CODE}: mediaTypes or mediaTypes.video is not specified. Rejecting bid: `, bid); + utils.logError(`${BB_CONSTANTS.BIDDER_CODE}: mediaTypes or mediaTypes.video is not specified. Rejecting bid: `, bid); return false; } @@ -273,7 +273,7 @@ export const spec = { return extBuilder; }, {}); - const videoParams = BB_HELPERS.transformVideoParams(deepAccess(validBidRequest, 'mediaTypes.video'), deepAccess(validBidRequest, 'params.video')); + const videoParams = BB_HELPERS.transformVideoParams(utils.deepAccess(validBidRequest, 'mediaTypes.video'), utils.deepAccess(validBidRequest, 'params.video')); imps.push({ id: validBidRequest.bidId, ext, secure: window.location.protocol === 'https' ? 1 : 0, video: videoParams }); }); @@ -294,16 +294,16 @@ export const spec = { if (bidderRequest.gdprConsent) { let gdprApplies = 0; if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') gdprApplies = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; - deepSetValue(request, 'regs.ext.gdpr', gdprApplies); - deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(request, 'regs.ext.gdpr', gdprApplies); + utils.deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString); } if (bidderRequest.uspConsent) { - deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent); this.syncStore.uspConsent = bidderRequest.uspConsent; } - if (getConfig('coppa') == true) deepSetValue(request, 'regs.coppa', 1); + if (getConfig('coppa') == true) utils.deepSetValue(request, 'regs.coppa', 1); // Enrich the request with any external data we may have BB_HELPERS.addSiteAppDevice(request, bidderRequest.refererInfo && bidderRequest.refererInfo.referer); diff --git a/modules/boldwinBidAdapter.js b/modules/boldwinBidAdapter.js index fcff7134a92..66b4cbfd77b 100644 --- a/modules/boldwinBidAdapter.js +++ b/modules/boldwinBidAdapter.js @@ -1,6 +1,6 @@ -import { isFn, deepAccess, logMessage } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'boldwin'; const AD_URL = 'https://ssp.videowalldirect.com/pbjs'; @@ -24,8 +24,8 @@ function isBidResponseValid(bid) { } function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidfloor', 0); + if (!utils.isFn(bid.getFloor)) { + return utils.deepAccess(bid, 'params.bidfloor', 0); } try { @@ -56,7 +56,7 @@ export const spec = { winTop = window.top; } catch (e) { location = winTop.location; - logMessage(e); + utils.logMessage(e); }; let placements = []; let request = { diff --git a/modules/brandmetricsRtdProvider.js b/modules/brandmetricsRtdProvider.js deleted file mode 100644 index 60d3c98f15e..00000000000 --- a/modules/brandmetricsRtdProvider.js +++ /dev/null @@ -1,168 +0,0 @@ -/** - * This module adds brandmetrics provider to the real time data module - * The {@link module:modules/realTimeData} module is required - * The module will load load the brandmetrics script and set survey- targeting to ad units of specific bidders. - * @module modules/brandmetricsRtdProvider - * @requires module:modules/realTimeData - */ -import { config } from '../src/config.js' -import { submodule } from '../src/hook.js' -import { deepSetValue, mergeDeep, logError, deepAccess } from '../src/utils.js' -import {loadExternalScript} from '../src/adloader.js' -const MODULE_NAME = 'brandmetrics' -const MODULE_CODE = MODULE_NAME -const RECEIVED_EVENTS = [] -const GVL_ID = 422 -const TCF_PURPOSES = [1, 7] - -function init (config, userConsent) { - const hasConsent = checkConsent(userConsent) - - if (hasConsent) { - const moduleConfig = getMergedConfig(config) - initializeBrandmetrics(moduleConfig.params.scriptId) - } - return hasConsent -} - -/** - * Checks TCF and USP consents - * @param {Object} userConsent - * @returns {boolean} - */ -function checkConsent (userConsent) { - let consent = false - - if (userConsent && userConsent.gdpr && userConsent.gdpr.gdprApplies) { - const gdpr = userConsent.gdpr - - if (gdpr.vendorData) { - const vendor = gdpr.vendorData.vendor - const purpose = gdpr.vendorData.purpose - - let vendorConsent = false - if (vendor.consents) { - vendorConsent = vendor.consents[GVL_ID] - } - - if (vendor.legitimateInterests) { - vendorConsent = vendorConsent || vendor.legitimateInterests[GVL_ID] - } - - const purposes = TCF_PURPOSES.map(id => { - return (purpose.consents && purpose.consents[id]) || (purpose.legitimateInterests && purpose.legitimateInterests[id]) - }) - const purposesValid = purposes.filter(p => p === true).length === TCF_PURPOSES.length - consent = vendorConsent && purposesValid - } - } else if (userConsent.usp) { - const usp = userConsent.usp - consent = usp[1] !== 'N' && usp[2] !== 'Y' - } - - return consent -} - -/** -* Add event- listeners to hook in to brandmetrics events -* @param {Object} reqBidsConfigObj -* @param {function} callback -*/ -function processBrandmetricsEvents (reqBidsConfigObj, moduleConfig, callback) { - const callBidTargeting = (event) => { - if (event.available && event.conf) { - const targetingConf = event.conf.displayOption || {} - if (targetingConf.type === 'pbjs') { - setBidderTargeting(reqBidsConfigObj, moduleConfig, targetingConf.targetKey || 'brandmetrics_survey', event.survey.measurementId) - } - } - callback() - } - - if (RECEIVED_EVENTS.length > 0) { - callBidTargeting(RECEIVED_EVENTS[RECEIVED_EVENTS.length - 1]) - } else { - window._brandmetrics = window._brandmetrics || [] - window._brandmetrics.push({ - cmd: '_addeventlistener', - val: { - event: 'surveyloaded', - reEmitLast: true, - handler: (ev) => { - RECEIVED_EVENTS.push(ev) - if (RECEIVED_EVENTS.length === 1) { - // Call bid targeting only for the first received event, if called subsequently, last event from the RECEIVED_EVENTS array is used - callBidTargeting(ev) - } - }, - } - }) - } -} - -/** - * Sets bid targeting of specific bidders - * @param {Object} reqBidsConfigObj - * @param {string} key Targeting key - * @param {string} val Targeting value - */ -function setBidderTargeting (reqBidsConfigObj, moduleConfig, key, val) { - const bidders = deepAccess(moduleConfig, 'params.bidders') - if (bidders && bidders.length > 0) { - const ortb2 = {} - deepSetValue(ortb2, 'ortb2.user.ext.data.' + key, val) - config.setBidderConfig({ - bidders: bidders, - config: ortb2 - }) - } -} - -/** - * Add the brandmetrics script to the page. - * @param {string} scriptId - The script- id provided by brandmetrics or brandmetrics partner - */ -function initializeBrandmetrics(scriptId) { - if (scriptId) { - const path = 'https://cdn.brandmetrics.com/survey/script/' - const file = scriptId + '.js' - const url = path + file - - loadExternalScript(url, MODULE_CODE) - } -} - -/** - * Merges a provided config with default values - * @param {Object} customConfig - * @returns - */ -function getMergedConfig(customConfig) { - return mergeDeep({ - waitForIt: false, - params: { - bidders: [], - scriptId: undefined, - } - }, customConfig) -} - -/** @type {RtdSubmodule} */ -export const brandmetricsSubmodule = { - name: MODULE_NAME, - getBidRequestData: function (reqBidsConfigObj, callback, customConfig) { - try { - const moduleConfig = getMergedConfig(customConfig) - if (moduleConfig.waitForIt) { - processBrandmetricsEvents(reqBidsConfigObj, moduleConfig, callback) - } else { - callback() - } - } catch (e) { - logError(e) - } - }, - init: init -} - -submodule('realTimeData', brandmetricsSubmodule) diff --git a/modules/brandmetricsRtdProvider.md b/modules/brandmetricsRtdProvider.md deleted file mode 100644 index 89ee6bb75cf..00000000000 --- a/modules/brandmetricsRtdProvider.md +++ /dev/null @@ -1,40 +0,0 @@ -# Brandmetrics Real-time Data Submodule -This module is intended to be used by brandmetrics (https://brandmetrics.com) partners and sets targeting keywords to bids if the browser is eligeble to see a brandmetrics survey. -The module hooks in to brandmetrics events and requires a brandmetrics script to be running. The module can optionally load and initialize brandmetrics by providing the 'scriptId'- parameter. - -## Usage -Compile the Brandmetrics RTD module into your Prebid build: -``` -gulp build --modules=rtdModule,brandmetricsRtdProvider -``` - -> Note that the global RTD module, `rtdModule`, is a prerequisite of the Brandmetrics RTD module. - -Enable the Brandmetrics RTD in your Prebid configuration, using the below format: - -```javascript -pbjs.setConfig({ - ..., - realTimeData: { - auctionDelay: 500, // auction delay - dataProviders: [{ - name: 'brandmetrics', - waitForIt: true // should be true if there's an `auctionDelay`, - params: { - scriptId: '00000000-0000-0000-0000-000000000000', - bidders: ['ozone'] - } - }] - }, - ... -}) -``` - -## Parameters -| Name | Type | Description | Default | -| ----------------- | -------------------- | ------------------ | ------------------ | -| name | String | This should always be `brandmetrics` | - | -| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (recommended) | `false` | -| params | Object | | - | -| params.bidders | String[] | An array of bidders which should receive targeting keys. | `[]` | -| params.scriptId | String | A script- id GUID if the brandmetrics- script should be initialized. | `undefined` | diff --git a/modules/braveBidAdapter.js b/modules/braveBidAdapter.js index 18bad6b0f75..7ea3eb9cd9b 100644 --- a/modules/braveBidAdapter.js +++ b/modules/braveBidAdapter.js @@ -1,4 +1,4 @@ -import { parseUrl, isEmpty, isStr, triggerPixel } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; @@ -90,7 +90,7 @@ export const spec = { ua: navigator.userAgent, }, site: { - domain: parseUrl(page).hostname, + domain: utils.parseUrl(page).hostname, page: page, }, tmax: bidderRequest.timeout || config.getConfig('bidderTimeout') || 500, @@ -134,7 +134,7 @@ export const spec = { * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: (serverResponse) => { - if (!serverResponse || isEmpty(serverResponse.body)) return []; + if (!serverResponse || utils.isEmpty(serverResponse.body)) return []; let bids = []; serverResponse.body.seatbid.forEach(response => { @@ -173,8 +173,8 @@ export const spec = { }, onBidWon: (bid) => { - if (isStr(bid.nurl) && bid.nurl !== '') { - triggerPixel(bid.nurl); + if (utils.isStr(bid.nurl) && bid.nurl !== '') { + utils.triggerPixel(bid.nurl); } } }; diff --git a/modules/bridgewellBidAdapter.js b/modules/bridgewellBidAdapter.js index b141763af8e..2034a59242e 100644 --- a/modules/bridgewellBidAdapter.js +++ b/modules/bridgewellBidAdapter.js @@ -1,7 +1,7 @@ -import {_each, deepSetValue, inIframe} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE} from '../src/mediaTypes.js'; -import {find} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE } from '../src/mediaTypes.js'; +import find from 'core-js-pure/features/array/find.js'; const BIDDER_CODE = 'bridgewell'; const REQUEST_ENDPOINT = 'https://prebid.scupio.com/recweb/prebid.aspx?cb='; @@ -40,7 +40,7 @@ export const spec = { var bidderUrl = REQUEST_ENDPOINT + Math.random(); var userIds; - _each(validBidRequests, function (bid) { + utils._each(validBidRequests, function (bid) { userIds = bid.userId; if (bid.params.cid) { @@ -83,7 +83,7 @@ export const spec = { prebid: '$prebid.version$', bridgewell: BIDDER_VERSION }, - inIframe: inIframe(), + inIframe: utils.inIframe(), url: topUrl, referrer: getTopWindowReferrer(), adUnits: adUnits, @@ -104,7 +104,7 @@ export const spec = { const bidResponses = []; // map responses to requests - _each(bidRequest.validBidRequests, function (req) { + utils._each(bidRequest.validBidRequests, function (req) { const bidResponse = {}; if (!serverResponse.body) { @@ -168,7 +168,7 @@ export const spec = { bidResponse.mediaType = matchedResponse.mediaType; if (matchedResponse.adomain) { - deepSetValue(bidResponse, 'meta.advertiserDomains', Array.isArray(matchedResponse.adomain) ? matchedResponse.adomain : [matchedResponse.adomain]); + utils.deepSetValue(bidResponse, 'meta.advertiserDomains', Array.isArray(matchedResponse.adomain) ? matchedResponse.adomain : [matchedResponse.adomain]); } // check required parameters by matchedResponse.mediaType diff --git a/modules/brightMountainMediaBidAdapter.js b/modules/brightMountainMediaBidAdapter.js index d3ae1d9cf43..602e621632c 100644 --- a/modules/brightMountainMediaBidAdapter.js +++ b/modules/brightMountainMediaBidAdapter.js @@ -1,6 +1,6 @@ -import { generateUUID, deepAccess, logWarn, deepSetValue } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; const BIDDER_CODE = 'bmtm'; @@ -38,7 +38,7 @@ export const spec = { }; validBidRequests.forEach((bid) => { - oRTBRequest['id'] = generateUUID(); + oRTBRequest['id'] = utils.generateUUID(); oRTBRequest['imp'] = [ { id: '1', @@ -52,7 +52,7 @@ export const spec = { }, ]; - if (deepAccess(bid, 'mediaTypes.banner')) { + if (utils.deepAccess(bid, 'mediaTypes.banner')) { if (bid.mediaTypes.banner.sizes) { size = bid.mediaTypes.banner.sizes[0]; } @@ -106,7 +106,7 @@ export const spec = { } if (!response || !bid || !bid.adm || !bid.price) { - logWarn(`Bidder ${spec.code} no valid bid`); + utils.logWarn(`Bidder ${spec.code} no valid bid`); return []; } @@ -117,7 +117,7 @@ export const spec = { width: bid.w, height: bid.h, creativeId: bid.crid, - mediaType: deepAccess(bidRequest, 'mediaTypes.banner') ? BANNER : VIDEO, + mediaType: utils.deepAccess(bidRequest, 'mediaTypes.banner') ? BANNER : VIDEO, ttl: 3000, netRevenue: true, meta: { @@ -157,12 +157,12 @@ function buildSite(bidderRequest) { }; if (bidderRequest && bidderRequest.refererInfo) { - deepSetValue( + utils.deepSetValue( site, 'page', bidderRequest.refererInfo.referer.href ? bidderRequest.refererInfo.referer.href : '', ); - deepSetValue( + utils.deepSetValue( site, 'ref', bidderRequest.refererInfo.referer ? bidderRequest.refererInfo.referer : '', @@ -189,12 +189,12 @@ function buildRegs(bidderRequest) { }; if (bidderRequest && bidderRequest.gdprConsent) { - deepSetValue( + utils.deepSetValue( regs, 'ext.gdpr', bidderRequest.gdprConsent.gdprApplies ? 1 : 0, ); - deepSetValue( + utils.deepSetValue( regs, 'ext.gdprConsentString', bidderRequest.gdprConsent.consentString || 'ALL', @@ -202,7 +202,7 @@ function buildRegs(bidderRequest) { } if (bidderRequest && bidderRequest.uspConsent) { - deepSetValue(regs, + utils.deepSetValue(regs, 'ext.us_privacy', bidderRequest.uspConsent); } diff --git a/modules/brightcomBidAdapter.js b/modules/brightcomBidAdapter.js index 4895f303973..8299a2331cb 100644 --- a/modules/brightcomBidAdapter.js +++ b/modules/brightcomBidAdapter.js @@ -1,4 +1,4 @@ -import { getBidIdParameter, _each, isArray, getWindowTop, getUniqueIdentifierStr, parseUrl, deepSetValue, logError, logWarn, createTrackPixelHtml, getWindowSelf, isFn, isPlainObject } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; @@ -22,17 +22,17 @@ function buildRequests(bidReqs, bidderRequest) { referrer = bidderRequest.refererInfo.referer; } const brightcomImps = []; - const publisherId = getBidIdParameter('publisherId', bidReqs[0].params); - _each(bidReqs, function (bid) { + const publisherId = utils.getBidIdParameter('publisherId', bidReqs[0].params); + utils._each(bidReqs, function (bid) { let bidSizes = (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) || bid.sizes; - bidSizes = ((isArray(bidSizes) && isArray(bidSizes[0])) ? bidSizes : [bidSizes]); - bidSizes = bidSizes.filter(size => isArray(size)); + bidSizes = ((utils.isArray(bidSizes) && utils.isArray(bidSizes[0])) ? bidSizes : [bidSizes]); + bidSizes = bidSizes.filter(size => utils.isArray(size)); const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); const element = document.getElementById(bid.adUnitCode); const minSize = _getMinSize(processedSizes); const viewabilityAmount = _isViewabilityMeasurable(element) - ? _getViewability(element, getWindowTop(), minSize) + ? _getViewability(element, utils.getWindowTop(), minSize) : 'na'; const viewabilityAmountRounded = isNaN(viewabilityAmount) ? viewabilityAmount : Math.round(viewabilityAmount); @@ -53,10 +53,10 @@ function buildRequests(bidReqs, bidderRequest) { brightcomImps.push(imp); }); const brightcomBidReq = { - id: getUniqueIdentifierStr(), + id: utils.getUniqueIdentifierStr(), imp: brightcomImps, site: { - domain: parseUrl(referrer).host, + domain: utils.parseUrl(referrer).host, page: referrer, publisher: { id: publisherId @@ -71,8 +71,8 @@ function buildRequests(bidReqs, bidderRequest) { }; if (bidderRequest && bidderRequest.gdprConsent) { - deepSetValue(brightcomBidReq, 'regs.ext.gdpr', +bidderRequest.gdprConsent.gdprApplies); - deepSetValue(brightcomBidReq, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(brightcomBidReq, 'regs.ext.gdpr', +bidderRequest.gdprConsent.gdprApplies); + utils.deepSetValue(brightcomBidReq, 'user.ext.consent', bidderRequest.gdprConsent.consentString); } return { @@ -82,7 +82,7 @@ function buildRequests(bidReqs, bidderRequest) { options: {contentType: 'text/plain', withCredentials: false} }; } catch (e) { - logError(e, {bidReqs, bidderRequest}); + utils.logError(e, {bidReqs, bidderRequest}); } } @@ -100,7 +100,7 @@ function isBidRequestValid(bid) { function interpretResponse(serverResponse) { if (!serverResponse.body || typeof serverResponse.body != 'object') { - logWarn('Brightcom server returned empty/non-json response: ' + JSON.stringify(serverResponse.body)); + utils.logWarn('Brightcom server returned empty/non-json response: ' + JSON.stringify(serverResponse.body)); return []; } const { body: {id, seatbid} } = serverResponse; @@ -131,7 +131,7 @@ function interpretResponse(serverResponse) { } return brightcomBidResponses; } catch (e) { - logError(e, {id, seatbid}); + utils.logError(e, {id, seatbid}); } } @@ -155,7 +155,7 @@ function _getDeviceType() { function _getAdMarkup(bid) { let adm = bid.adm; if ('nurl' in bid) { - adm += createTrackPixelHtml(bid.nurl); + adm += utils.createTrackPixelHtml(bid.nurl); } return adm; } @@ -165,14 +165,14 @@ function _isViewabilityMeasurable(element) { } function _getViewability(element, topWin, { w, h } = {}) { - return getWindowTop().document.visibilityState === 'visible' + return utils.getWindowTop().document.visibilityState === 'visible' ? _getPercentInView(element, topWin, { w, h }) : 0; } function _isIframe() { try { - return getWindowSelf() !== getWindowTop(); + return utils.getWindowSelf() !== utils.getWindowTop(); } catch (e) { return true; } @@ -252,7 +252,7 @@ function _getPercentInView(element, topWin, { w, h } = {}) { } function _getBidFloor(bid) { - if (!isFn(bid.getFloor)) { + if (!utils.isFn(bid.getFloor)) { return bid.params.bidFloor ? bid.params.bidFloor : null; } @@ -261,7 +261,7 @@ function _getBidFloor(bid) { mediaType: '*', size: '*' }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { + if (utils.isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { return floor.floor; } return null; diff --git a/modules/britepoolIdSystem.js b/modules/britepoolIdSystem.js index 2316fbb732d..3bf416957d2 100644 --- a/modules/britepoolIdSystem.js +++ b/modules/britepoolIdSystem.js @@ -5,7 +5,7 @@ * @requires module:modules/userId */ -import { isEmpty, triggerPixel, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js' import {ajax} from '../src/ajax.js'; import {submodule} from '../src/hook.js'; const PIXEL = 'https://px.britepool.com/new?partner_id=t'; @@ -47,14 +47,14 @@ export const britepoolIdSubmodule = { }; } } - if (isEmpty(params)) { - triggerPixel(PIXEL); + if (utils.isEmpty(params)) { + utils.triggerPixel(PIXEL); } // Return for async operation return { callback: function(callback) { if (errors.length > 0) { - errors.forEach(error => logError(error)); + errors.forEach(error => utils.logError(error)); callback(); return; } @@ -65,7 +65,7 @@ export const britepoolIdSubmodule = { callback(britepoolIdSubmodule.normalizeValue(response)); }); } catch (error) { - if (error !== '') logError(error); + if (error !== '') utils.logError(error); callback(); } } else { @@ -75,7 +75,7 @@ export const britepoolIdSubmodule = { callback(responseObj ? { primaryBPID: responseObj.primaryBPID } : null); }, error: error => { - if (error !== '') logError(error); + if (error !== '') utils.logError(error); callback(); } }, JSON.stringify(params), { customHeaders: headers, contentType: 'application/json', method: 'POST', withCredentials: true }); @@ -132,7 +132,7 @@ export const britepoolIdSubmodule = { try { valueObj = JSON.parse(value); } catch (error) { - logError(error); + utils.logError(error); } } return valueObj; diff --git a/modules/browsiRtdProvider.js b/modules/browsiRtdProvider.js index 15f2d58010d..4ee338e94cc 100644 --- a/modules/browsiRtdProvider.js +++ b/modules/browsiRtdProvider.js @@ -15,28 +15,21 @@ * @property {?string} keyName */ -import {deepClone, deepSetValue, isFn, isGptPubadsDefined, isNumber, logError, logInfo, generateUUID} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {submodule} from '../src/hook.js'; import {ajaxBuilder} from '../src/ajax.js'; import {loadExternalScript} from '../src/adloader.js'; import {getStorageManager} from '../src/storageManager.js'; -import {find, includes} from '../src/polyfill.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import * as events from '../src/events.js'; -import CONSTANTS from '../src/constants.json'; +import find from 'core-js-pure/features/array/find.js'; const storage = getStorageManager(); /** @type {ModuleParams} */ let _moduleParams = {}; /** @type {null|Object} */ -let _browsiData = null; +let _predictionsData = null; /** @type {string} */ const DEF_KEYNAME = 'browsiViewability'; -/** @type {null | function} */ -let _dataReadyCallback = null; -/** @type {null|Object} */ -let _ic = {}; /** * add browsi script to page @@ -50,7 +43,7 @@ export function addBrowsiTag(data) { script.setAttribute('prebidbpt', 'true'); script.setAttribute('id', 'browsi-tag'); script.setAttribute('src', data.u); - script.prebidData = deepClone(data); + script.prebidData = utils.deepClone(data); if (_moduleParams.keyName) { script.prebidData.kn = _moduleParams.keyName; } @@ -68,7 +61,7 @@ export function collectData() { try { browsiData = storage.getDataFromLocalStorage('__brtd'); } catch (e) { - logError('unable to parse __brtd'); + utils.logError('unable to parse __brtd'); } let predictorData = { @@ -85,50 +78,29 @@ export function collectData() { getPredictionsFromServer(`//${_moduleParams.url}/prebid?${toUrlParams(predictorData)}`); } -/** - * wait for data from server - * call callback when data is ready - * @param {function} callback - */ -function waitForData(callback) { - if (_browsiData) { - _dataReadyCallback = null; - callback(_browsiData); - } else { - _dataReadyCallback = callback; - } -} - export function setData(data) { - _browsiData = data; - if (isFn(_dataReadyCallback)) { - _dataReadyCallback(_browsiData); - _dataReadyCallback = null; - } + _predictionsData = data; } -function getRTD(auc) { - logInfo(`Browsi RTD provider is fetching data for ${auc}`); +function sendDataToModule(adUnitsCodes) { try { - const _bp = (_browsiData && _browsiData.p) || {}; - return auc.reduce((rp, uc) => { - _ic[uc] = _ic[uc] || 0; - const _c = _ic[uc]; - if (!uc) { + const _predictions = (_predictionsData && _predictionsData.p) || {}; + return adUnitsCodes.reduce((rp, adUnitCode) => { + if (!adUnitCode) { return rp } - const adSlot = getSlotByCode(uc); - const identifier = adSlot ? getMacroId(_browsiData['pmd'], adSlot) : uc; - const _pd = _bp[identifier]; - rp[uc] = getKVObject(-1); - if (!_pd) { + const adSlot = getSlotByCode(adUnitCode); + const identifier = adSlot ? getMacroId(_predictionsData['pmd'], adSlot) : adUnitCode; + const predictionData = _predictions[identifier]; + rp[adUnitCode] = getKVObject(-1, _predictionsData['kn']); + if (!predictionData) { return rp } - if (_pd.ps) { - if (!isIdMatchingAdUnit(adSlot, _pd.w)) { + if (predictionData.p) { + if (!isIdMatchingAdUnit(adSlot, predictionData.w)) { return rp; } - rp[uc] = getKVObject(getCurrentData(_pd.ps, _c)); + rp[adUnitCode] = getKVObject(predictionData.p, _predictionsData.kn); } return rp; }, {}); @@ -137,37 +109,12 @@ function getRTD(auc) { } } -/** - * get prediction - * return -1 if prediction not found - * @param {object} predictionObject - * @param {number} _c - * @return {number} - */ -export function getCurrentData(predictionObject, _c) { - if (!predictionObject || !isNumber(_c)) { - return -1; - } - if (isNumber(predictionObject[_c])) { - return predictionObject[_c]; - } - if (Object.keys(predictionObject).length > 1) { - while (_c > 0) { - _c--; - if (isNumber(predictionObject[_c])) { - return predictionObject[_c]; - } - } - } - return -1; -} - /** * get all slots on page * @return {Object[]} slot GoogleTag slots */ function getAllSlots() { - return isGptPubadsDefined() && window.googletag.pubads().getSlots(); + return utils.isGptPubadsDefined() && window.googletag.pubads().getSlots(); } /** * get prediction and return valid object for key value set @@ -175,16 +122,12 @@ function getAllSlots() { * @param {string?} keyName * @return {Object} key:value */ -function getKVObject(p) { +function getKVObject(p, keyName) { const prValue = p < 0 ? 'NA' : (Math.floor(p * 10) / 10).toFixed(2); let prObject = {}; - prObject[getKey()] = prValue.toString(); + prObject[((_moduleParams['keyName'] || keyName || DEF_KEYNAME).toString())] = prValue.toString(); return prObject; } - -function getKey() { - return ((_moduleParams['keyName'] || (_browsiData && _browsiData['kn']) || DEF_KEYNAME).toString()) -} /** * check if placement id matches one of given ad units * @param {Object} slot google slot @@ -226,7 +169,7 @@ export function getMacroId(macro, slot) { }); return macroResult; } catch (e) { - logError(`failed to evaluate: ${macro}`); + utils.logError(`failed to evaluate: ${macro}`); } } return slot.getSlotElementId(); @@ -268,7 +211,7 @@ function getPredictionsFromServer(url) { } addBrowsiTag(data); } catch (err) { - logError('unable to parse data'); + utils.logError('unable to parse data'); setData({}) } } else if (req.status === 204) { @@ -278,7 +221,7 @@ function getPredictionsFromServer(url) { }, error: function () { setData({}); - logError('unable to get prediction data'); + utils.logError('unable to get prediction data'); } } ); @@ -295,28 +238,6 @@ function toUrlParams(data) { .join('&'); } -function setBidRequestsData(bidObj, callback) { - let adUnitCodes = bidObj.adUnitCodes; - let adUnits = bidObj.adUnits || getGlobal().adUnits || []; - if (adUnitCodes) { - adUnits = adUnits.filter(au => includes(adUnitCodes, au.code)); - } else { - adUnitCodes = adUnits.map(au => au.code); - } - waitForData(() => { - const data = getRTD(adUnitCodes); - if (data) { - adUnits.forEach(adUnit => { - const adUnitCode = adUnit.code; - if (data[adUnitCode]) { - deepSetValue(adUnit, 'ortb2Imp.ext.data.browsi', {[getKey()]: data[adUnitCode][getKey()]}); - } - }); - } - callback(); - }) -} - /** @type {RtdSubmodule} */ export const browsiSubmodule = { /** @@ -329,37 +250,16 @@ export const browsiSubmodule = { * @function * @param {string[]} adUnitsCodes */ - getTargetingData: getTargetingData, + getTargetingData: sendDataToModule, init: init, - getBidRequestData: setBidRequestsData }; -function getTargetingData(uc, c, us, a) { - const targetingData = getRTD(uc); - const auctionId = a.auctionId - uc.forEach(auc => { - if (isNumber(_ic[auc])) { - _ic[auc] = _ic[auc] + 1; - } - const transactionId = a.adUnits.find(adUnit => adUnit.code === auc).transactionId; - events.emit(CONSTANTS.EVENTS.BILLABLE_EVENT, { - vendor: 'browsi', - type: 'adRequest', - billingId: generateUUID(), - transactionId: transactionId, - auctionId: auctionId - }) - }); - logInfo('Browsi RTD provider returned targeting data', targetingData, 'for', uc) - return targetingData; -} - function init(moduleConfig) { _moduleParams = moduleConfig.params; if (_moduleParams && _moduleParams.siteKey && _moduleParams.pubKey && _moduleParams.url) { collectData(); } else { - logError('missing params for Browsi provider'); + utils.logError('missing params for Browsi provider'); } return true; } diff --git a/modules/bucksenseBidAdapter.js b/modules/bucksenseBidAdapter.js index fcf99179993..46d0dfe3590 100644 --- a/modules/bucksenseBidAdapter.js +++ b/modules/bucksenseBidAdapter.js @@ -1,6 +1,6 @@ -import { logInfo } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; const WHO = 'BKSHBID-005'; const BIDDER_CODE = 'bucksense'; @@ -17,7 +17,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - logInfo(WHO + ' isBidRequestValid() - INPUT bid:', bid); + utils.logInfo(WHO + ' isBidRequestValid() - INPUT bid:', bid); if (bid.bidder !== BIDDER_CODE || typeof bid.params === 'undefined') { return false; } @@ -34,7 +34,7 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function (validBidRequests, bidderRequest) { - logInfo(WHO + ' buildRequests() - INPUT validBidRequests:', validBidRequests, 'INPUT bidderRequest:', bidderRequest); + utils.logInfo(WHO + ' buildRequests() - INPUT validBidRequests:', validBidRequests, 'INPUT bidderRequest:', bidderRequest); let requests = []; const len = validBidRequests.length; for (let i = 0; i < len; i++) { @@ -64,7 +64,7 @@ export const spec = { data: sendData }); } - logInfo(WHO + ' buildRequests() - requests:', requests); + utils.logInfo(WHO + ' buildRequests() - requests:', requests); return requests; }, @@ -75,7 +75,7 @@ export const spec = { * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: function (serverResponse, request) { - logInfo(WHO + ' interpretResponse() - INPUT serverResponse:', serverResponse, 'INPUT request:', request); + utils.logInfo(WHO + ' interpretResponse() - INPUT serverResponse:', serverResponse, 'INPUT request:', request); const bidResponses = []; if (serverResponse.body) { @@ -93,12 +93,12 @@ export const spec = { var sAdomains = oResponse.adomains || []; if (request && sRequestID.length == 0) { - logInfo(WHO + ' interpretResponse() - use RequestID from Placments'); + utils.logInfo(WHO + ' interpretResponse() - use RequestID from Placments'); sRequestID = request.data.bid_id || ''; } if (request && request.data.params.hasOwnProperty('testcpm')) { - logInfo(WHO + ' interpretResponse() - use Test CPM '); + utils.logInfo(WHO + ' interpretResponse() - use Test CPM '); nCPM = request.data.params.testcpm; } @@ -118,9 +118,9 @@ export const spec = { }; bidResponses.push(bidResponse); } else { - logInfo(WHO + ' interpretResponse() - serverResponse not valid'); + utils.logInfo(WHO + ' interpretResponse() - serverResponse not valid'); } - logInfo(WHO + ' interpretResponse() - return', bidResponses); + utils.logInfo(WHO + ' interpretResponse() - return', bidResponses); return bidResponses; }, diff --git a/modules/buzzoolaBidAdapter.js b/modules/buzzoolaBidAdapter.js index c6e27c94e04..db4863f7503 100644 --- a/modules/buzzoolaBidAdapter.js +++ b/modules/buzzoolaBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, deepClone } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js'; import {Renderer} from '../src/Renderer.js'; @@ -62,8 +62,8 @@ export const spec = { return response.map(bid => { let requestBid = requestBids[bid.requestId]; - let context = deepAccess(requestBid, 'mediaTypes.video.context'); - let validBid = deepClone(bid); + let context = utils.deepAccess(requestBid, 'mediaTypes.video.context'); + let validBid = utils.deepClone(bid); if (validBid.mediaType === VIDEO && context === OUTSTREAM) { let renderer = Renderer.install({ @@ -88,7 +88,7 @@ export const spec = { */ function setOutstreamRenderer(bid) { let adData = JSON.parse(bid.ad); - let unitSettings = deepAccess(adData, 'placement.unit_settings'); + let unitSettings = utils.deepAccess(adData, 'placement.unit_settings'); let extendedSettings = { width: '' + bid.width, height: '' + bid.height, diff --git a/modules/byDataAnalyticsAdapter.js b/modules/byDataAnalyticsAdapter.js deleted file mode 100644 index ef6e1a503ee..00000000000 --- a/modules/byDataAnalyticsAdapter.js +++ /dev/null @@ -1,311 +0,0 @@ -import { deepClone, logInfo, logError } from '../src/utils.js'; -import Base64 from 'crypto-js/enc-base64'; -import hmacSHA512 from 'crypto-js/hmac-sha512'; -import enc from 'crypto-js/enc-utf8'; -import adapter from '../src/AnalyticsAdapter.js'; -import CONSTANTS from '../src/constants.json'; -import adapterManager from '../src/adapterManager.js'; -import { ajax } from '../src/ajax.js'; - -const secretKey = 'bydata@123456'; -const { EVENTS: { NO_BID, BID_TIMEOUT, AUCTION_END } } = CONSTANTS; -const DEFAULT_EVENT_URL = 'https://pbjs-stream.bydata.com/topics/prebid'; -const analyticsType = 'endpoint'; -var payload = {}; -var bdNbTo = { 'to': [], 'nb': [] }; -let initOptions = {}; - -function onBidTimeout(t) { - if (payload['visitor_data'] && t && t.length > 0) { - bdNbTo['to'] = t; - } -} - -function onNoBidData(t) { - if (payload['visitor_data'] && t) { - bdNbTo['nb'].push(t); - } -} - -function onAuctionEnd(t) { - _logInfo('onAuctionEnd', t); - const {isCorrectOption, logFrequency} = initOptions; - var value = Math.floor(Math.random() * 10000 + 1); - _logInfo(' value - frequency ', (value + '-' + logFrequency)); - setTimeout(() => { - if (isCorrectOption && value < logFrequency) { - ascAdapter.dataProcess(t); - addKeyForPrebidWinningAndWinningsBids(); - ascAdapter.sendPayload(); - } - }, 500); -} - -const ascAdapter = Object.assign(adapter({ url: DEFAULT_EVENT_URL, analyticsType: analyticsType }), { - track({ eventType, args }) { - switch (eventType) { - case NO_BID: - onNoBidData(args); - break; - case BID_TIMEOUT: - onBidTimeout(args); - break; - case AUCTION_END: - onAuctionEnd(args); - break; - default: - break; - } - } -}); - -// save the base class function -ascAdapter.originEnableAnalytics = ascAdapter.enableAnalytics; -// override enableAnalytics so we can get access to the config passed in from the page -ascAdapter.enableAnalytics = function(config) { - if (this.initConfig(config)) { - _logInfo('initiated:', initOptions); - initOptions.isCorrectOption && ascAdapter.getVisitorData(); - ascAdapter.originEnableAnalytics(config); - } -}; - -ascAdapter.initConfig = function (config) { - let isCorrectOption = true; - initOptions = {}; - _logInfo('initConfig', config); - initOptions.options = deepClone(config.options); - initOptions.clientId = initOptions.options.clientId || null; - initOptions.logFrequency = initOptions.options.logFrequency; - if (!initOptions.clientId) { - _logError('"options.clientId" should not empty!!'); - isCorrectOption = false; - } - initOptions.isCorrectOption = isCorrectOption; - this.initOptions = initOptions; - return isCorrectOption; -}; - -ascAdapter.getVisitorData = function(data = {}) { - var ua = data.userId ? data : {}; - var module = { - options: [], - header: [window.navigator.platform, window.navigator.userAgent, window.navigator.appVersion, window.navigator.vendor, window.opera], - dataos: [ - { name: 'Windows Phone', value: 'Windows Phone', version: 'OS' }, - { name: 'Windows', value: 'Win', version: 'NT' }, - { name: 'iPhone', value: 'iPhone', version: 'OS' }, - { name: 'iPad', value: 'iPad', version: 'OS' }, - { name: 'Kindle', value: 'Silk', version: 'Silk' }, - { name: 'Android', value: 'Android', version: 'Android' }, - { name: 'PlayBook', value: 'PlayBook', version: 'OS' }, - { name: 'BlackBerry', value: 'BlackBerry', version: '/' }, - { name: 'Macintosh', value: 'Mac', version: 'OS X' }, - { name: 'Linux', value: 'Linux', version: 'rv' }, - { name: 'Palm', value: 'Palm', version: 'PalmOS' } - ], - databrowser: [ - { name: 'Chrome', value: 'Chrome', version: 'Chrome' }, - { name: 'Firefox', value: 'Firefox', version: 'Firefox' }, - { name: 'Safari', value: 'Safari', version: 'Version' }, - { name: 'Internet Explorer', value: 'MSIE', version: 'MSIE' }, - { name: 'Opera', value: 'Opera', version: 'Opera' }, - { name: 'BlackBerry', value: 'CLDC', version: 'CLDC' }, - { name: 'Mozilla', value: 'Mozilla', version: 'Mozilla' } - ], - init: function () { var agent = this.header.join(' '); var os = this.matchItem(agent, this.dataos); var browser = this.matchItem(agent, this.databrowser); return { os: os, browser: browser }; }, - matchItem: function (string, data) { - var i = 0; var j = 0; var regex; var regexv; var match; var matches; var version; - for (i = 0; i < data.length; i += 1) { - regex = new RegExp(data[i].value, 'i'); - match = regex.test(string); - if (match) { - regexv = new RegExp(data[i].version + '[- /:;]([\\d._]+)', 'i'); - matches = string.match(regexv); - version = ''; - if (matches) { if (matches[1]) { matches = matches[1]; } } - if (matches) { - matches = matches.split(/[._]+/); - for (j = 0; j < matches.length; j += 1) { - if (j === 0) { - version += matches[j] + '.'; - } else { - version += matches[j]; - } - } - } else { - version = '0'; - } - return { - name: data[i].name, - version: parseFloat(version) - }; - } - } - return { name: 'unknown', version: 0 }; - } - }; - - function generateUid() { - try { - var buffer = new Uint8Array(16); - crypto.getRandomValues(buffer); - buffer[6] = (buffer[6] & ~176) | 64; - buffer[8] = (buffer[8] & ~64) | 128; - var hex = Array.prototype.map.call(new Uint8Array(buffer), function(x) { - return ('00' + x.toString(16)).slice(-2); - }).join(''); - return hex.slice(0, 5) + '-' + hex.slice(5, 9) + '-' + hex.slice(9, 13) + '-' + hex.slice(13, 18); - } catch (e) { - return ''; - } - } - function base64url(source) { - var encodedSource = Base64.stringify(source); - encodedSource = encodedSource.replace(/=+$/, ''); - encodedSource = encodedSource.replace(/\+/g, '-'); - encodedSource = encodedSource.replace(/\//g, '_'); - return encodedSource; - } - function getJWToken(data) { - var header = { - 'alg': 'HS256', - 'typ': 'JWT' - }; - var stringifiedHeader = enc.parse(JSON.stringify(header)); - var encodedHeader = base64url(stringifiedHeader); - var stringifiedData = enc.parse(JSON.stringify(data)); - var encodedData = base64url(stringifiedData); - var token = encodedHeader + '.' + encodedData; - var signature = hmacSHA512(token, secretKey); - signature = base64url(signature); - var signedToken = token + '.' + signature; - return signedToken; - } - const {clientId} = initOptions; - var userId = window.localStorage.getItem('userId'); - if (!userId) { - userId = generateUid(); - window.localStorage.setItem('userId', userId); - } - var screenSize = {width: window.screen.width, height: window.screen.height}; - var deviceType = window.navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) ? 'Mobile' : 'Desktop'; - var e = module.init(); - if (!ua['userId']) { - ua['userId'] = userId; - ua['client_id'] = clientId; - ua['plateform_name'] = e.os.name; - ua['os_version'] = e.os.version; - ua['browser_name'] = e.browser.name; - ua['browser_version'] = e.browser.version; - ua['screen_size'] = screenSize; - ua['device_type'] = deviceType; - ua['time_zone'] = window.Intl.DateTimeFormat().resolvedOptions().timeZone; - } - var signedToken = getJWToken(ua); - payload['visitor_data'] = signedToken; - return signedToken; -} - -ascAdapter.dataProcess = function(t) { - payload['auction_id'] = t.auctionId; - payload['auction_start'] = t.timestamp; - payload['auctionData'] = []; - var bidderRequestsData = []; var bidsReceivedData = []; - t.bidderRequests && t.bidderRequests.forEach(bidReq => { - var pObj = {}; pObj['bids'] = []; - bidReq.bids.forEach(bid => { - var data = {}; - data['adUnitCode'] = bid.adUnitCode; - data['sizes'] = bid.sizes; - data['bidder'] = bid.bidder; - data['bidId'] = bid.bidId; - data['mediaTypes'] = []; - var mt = bid.mediaTypes.banner ? 'display' : 'video'; - data['mediaTypes'].push(mt); - pObj['bids'].push(data); - }) - bidderRequestsData.push(pObj); - }); - t.bidsReceived && t.bidsReceived.forEach(bid => { - const {requestId, bidder, width, height, cpm, currency, timeToRespond, adUnitCode} = bid; - bidsReceivedData.push({requestId, bidder, width, height, cpm, currency, timeToRespond, adUnitCode}); - }); - bidderRequestsData.length > 0 && bidderRequestsData.forEach(bdObj => { - var bdsArray = bdObj['bids']; - bdsArray.forEach(bid => { - const {adUnitCode, sizes, bidder, bidId, mediaTypes} = bid; - sizes.forEach(size => { - var sstr = size[0] + 'x' + size[1] - payload['auctionData'].push({adUnit: adUnitCode, size: sstr, media_type: mediaTypes[0], bids_bidder: bidder, bids_bid_id: bidId}); - }); - }); - }); - bidsReceivedData.length > 0 && bidsReceivedData.forEach(bdRecived => { - const {requestId, bidder, width, height, cpm, currency, timeToRespond} = bdRecived; - payload['auctionData'].forEach(rwData => { - if (rwData['bids_bid_id'] === requestId && rwData['size'] === width + 'x' + height) { - rwData['br_request_id'] = requestId; rwData['br_bidder'] = bidder; rwData['br_pb_mg'] = cpm; - rwData['br_currency'] = currency; rwData['br_time_to_respond'] = timeToRespond; rwData['br_size'] = width + 'x' + height; - } - }) - }); - payload['auctionData'] && payload['auctionData'].length > 0 && payload['auctionData'].forEach(u => { - bdNbTo['to'].forEach(i => { - if (u.bids_bid_id === i.bidId) u.is_timeout = 1; - }); - bdNbTo['nb'].forEach(i => { - if (u.adUnit === i.adUnitCode && u.bids_bidder === i.bidder && u.bids_bid_id === i.bidId) { u.is_nobid = 1; } - }) - }); - return payload; -} - -ascAdapter.sendPayload = function () { - var obj = { 'records': [ { 'value': payload } ] }; - let strJSON = JSON.stringify(obj); - _logInfo(' sendPayload ', JSON.stringify(obj)); - ajax(DEFAULT_EVENT_URL, undefined, strJSON, { - contentType: 'application/vnd.kafka.json.v2+json', - method: 'POST', - withCredentials: true - }); -} - -function addKeyForPrebidWinningAndWinningsBids() { - var prebidWinningBids = $$PREBID_GLOBAL$$.getAllPrebidWinningBids(); - var winningBids = $$PREBID_GLOBAL$$.getAllWinningBids(); - prebidWinningBids && prebidWinningBids.length > 0 && prebidWinningBids.forEach(pbbid => { - payload['auctionData'] && payload['auctionData'].forEach(rwData => { - if (rwData['bids_bid_id'] === pbbid.requestId && rwData['br_size'] === pbbid.size) { - rwData['is_prebid_winning_bid'] = 1; - } - }); - }) - winningBids && winningBids.length > 0 && winningBids.forEach(wBid => { - payload['auctionData'] && payload['auctionData'].forEach(rwData => { - if (rwData['bids_bid_id'] === wBid.requestId && rwData['br_size'] === wBid.size) { - rwData['is_winning_bid'] = 1; - } - }); - }) -} - -adapterManager.registerAnalyticsAdapter({ - adapter: ascAdapter, - code: 'bydata' -}); - -function _logInfo(message, meta) { - logInfo(buildLogMessage(message), meta); -} - -function _logError(message) { - logError(buildLogMessage(message)); -} - -function buildLogMessage(message) { - return 'Bydata Prebid Analytics: ' + message; -} - -export default ascAdapter; diff --git a/modules/byDataAnalyticsAdapter.md b/modules/byDataAnalyticsAdapter.md deleted file mode 100644 index 84207d8b3a1..00000000000 --- a/modules/byDataAnalyticsAdapter.md +++ /dev/null @@ -1,34 +0,0 @@ -# Overview - -layout: Analytics Adapter -title: Ascendeum Pvt Ltd. (https://ascendeum.com/) -description: Bydata Analytics Adapter -modulecode: byDataAnalyticsAdapter -gdpr_supported: false (EU GDPR support) -usp_supported: false (US Privacy support) -coppa_supported: false (COPPA support) -prebid_member: false -gvl_id: (IAB Global Vendor List ID) -enable_download: false (in case you don't want users of the website to download your adapter) - -Module Name: Bydata Analytics Adapter -Module Type: Analytics Adapter -Maintainer: Ascendeum - -# Description - -Analytics adapter for https://ascendeum.com/. Contact engineering@ascendeum.com for information. - -# Test Parameters - -``` -{ - provider: 'bydata', - options : { - clientId: "ASCENDEUM_PROVIDED_CLIENT_ID", - logFrequency : 100, // Sample Rate Default - 1% - } -} -``` - - diff --git a/modules/ccxBidAdapter.js b/modules/ccxBidAdapter.js index 65d1ced30e2..2160e539040 100644 --- a/modules/ccxBidAdapter.js +++ b/modules/ccxBidAdapter.js @@ -1,10 +1,10 @@ -import { deepAccess, isArray, _each, logWarn, isEmpty } from '../src/utils.js'; +import * as utils from '../src/utils.js' import { registerBidder } from '../src/adapters/bidderFactory.js' import { config } from '../src/config.js' import { getStorageManager } from '../src/storageManager.js'; +const storage = getStorageManager(); const BIDDER_CODE = 'ccx' -const storage = getStorageManager({bidderCode: BIDDER_CODE}); const BID_URL = 'https://delivery.clickonometrics.pl/ortb/prebid/bid' const SUPPORTED_VIDEO_PROTOCOLS = [2, 3, 5, 6] const SUPPORTED_VIDEO_MIMES = ['video/mp4', 'video/x-flv'] @@ -20,7 +20,7 @@ function _getDeviceObj () { function _getSiteObj (bidderRequest) { let site = {} - let url = config.getConfig('pageUrl') || deepAccess(window, 'location.href'); + let url = config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href'); if (url.length > 0) { url = url.split('?')[0] } @@ -30,19 +30,19 @@ function _getSiteObj (bidderRequest) { } function _validateSizes (sizeObj, type) { - if (!isArray(sizeObj) || typeof sizeObj[0] === 'undefined') { + if (!utils.isArray(sizeObj) || typeof sizeObj[0] === 'undefined') { return false } - if (type === 'video' && (!isArray(sizeObj[0]) || sizeObj[0].length !== 2)) { + if (type === 'video' && (!utils.isArray(sizeObj[0]) || sizeObj[0].length !== 2)) { return false } let result = true if (type === 'banner') { - _each(sizeObj, function (size) { - if (!isArray(size) || (size.length !== 2)) { + utils._each(sizeObj, function (size) { + if (!utils.isArray(size) || (size.length !== 2)) { result = false } }) @@ -50,11 +50,11 @@ function _validateSizes (sizeObj, type) { } if (type === 'old') { - if (!isArray(sizeObj[0]) && sizeObj.length !== 2) { + if (!utils.isArray(sizeObj[0]) && sizeObj.length !== 2) { result = false - } else if (isArray(sizeObj[0])) { - _each(sizeObj, function (size) { - if (!isArray(size) || (size.length !== 2)) { + } else if (utils.isArray(sizeObj[0])) { + utils._each(sizeObj, function (size) { + if (!utils.isArray(size) || (size.length !== 2)) { result = false } }) @@ -70,22 +70,22 @@ function _buildBid (bid) { placement.id = bid.bidId placement.secure = 1 - let sizes = deepAccess(bid, 'mediaTypes.banner.sizes') || deepAccess(bid, 'mediaTypes.video.playerSize') || deepAccess(bid, 'sizes') + let sizes = utils.deepAccess(bid, 'mediaTypes.banner.sizes') || utils.deepAccess(bid, 'mediaTypes.video.playerSize') || utils.deepAccess(bid, 'sizes') - if (deepAccess(bid, 'mediaTypes.banner') || deepAccess(bid, 'mediaType') === 'banner' || (!deepAccess(bid, 'mediaTypes.video') && !deepAccess(bid, 'mediaType'))) { + if (utils.deepAccess(bid, 'mediaTypes.banner') || utils.deepAccess(bid, 'mediaType') === 'banner' || (!utils.deepAccess(bid, 'mediaTypes.video') && !utils.deepAccess(bid, 'mediaType'))) { placement.banner = {'format': []} - if (isArray(sizes[0])) { - _each(sizes, function (size) { + if (utils.isArray(sizes[0])) { + utils._each(sizes, function (size) { placement.banner.format.push({'w': size[0], 'h': size[1]}) }) } else { placement.banner.format.push({'w': sizes[0], 'h': sizes[1]}) } - } else if (deepAccess(bid, 'mediaTypes.video') || deepAccess(bid, 'mediaType') === 'video') { + } else if (utils.deepAccess(bid, 'mediaTypes.video') || utils.deepAccess(bid, 'mediaType') === 'video') { placement.video = {} if (typeof sizes !== 'undefined') { - if (isArray(sizes[0])) { + if (utils.isArray(sizes[0])) { placement.video.w = sizes[0][0] placement.video.h = sizes[0][1] } else { @@ -94,12 +94,12 @@ function _buildBid (bid) { } } - placement.video.protocols = deepAccess(bid, 'mediaTypes.video.protocols') || deepAccess(bid, 'params.video.protocols') || SUPPORTED_VIDEO_PROTOCOLS - placement.video.mimes = deepAccess(bid, 'mediaTypes.video.mimes') || deepAccess(bid, 'params.video.mimes') || SUPPORTED_VIDEO_MIMES - placement.video.playbackmethod = deepAccess(bid, 'mediaTypes.video.playbackmethod') || deepAccess(bid, 'params.video.playbackmethod') || SUPPORTED_VIDEO_PLAYBACK_METHODS - placement.video.skip = deepAccess(bid, 'mediaTypes.video.skip') || deepAccess(bid, 'params.video.skip') || 0 - if (placement.video.skip === 1 && (deepAccess(bid, 'mediaTypes.video.skipafter') || deepAccess(bid, 'params.video.skipafter'))) { - placement.video.skipafter = deepAccess(bid, 'mediaTypes.video.skipafter') || deepAccess(bid, 'params.video.skipafter') + placement.video.protocols = utils.deepAccess(bid, 'mediaTypes.video.protocols') || utils.deepAccess(bid, 'params.video.protocols') || SUPPORTED_VIDEO_PROTOCOLS + placement.video.mimes = utils.deepAccess(bid, 'mediaTypes.video.mimes') || utils.deepAccess(bid, 'params.video.mimes') || SUPPORTED_VIDEO_MIMES + placement.video.playbackmethod = utils.deepAccess(bid, 'mediaTypes.video.playbackmethod') || utils.deepAccess(bid, 'params.video.playbackmethod') || SUPPORTED_VIDEO_PLAYBACK_METHODS + placement.video.skip = utils.deepAccess(bid, 'mediaTypes.video.skip') || utils.deepAccess(bid, 'params.video.skip') || 0 + if (placement.video.skip === 1 && (utils.deepAccess(bid, 'mediaTypes.video.skipafter') || utils.deepAccess(bid, 'params.video.skipafter'))) { + placement.video.skipafter = utils.deepAccess(bid, 'mediaTypes.video.skipafter') || utils.deepAccess(bid, 'params.video.skipafter') } } @@ -131,7 +131,7 @@ function _buildResponse (bid, currency, ttl) { resp.ad = bid.adm } - if (deepAccess(bid, 'dealid')) { + if (utils.deepAccess(bid, 'dealid')) { resp.dealId = bid.dealid } @@ -143,30 +143,30 @@ export const spec = { supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { - if (!deepAccess(bid, 'params.placementId')) { - logWarn('placementId param is reqeuired.') + if (!utils.deepAccess(bid, 'params.placementId')) { + utils.logWarn('placementId param is reqeuired.') return false } - if (deepAccess(bid, 'mediaTypes.banner.sizes')) { + if (utils.deepAccess(bid, 'mediaTypes.banner.sizes')) { let isValid = _validateSizes(bid.mediaTypes.banner.sizes, 'banner') if (!isValid) { - logWarn('Bid sizes are invalid.') + utils.logWarn('Bid sizes are invalid.') } return isValid - } else if (deepAccess(bid, 'mediaTypes.video.playerSize')) { + } else if (utils.deepAccess(bid, 'mediaTypes.video.playerSize')) { let isValid = _validateSizes(bid.mediaTypes.video.playerSize, 'video') if (!isValid) { - logWarn('Bid sizes are invalid.') + utils.logWarn('Bid sizes are invalid.') } return isValid - } else if (deepAccess(bid, 'sizes')) { + } else if (utils.deepAccess(bid, 'sizes')) { let isValid = _validateSizes(bid.sizes, 'old') if (!isValid) { - logWarn('Bid sizes are invalid.') + utils.logWarn('Bid sizes are invalid.') } return isValid } else { - logWarn('Bid sizes are required.') + utils.logWarn('Bid sizes are required.') return false } }, @@ -195,7 +195,7 @@ export const spec = { }; } - _each(validBidRequests, function (bid) { + utils._each(validBidRequests, function (bid) { requestBody.imp.push(_buildBid(bid)) }) // Return the server request @@ -210,9 +210,9 @@ export const spec = { const bidResponses = [] // response is not empty (HTTP 204) - if (!isEmpty(serverResponse.body)) { - _each(serverResponse.body.seatbid, function (seatbid) { - _each(seatbid.bid, function (bid) { + if (!utils.isEmpty(serverResponse.body)) { + utils._each(serverResponse.body.seatbid, function (seatbid) { + utils._each(seatbid.bid, function (bid) { bidResponses.push(_buildResponse(bid, serverResponse.body.cur, serverResponse.body.ext.ttl)) }) }) @@ -223,8 +223,8 @@ export const spec = { getUserSyncs: function (syncOptions, serverResponses) { const syncs = [] - if (deepAccess(serverResponses[0], 'body.ext.usersync') && !isEmpty(serverResponses[0].body.ext.usersync)) { - _each(serverResponses[0].body.ext.usersync, function (match) { + if (utils.deepAccess(serverResponses[0], 'body.ext.usersync') && !utils.isEmpty(serverResponses[0].body.ext.usersync)) { + utils._each(serverResponses[0].body.ext.usersync, function (match) { if ((syncOptions.iframeEnabled && match.type === 'iframe') || (syncOptions.pixelEnabled && match.type === 'image')) { syncs.push({ type: match.type, diff --git a/modules/cleanioRtdProvider.js b/modules/cleanioRtdProvider.js deleted file mode 100644 index b9fdcef768e..00000000000 --- a/modules/cleanioRtdProvider.js +++ /dev/null @@ -1,192 +0,0 @@ -/** - * This module adds clean.io provider to the real time data module - * The {@link module:modules/realTimeData} module is required - * The module will wrap bid responses markup in clean.io agent script for protection - * @module modules/cleanioRtdProvider - * @requires module:modules/realTimeData - */ - -import { submodule } from '../src/hook.js'; -import { logError, generateUUID, insertElement } from '../src/utils.js'; - -// ============================ MODULE STATE =============================== - -/** - * @type {function(): void} - * Page-wide initialization step / strategy - */ -let onModuleInit = () => {}; - -/** - * @type {function(Object): void} - * Bid response mutation step / strategy. - */ -let onBidResponse = () => {}; - -/** - * @type {number} - * 0 for unknown, 1 for preloaded, -1 for error. - */ -let preloadStatus = 0; - -// ============================ MODULE LOGIC =============================== - -/** - * Page initialization step which just preloads the script, to be available whenever we start processing the bids. - * @param {string} scriptURL The script URL to preload - */ -function pageInitStepPreloadScript(scriptURL) { - const linkElement = document.createElement('link'); - linkElement.rel = 'preload'; - linkElement.as = 'script'; - linkElement.href = scriptURL; - linkElement.onload = () => { preloadStatus = 1; }; - linkElement.onerror = () => { preloadStatus = -1; }; - insertElement(linkElement); -} - -/** - * Page initialization step which adds the protector script to the whole page. With that, there is no need wrapping bids, and the coverage is better. - * @param {string} scriptURL The script URL to add to the page for protection - */ -function pageInitStepProtectPage(scriptURL) { - const scriptElement = document.createElement('script'); - scriptElement.type = 'text/javascript'; - scriptElement.src = scriptURL; - insertElement(scriptElement); -} - -/** - * Bid processing step which alters the ad HTML to contain bid-specific information, which can be used to identify the creative later. - * @param {Object} bidResponse Bid response data - */ -function bidWrapStepAugmentHtml(bidResponse) { - bidResponse.ad = `\n${bidResponse.ad}`; -} - -/** - * Bid processing step which applies creative protection by wrapping the ad HTML. - * @param {string} scriptURL - * @param {number} requiredPreload - * @param {Object} bidResponse - */ -function bidWrapStepProtectByWrapping(scriptURL, requiredPreload, bidResponse) { - // Still prepend bid info, it's always helpful to have creative data in its payload - bidWrapStepAugmentHtml(bidResponse); - - // If preloading failed, or if configuration requires us to finish preloading - - // we should not process this bid any further - if (preloadStatus < requiredPreload) { - return; - } - - const sid = generateUUID(); - bidResponse.ad = ` - - - `; -} - -/** - * Custom error class to differentiate validation errors - */ -class ConfigError extends Error { } - -/** - * The function to be called upon module init. Depending on the passed config, initializes properly init/bid steps or throws ConfigError. - * @param {Object} config - */ -function readConfig(config) { - if (!config.params) { - throw new ConfigError('Missing config parameters for clean.io RTD module provider.'); - } - - if (typeof config.params.cdnUrl !== 'string' || !/^https?:\/\//.test(config.params.cdnUrl)) { - throw new ConfigError('Parameter "cdnUrl" is a required string parameter, which should start with "http(s)://".'); - } - - if (typeof config.params.protectionMode !== 'string') { - throw new ConfigError('Parameter "protectionMode" is a required string parameter.'); - } - - const scriptURL = config.params.cdnUrl; - - switch (config.params.protectionMode) { - case 'full': - onModuleInit = () => pageInitStepProtectPage(scriptURL); - onBidResponse = (bidResponse) => bidWrapStepAugmentHtml(bidResponse); - break; - - case 'bids': - onModuleInit = () => pageInitStepPreloadScript(scriptURL); - onBidResponse = (bidResponse) => bidWrapStepProtectByWrapping(scriptURL, 0, bidResponse); - break; - - case 'bids-nowait': - onModuleInit = () => pageInitStepPreloadScript(scriptURL); - onBidResponse = (bidResponse) => bidWrapStepProtectByWrapping(scriptURL, 1, bidResponse); - break; - - default: - throw new ConfigError('Parameter "protectionMode" must be one of "full" | "bids" | "bids-nowait".'); - } -} - -// ============================ MODULE REGISTRATION =============================== - -/** - * The function which performs submodule registration. - */ -function beforeInit() { - submodule('realTimeData', /** @type {RtdSubmodule} */ ({ - name: 'clean.io', - - init: (config, userConsent) => { - try { - readConfig(config); - onModuleInit(); - return true; - } catch (err) { - if (err instanceof ConfigError) { - logError(err.message); - } - return false; - } - }, - - onBidResponseEvent: (bidResponse, config, userConsent) => { - onBidResponse(bidResponse); - } - })); -} - -/** - * Exporting local (and otherwise encapsulated to this module) functions - * for testing purposes - */ -export const __TEST__ = { - pageInitStepPreloadScript, - pageInitStepProtectPage, - bidWrapStepAugmentHtml, - bidWrapStepProtectByWrapping, - ConfigError, - readConfig, - beforeInit, -} - -beforeInit(); diff --git a/modules/cleanioRtdProvider.md b/modules/cleanioRtdProvider.md deleted file mode 100644 index 7870a2719b6..00000000000 --- a/modules/cleanioRtdProvider.md +++ /dev/null @@ -1,59 +0,0 @@ -# Overview - -``` -Module Name: clean.io Rtd provider -Module Type: Rtd Provider -Maintainer: nick@clean.io -``` - -The clean.io Realtime module provides effective anti-malvertising solution for publishers, including, but not limited to, -blocking unwanted 0- and 1-click redirects, deceptive ads or those with malicious landing pages, and various types of affiliate fraud. - -Using this module requires prior agreement with [clean.io](https://clean.io) to obtain the necessary distribution key. - - -# Integration - -clean.io Realtime module can be built just like any other prebid module: - -``` -gulp build --modules=cleanioRtdProvider,... -``` - - -# Configuration - -When built into prebid.js, this module can be configured through the following `pbjs.setConfig` call: - -```javascript -pbjs.setConfig({ - realTimeData: { - dataProviders: [{ - name: 'clean.io', - params: { - cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', ///< Contact clean.io to get your own CDN URL - protectionMode: 'full', ///< Supported modes are 'full', 'bids' and 'bids-nowait', see below. - } - }] - } -}); -``` - - -## Configuration parameters - -{: .table .table-bordered .table-striped } -| Name | Type | Scope | Description | -| :------------ | :------------ | :------------ |:------------ | -| ``cdnUrl`` | ``string`` | Required | CDN URL of the script, which is to be used for protection. | -| ``protectionMode`` | ``'full' \| 'bids' \| 'bids-nowait'`` | Required | Integration mode. Please refer to the "Integration modes" section for details. | - - -## Integration modes - -{: .table .table-bordered .table-striped } -| Integration Mode | Parameter Value | Description | -| :------------ | :------------ | :------------ | -| Full page protection | ``'full'`` | Preferred mode. The module will add the protector agent script directly to the page, and it will protect all placements. This mode will make the most out of various behavioral detection mechanisms, and will also prevent typical malicious behaviors. Please note that in this mode, depending on Prebid library naming, Chrome may mistakenly tag non-ad-related content as ads: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/ad_tagging.md. | -| Bids-only protection | ``'bids'`` | The module will protect specific bid responses, more specifically, the HTML representing ad payload, by wrapping it into the agent script. Please note that in this mode, ads delivered directly, outside of Prebid integration, will not be protected, since the module can only access the ads coming through Prebid. | -| Bids-only protection with no delay on bid rendering | ``'bids-nowait'`` | Same as above, but in this mode, the script will also *not* wrap those bid responses, which arrived prior to successful preloading of agent script. | diff --git a/modules/cleanmedianetBidAdapter.js b/modules/cleanmedianetBidAdapter.js index 3fda9917715..7b36117d404 100644 --- a/modules/cleanmedianetBidAdapter.js +++ b/modules/cleanmedianetBidAdapter.js @@ -1,9 +1,9 @@ -import {deepAccess, getDNT, inIframe, isArray, isNumber, logError, logWarn} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; import {Renderer} from '../src/Renderer.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {includes} from '../src/polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js'; export const helper = { getTopWindowDomain: function (url) { @@ -76,7 +76,7 @@ export const spec = { }, device: { ua: navigator.userAgent, - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, h: screen.height, w: screen.width, language: navigator.language @@ -129,7 +129,7 @@ export const spec = { w: sizes.length ? sizes[0][0] : 300, h: sizes.length ? sizes[0][1] : 250, pos: params.pos || 0, - topframe: inIframe() ? 0 : 1 + topframe: utils.inIframe() ? 0 : 1 } }); rtbBidRequest.imp.push(bannerImp); @@ -147,10 +147,10 @@ export const spec = { }; let playerSize = mediaTypes.video.playerSize || sizes; - if (isArray(playerSize[0])) { + if (utils.isArray(playerSize[0])) { videoImp.video.w = playerSize[0][0]; videoImp.video.h = playerSize[0][1]; - } else if (isNumber(playerSize[0])) { + } else if (utils.isNumber(playerSize[0])) { videoImp.video.w = playerSize[0]; videoImp.video.h = playerSize[1]; } else { @@ -179,7 +179,7 @@ export const spec = { interpretResponse: function (serverResponse, bidRequest) { const response = serverResponse && serverResponse.body; if (!response) { - logError('empty response'); + utils.logError('empty response'); return []; } @@ -203,7 +203,7 @@ export const spec = { }; if ( - deepAccess( + utils.deepAccess( bidRequest.bidRequest, 'mediaTypes.' + outBid.mediaType ) @@ -211,7 +211,7 @@ export const spec = { if (outBid.mediaType === BANNER) { outBids.push(Object.assign({}, outBid, {ad: bid.adm})); } else if (outBid.mediaType === VIDEO) { - const context = deepAccess( + const context = utils.deepAccess( bidRequest.bidRequest, 'mediaTypes.video.context' ); @@ -287,7 +287,7 @@ function newRenderer(bidRequest, bid, rendererOptions = {}) { try { renderer.setRender(renderOutstream); } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); + utils.logWarn('Prebid Error calling setRender on renderer', err); } return renderer; } diff --git a/modules/clickforceBidAdapter.js b/modules/clickforceBidAdapter.js index eceb4934b04..2e758c509f7 100644 --- a/modules/clickforceBidAdapter.js +++ b/modules/clickforceBidAdapter.js @@ -1,4 +1,4 @@ -import { _each } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE} from '../src/mediaTypes.js'; const BIDDER_CODE = 'clickforce'; @@ -25,7 +25,7 @@ export const spec = { */ buildRequests: function(validBidRequests) { const bidParams = []; - _each(validBidRequests, function(bid) { + utils._each(validBidRequests, function(bid) { bidParams.push({ z: bid.params.zone, bidId: bid.bidId @@ -51,12 +51,12 @@ export const spec = { const bidRequestList = []; if (typeof bidRequest != 'undefined') { - _each(bidRequest.validBidRequests, function(req) { + utils._each(bidRequest.validBidRequests, function(req) { bidRequestList[req.bidId] = req; }); } - _each(serverResponse.body, function(response) { + utils._each(serverResponse.body, function(response) { if (response.requestId != null) { // native ad size if (response.width == 3) { diff --git a/modules/codefuelBidAdapter.js b/modules/codefuelBidAdapter.js deleted file mode 100644 index b9da86ac24e..00000000000 --- a/modules/codefuelBidAdapter.js +++ /dev/null @@ -1,181 +0,0 @@ -import { deepAccess, isArray } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import { BANNER } from '../src/mediaTypes.js'; -const BIDDER_CODE = 'codefuel'; -const CURRENCY = 'USD'; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [ BANNER ], - aliases: ['ex'], // short code - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function(bid) { - if (bid.nativeParams) { - return false; - } - return !!(bid.params.placementId || (bid.params.member && bid.params.invCode)); - }, - /** - * Make a server request from the list of BidRequests. - * - * @param {validBidRequests[]} - an array of bids - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function(validBidRequests, bidderRequest) { - const page = bidderRequest.refererInfo.referer; - const domain = getDomainFromURL(page) - const ua = navigator.userAgent; - const devicetype = getDeviceType() - const publisher = setOnAny(validBidRequests, 'params.publisher'); - const cur = CURRENCY; - const endpointUrl = 'https://ai-p-codefuel-ds-rtb-us-east-1-k8s.seccint.com/prebid' - const timeout = bidderRequest.timeout; - - validBidRequests.forEach(bid => bid.netRevenue = 'net'); - - const imps = validBidRequests.map((bid, idx) => { - const imp = { - id: idx + 1 + '' - } - - if (bid.params.tagid) { - imp.tagid = bid.params.tagid - } - - if (bid.sizes) { - imp.banner = { - format: transformSizes(bid.sizes) - } - } - - return imp; - }); - - const request = { - id: bidderRequest.auctionId, - site: { page, domain, publisher }, - device: { ua, devicetype }, - source: { fd: 1 }, - cur: [cur], - tmax: timeout, - imp: imps, - }; - - return { - method: 'POST', - url: endpointUrl, - data: request, - bids: validBidRequests, - options: { - withCredentials: false - } - }; - }, - /** - * Unpack the response from the server into a list of bids. - * - * @param {ServerResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: (serverResponse, { bids }) => { - if (!serverResponse.body) { - return []; - } - const { seatbid, cur } = serverResponse.body; - - const bidResponses = flatten(seatbid.map(seat => seat.bid)).reduce((result, bid) => { - result[bid.impid - 1] = bid; - return result; - }, []); - - return bids.map((bid, id) => { - const bidResponse = bidResponses[id]; - if (bidResponse) { - const bidObject = { - requestId: bid.bidId, - cpm: bidResponse.price, - creativeId: bidResponse.crid, - ttl: 360, - netRevenue: true, - currency: cur, - mediaType: BANNER, - ad: bidResponse.adm, - width: bidResponse.w, - height: bidResponse.h, - meta: { advertiserDomains: bid.adomain ? bid.adomain : [] } - }; - return bidObject; - } - }).filter(Boolean); - }, - - /** - * Register the user sync pixels which should be dropped after the auction. - * - * @param {SyncOptions} syncOptions Which user syncs are allowed? - * @param {ServerResponse[]} serverResponses List of server's responses. - * @return {UserSync[]} The user syncs which should be dropped. - */ - getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { - return []; - } - -} -registerBidder(spec); - -function getDomainFromURL(url) { - let anchor = document.createElement('a'); - anchor.href = url; - return anchor.hostname; -} - -function getDeviceType() { - if ((/ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i.test(navigator.userAgent.toLowerCase()))) { - return 5; // 'tablet' - } - if ((/iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(navigator.userAgent.toLowerCase()))) { - return 4; // 'mobile' - } - return 2; // 'desktop' -} - -function setOnAny(collection, key) { - for (let i = 0, result; i < collection.length; i++) { - result = deepAccess(collection[i], key); - if (result) { - return result; - } - } -} - -function flatten(arr) { - return [].concat(...arr); -} - -/* Turn bid request sizes into ut-compatible format */ -function transformSizes(requestSizes) { - if (!isArray(requestSizes)) { - return []; - } - - if (requestSizes.length === 2 && !isArray(requestSizes[0])) { - return [{ - w: parseInt(requestSizes[0], 10), - h: parseInt(requestSizes[1], 10) - }]; - } else if (isArray(requestSizes[0])) { - return requestSizes.map(item => - ({ - w: parseInt(item[0], 10), - h: parseInt(item[1], 10) - }) - ); - } - - return []; -} diff --git a/modules/codefuelBidAdapter.md b/modules/codefuelBidAdapter.md deleted file mode 100644 index 4e1a0dd6409..00000000000 --- a/modules/codefuelBidAdapter.md +++ /dev/null @@ -1,111 +0,0 @@ -# Overview - -``` -Module Name: Codefuel Adapter -Module Type: Bidder Adapter -Maintainer: hayimm@codefuel.com -``` - -# Description - -Module that connects to Codefuel bidder to fetch bids. -Display format is supported but not native format. Using OpenRTB standard. - -# Configuration - -## Bidder and usersync URLs - -The Codefuel adapter does not work without setting the correct bidder. -You will receive the URLs when contacting us. - -``` -pbjs.setConfig({ - codefuel: { - bidderUrl: 'https://ai-p-codefuel-ds-rtb-us-east-1-k8s.seccint.com/prebid', - usersyncUrl: 'https://usersync-url.com' - } -}); -``` - - -# Test Native Parameters -``` - var adUnits = [ - code: '/19968336/prebid_native_example_1', - mediaTypes: { - native: { - image: { - required: false, - sizes: [100, 50] - }, - title: { - required: false, - len: 140 - }, - sponsoredBy: { - required: false - }, - clickUrl: { - required: false - }, - body: { - required: false - }, - icon: { - required: false, - sizes: [50, 50] - } - } - }, - bids: [{ - bidder: 'codefuel', - params: { - publisher: { - id: '2706', // required - name: 'Publishers Name', - domain: 'publisher.com' - }, - tagid: 'tag-id', - bcat: ['IAB1-1'], - badv: ['example.com'] - } - }] - ]; - - pbjs.setConfig({ - codefuel: { - bidderUrl: 'https://ai-p-codefuel-ds-rtb-us-east-1-k8s.seccint.com/prebid' - } - }); -``` - -# Test Display Parameters -``` - var adUnits = [ - code: '/19968336/prebid_display_example_1', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - bids: [{ - bidder: 'codefuel', - params: { - publisher: { - id: '2706', // required - name: 'Publishers Name', - domain: 'publisher.com' - }, - tagid: 'tag-id', - bcat: ['IAB1-1'], - badv: ['example.com'] - }, - }] - ]; - - pbjs.setConfig({ - codefuel: { - bidderUrl: 'https://ai-p-codefuel-ds-rtb-us-east-1-k8s.seccint.com/prebid' - } - }); -``` diff --git a/modules/cointrafficBidAdapter.js b/modules/cointrafficBidAdapter.js index f61d58664ca..a6241980e06 100644 --- a/modules/cointrafficBidAdapter.js +++ b/modules/cointrafficBidAdapter.js @@ -1,10 +1,10 @@ -import { parseSizesInput, logError, isEmpty } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js' import { config } from '../src/config.js' const BIDDER_CODE = 'cointraffic'; -const ENDPOINT_URL = 'https://apps-pbd.ctengine.io/pb/tmp'; +const ENDPOINT_URL = 'https://appspb.cointraffic.io/pb/tmp'; const DEFAULT_CURRENCY = 'EUR'; const ALLOWED_CURRENCIES = [ 'EUR', 'USD', 'JPY', 'BGN', 'CZK', 'DKK', 'GBP', 'HUF', 'PLN', 'RON', 'SEK', 'CHF', 'ISK', 'NOK', 'HRK', 'RUB', 'TRY', @@ -34,14 +34,14 @@ export const spec = { */ buildRequests: function (validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { - const sizes = parseSizesInput(bidRequest.params.size || bidRequest.sizes); + const sizes = utils.parseSizesInput(bidRequest.params.size || bidRequest.sizes); const currency = config.getConfig(`currency.bidderCurrencyDefault.${BIDDER_CODE}`) || config.getConfig('currency.adServerCurrency') || DEFAULT_CURRENCY; if (ALLOWED_CURRENCIES.indexOf(currency) === -1) { - logError('Currency is not supported - ' + currency); + utils.logError('Currency is not supported - ' + currency); return; } @@ -72,7 +72,7 @@ export const spec = { const bidResponses = []; const response = serverResponse.body; - if (isEmpty(response)) { + if (utils.isEmpty(response)) { return bidResponses; } diff --git a/modules/coinzillaBidAdapter.js b/modules/coinzillaBidAdapter.js index cd087daa8cb..e1c2b7d01b2 100644 --- a/modules/coinzillaBidAdapter.js +++ b/modules/coinzillaBidAdapter.js @@ -1,4 +1,4 @@ -import { parseSizesInput } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; @@ -31,7 +31,7 @@ export const spec = { return []; } return validBidRequests.map(bidRequest => { - const sizes = parseSizesInput(bidRequest.params.size || bidRequest.sizes)[0]; + const sizes = utils.parseSizesInput(bidRequest.params.size || bidRequest.sizes)[0]; const width = sizes.split('x')[0]; const height = sizes.split('x')[1]; const payload = { diff --git a/modules/colossussspBidAdapter.js b/modules/colossussspBidAdapter.js index fec0d1b6510..0f7daf8fda9 100644 --- a/modules/colossussspBidAdapter.js +++ b/modules/colossussspBidAdapter.js @@ -1,12 +1,10 @@ -import { getWindowTop, deepAccess, logMessage } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { ajax } from '../src/ajax.js'; -import { config } from '../src/config.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'colossusssp'; const G_URL = 'https://colossusssp.com/?c=o&m=multi'; -const G_URL_SYNC = 'https://sync.colossusssp.com'; +const G_URL_SYNC = 'https://colossusssp.com/?c=o&m=cookie'; function isBidResponseValid(bid) { if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency) { @@ -48,10 +46,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: (bid) => { - const validPlacamentId = bid.params && !isNaN(bid.params.placement_id); - const validGroupId = bid.params && !isNaN(bid.params.group_id); - - return Boolean(bid.bidId && (validPlacamentId || validGroupId)); + return Boolean(bid.bidId && bid.params && !isNaN(bid.params.placement_id)); }, /** @@ -61,38 +56,17 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: (validBidRequests, bidderRequest) => { - let deviceWidth = 0; - let deviceHeight = 0; - let winLocation; - - try { - const winTop = getWindowTop(); - deviceWidth = winTop.screen.width; - deviceHeight = winTop.screen.height; - winLocation = winTop.location; - } catch (e) { - logMessage(e); - winLocation = window.location; - } - - const refferUrl = bidderRequest.refererInfo && bidderRequest.refererInfo.referer; - let refferLocation; - try { - refferLocation = refferUrl && new URL(refferUrl); - } catch (e) { - logMessage(e); - } - - const location = refferLocation || winLocation; + const winTop = utils.getWindowTop(); + const location = winTop.location; let placements = []; let request = { - deviceWidth, - deviceHeight, - language: (navigator && navigator.language) ? navigator.language : '', - secure: location.protocol === 'https:' ? 1 : 0, - host: location.host, - page: location.pathname, - placements: placements, + 'deviceWidth': winTop.screen.width, + 'deviceHeight': winTop.screen.height, + 'language': (navigator && navigator.language) ? navigator.language : '', + 'secure': location.protocol === 'https:' ? 1 : 0, + 'host': location.host, + 'page': location.pathname, + 'placements': placements, }; if (bidderRequest) { @@ -110,8 +84,8 @@ export const spec = { let traff = bid.params.traffic || BANNER let placement = { placementId: bid.params.placement_id, - groupId: bid.params.group_id, bidId: bid.bidId, + sizes: bid.mediaTypes[traff].sizes, traffic: traff, eids: [], floor: {} @@ -132,25 +106,15 @@ export const spec = { if (bid.schain) { placement.schain = bid.schain; } - let gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); - if (gpid) { - placement.gpid = gpid; - } if (bid.userId) { getUserId(placement.eids, bid.userId.britepoolid, 'britepool.com'); getUserId(placement.eids, bid.userId.idl_env, 'identityLink'); - getUserId(placement.eids, bid.userId.id5id, 'id5-sync.com'); - getUserId(placement.eids, bid.userId.uid2 && bid.userId.uid2.id, 'uidapi.com'); + getUserId(placement.eids, bid.userId.id5id, 'id5-sync.com') getUserId(placement.eids, bid.userId.tdid, 'adserver.org', { rtiPartner: 'TDID' }); } - if (traff === BANNER) { - placement.sizes = bid.mediaTypes[BANNER].sizes - } - if (traff === VIDEO) { - placement.sizes = bid.mediaTypes[VIDEO].playerSize; placement.playerSize = bid.mediaTypes[VIDEO].playerSize; placement.minduration = bid.mediaTypes[VIDEO].minduration; placement.maxduration = bid.mediaTypes[VIDEO].maxduration; @@ -196,38 +160,16 @@ export const spec = { } } } catch (e) { - logMessage(e); + utils.logMessage(e); }; return response; }, - getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { - let syncType = syncOptions.iframeEnabled ? 'html' : 'hms.gif'; - let syncUrl = G_URL_SYNC + `/${syncType}?pbjs=1`; - if (gdprConsent && gdprConsent.consentString) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; - } - } - if (uspConsent && uspConsent.consentString) { - syncUrl += `&ccpa_consent=${uspConsent.consentString}`; - } - - const coppa = config.getConfig('coppa') ? 1 : 0; - syncUrl += `&coppa=${coppa}`; - + getUserSyncs: () => { return [{ - type: syncType, - url: syncUrl + type: 'image', + url: G_URL_SYNC }]; - }, - - onBidWon: (bid) => { - if (bid.nurl) { - ajax(bid.nurl, null); - } } }; diff --git a/modules/colossussspBidAdapter.md b/modules/colossussspBidAdapter.md index 4187dfbf36e..8797c648c95 100644 --- a/modules/colossussspBidAdapter.md +++ b/modules/colossussspBidAdapter.md @@ -26,19 +26,5 @@ Module that connects to Colossus SSP demand sources traffic: 'banner' } }] - }, { - code: 'placementid_1', - mediaTypes: { - banner: { - sizes: [[300, 250], [300,600]] - } - }, - bids: [{ - bidder: 'colossusssp', - params: { - group_id: 0, - traffic: 'banner' - } - }] - }]; + ]; ``` diff --git a/modules/compassBidAdapter.js b/modules/compassBidAdapter.js deleted file mode 100644 index 77f918276bc..00000000000 --- a/modules/compassBidAdapter.js +++ /dev/null @@ -1,208 +0,0 @@ -import { isFn, deepAccess, logMessage, logError } from '../src/utils.js'; - -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; - -const BIDDER_CODE = 'compass'; -const AD_URL = 'https://sa-lb.deliverimp.com/pbjs'; -const SYNC_URL = 'https://sa-cs.deliverimp.com'; - -function isBidResponseValid(bid) { - if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency) { - return false; - } - - switch (bid.mediaType) { - case BANNER: - return Boolean(bid.width && bid.height && bid.ad); - case VIDEO: - return Boolean(bid.vastUrl || bid.vastXml); - case NATIVE: - return Boolean(bid.native && bid.native.impressionTrackers && bid.native.impressionTrackers.length); - default: - return false; - } -} - -function getPlacementReqData(bid) { - const { params, bidId, mediaTypes } = bid; - const schain = bid.schain || {}; - const { placementId, endpointId } = params; - const bidfloor = getBidFloor(bid); - - const placement = { - bidId, - schain, - bidfloor - }; - - if (placementId) { - placement.placementId = placementId; - placement.type = 'publisher'; - } else if (endpointId) { - placement.endpointId = endpointId; - placement.type = 'network'; - } - - if (mediaTypes && mediaTypes[BANNER]) { - placement.adFormat = BANNER; - placement.sizes = mediaTypes[BANNER].sizes; - } else if (mediaTypes && mediaTypes[VIDEO]) { - placement.adFormat = VIDEO; - placement.playerSize = mediaTypes[VIDEO].playerSize; - placement.minduration = mediaTypes[VIDEO].minduration; - placement.maxduration = mediaTypes[VIDEO].maxduration; - placement.mimes = mediaTypes[VIDEO].mimes; - placement.protocols = mediaTypes[VIDEO].protocols; - placement.startdelay = mediaTypes[VIDEO].startdelay; - placement.placement = mediaTypes[VIDEO].placement; - placement.skip = mediaTypes[VIDEO].skip; - placement.skipafter = mediaTypes[VIDEO].skipafter; - placement.minbitrate = mediaTypes[VIDEO].minbitrate; - placement.maxbitrate = mediaTypes[VIDEO].maxbitrate; - placement.delivery = mediaTypes[VIDEO].delivery; - placement.playbackmethod = mediaTypes[VIDEO].playbackmethod; - placement.api = mediaTypes[VIDEO].api; - placement.linearity = mediaTypes[VIDEO].linearity; - } else if (mediaTypes && mediaTypes[NATIVE]) { - placement.native = mediaTypes[NATIVE]; - placement.adFormat = NATIVE; - } - - return placement; -} - -function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidfloor', 0); - } - - try { - const bidFloor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*', - }); - return bidFloor.floor; - } catch (err) { - logError(err); - return 0; - } -} - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO, NATIVE], - - isBidRequestValid: (bid = {}) => { - const { params, bidId, mediaTypes } = bid; - let valid = Boolean(bidId && params && (params.placementId || params.endpointId)); - - if (mediaTypes && mediaTypes[BANNER]) { - valid = valid && Boolean(mediaTypes[BANNER] && mediaTypes[BANNER].sizes); - } else if (mediaTypes && mediaTypes[VIDEO]) { - valid = valid && Boolean(mediaTypes[VIDEO] && mediaTypes[VIDEO].playerSize); - } else if (mediaTypes && mediaTypes[NATIVE]) { - valid = valid && Boolean(mediaTypes[NATIVE]); - } else { - valid = false; - } - return valid; - }, - - buildRequests: (validBidRequests = [], bidderRequest = {}) => { - let deviceWidth = 0; - let deviceHeight = 0; - - let winLocation; - try { - const winTop = window.top; - deviceWidth = winTop.screen.width; - deviceHeight = winTop.screen.height; - winLocation = winTop.location; - } catch (e) { - logMessage(e); - winLocation = window.location; - } - - const refferUrl = bidderRequest.refererInfo && bidderRequest.refererInfo.referer; - let refferLocation; - try { - refferLocation = refferUrl && new URL(refferUrl); - } catch (e) { - logMessage(e); - } - - let location = refferLocation || winLocation; - const language = (navigator && navigator.language) ? navigator.language.split('-')[0] : ''; - const host = location.host; - const page = location.pathname; - const secure = location.protocol === 'https:' ? 1 : 0; - const placements = []; - const request = { - deviceWidth, - deviceHeight, - language, - secure, - host, - page, - placements, - coppa: config.getConfig('coppa') === true ? 1 : 0, - ccpa: bidderRequest.uspConsent || undefined, - gdpr: bidderRequest.gdprConsent || undefined, - tmax: config.getConfig('bidderTimeout') - }; - - const len = validBidRequests.length; - for (let i = 0; i < len; i++) { - const bid = validBidRequests[i]; - placements.push(getPlacementReqData(bid)); - } - - return { - method: 'POST', - url: AD_URL, - data: request - }; - }, - - interpretResponse: (serverResponse) => { - let response = []; - for (let i = 0; i < serverResponse.body.length; i++) { - let resItem = serverResponse.body[i]; - if (isBidResponseValid(resItem)) { - const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : []; - resItem.meta = { ...resItem.meta, advertiserDomains }; - - response.push(resItem); - } - } - return response; - }, - - getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { - let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; - let syncUrl = SYNC_URL + `/${syncType}?pbjs=1`; - if (gdprConsent && gdprConsent.consentString) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; - } - } - if (uspConsent && uspConsent.consentString) { - syncUrl += `&ccpa_consent=${uspConsent.consentString}`; - } - - const coppa = config.getConfig('coppa') ? 1 : 0; - syncUrl += `&coppa=${coppa}`; - - return [{ - type: syncType, - url: syncUrl - }]; - } -}; - -registerBidder(spec); diff --git a/modules/compassBidAdapter.md b/modules/compassBidAdapter.md deleted file mode 100644 index 18d52c12384..00000000000 --- a/modules/compassBidAdapter.md +++ /dev/null @@ -1,79 +0,0 @@ -# Overview - -``` -Module Name: Compass Bidder Adapter -Module Type: Compass Bidder Adapter -Maintainer: sa-support@brightcom.com -``` - -# Description - -Connects to Compass exchange for bids. -Compass bid adapter supports Banner, Video (instream and outstream) and Native. - -# Test Parameters -``` - var adUnits = [ - // Will return static test banner - { - code: 'adunit1', - mediaTypes: { - banner: { - sizes: [ [300, 250], [320, 50] ], - } - }, - bids: [ - { - bidder: 'compass', - params: { - placementId: 'testBanner', - } - } - ] - }, - { - code: 'addunit2', - mediaTypes: { - video: { - playerSize: [ [640, 480] ], - context: 'instream', - minduration: 5, - maxduration: 60, - } - }, - bids: [ - { - bidder: 'compass', - params: { - placementId: 'testVideo', - } - } - ] - }, - { - code: 'addunit3', - mediaTypes: { - native: { - title: { - required: true - }, - body: { - required: true - }, - icon: { - required: true, - size: [64, 64] - } - } - }, - bids: [ - { - bidder: 'compass', - params: { - placementId: 'testNative', - } - } - ] - } - ]; -``` \ No newline at end of file diff --git a/modules/concertAnalyticsAdapter.js b/modules/concertAnalyticsAdapter.js index cd52a2ffabf..a81d07e63b5 100644 --- a/modules/concertAnalyticsAdapter.js +++ b/modules/concertAnalyticsAdapter.js @@ -1,8 +1,8 @@ -import { logMessage } from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; +import * as utils from '../src/utils.js'; const analyticsType = 'endpoint'; @@ -90,7 +90,7 @@ function sendEvents() { if (!queue.length) return; if (!pageIncludedInSample) { - logMessage('Page not included in sample for Concert Analytics'); + utils.logMessage('Page not included in sample for Concert Analytics'); return; } @@ -100,7 +100,7 @@ function sendEvents() { contentType: 'application/json', method: 'POST' }); - } catch (err) { logMessage('Concert Analytics error') } + } catch (err) { utils.logMessage('Concert Analytics error') } } // save the base class function diff --git a/modules/concertBidAdapter.js b/modules/concertBidAdapter.js index 99e2492fb94..60634151aba 100644 --- a/modules/concertBidAdapter.js +++ b/modules/concertBidAdapter.js @@ -1,4 +1,5 @@ -import { logWarn, logMessage, debugTurnedOn, generateUUID } from '../src/utils.js'; + +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { getStorageManager } from '../src/storageManager.js' @@ -16,7 +17,7 @@ export const spec = { */ isBidRequestValid: function(bid) { if (!bid.params.partnerId) { - logWarn('Missing partnerId bid parameter'); + utils.logWarn('Missing partnerId bid parameter'); return false; } @@ -31,14 +32,14 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function(validBidRequests, bidderRequest) { - logMessage(validBidRequests); - logMessage(bidderRequest); + utils.logMessage(validBidRequests); + utils.logMessage(bidderRequest); let payload = { meta: { prebidVersion: '$prebid.version$', pageUrl: bidderRequest.refererInfo.referer, screen: [window.screen.width, window.screen.height].join('x'), - debug: debugTurnedOn(), + debug: utils.debugTurnedOn(), uid: getUid(bidderRequest), optedOut: hasOptedOutOfPersonalization(), adapterVersion: '1.1.1', @@ -63,7 +64,7 @@ export const spec = { return slot; }); - logMessage(payload); + utils.logMessage(payload); return { method: 'POST', @@ -78,8 +79,8 @@ export const spec = { * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: function(serverResponse, bidRequest) { - logMessage(serverResponse); - logMessage(bidRequest); + utils.logMessage(serverResponse); + utils.logMessage(bidRequest); const serverBody = serverResponse.body; @@ -104,11 +105,11 @@ export const spec = { } }); - if (debugTurnedOn() && serverBody.debug) { - logMessage(`CONCERT`, serverBody.debug); + if (utils.debugTurnedOn() && serverBody.debug) { + utils.logMessage(`CONCERT`, serverBody.debug); } - logMessage(bidResponses); + utils.logMessage(bidResponses); return bidResponses; }, @@ -149,8 +150,8 @@ export const spec = { * @param {data} Containing timeout specific data */ onTimeout: function(data) { - logMessage('concert bidder timed out'); - logMessage(data); + utils.logMessage('concert bidder timed out'); + utils.logMessage(data); }, /** @@ -158,15 +159,15 @@ export const spec = { * @param {Bid} The bid that won the auction */ onBidWon: function(bid) { - logMessage('concert bidder won bid'); - logMessage(bid); + utils.logMessage('concert bidder won bid'); + utils.logMessage(bid); } } registerBidder(spec); -const storage = getStorageManager({bidderCode: BIDDER_CODE}); +const storage = getStorageManager(); /** * Check or generate a UID for the current user. @@ -181,7 +182,7 @@ function getUid(bidderRequest) { let uid = storage.getDataFromLocalStorage(CONCERT_UID_KEY); if (!uid) { - uid = generateUUID(); + uid = utils.generateUUID(); storage.setDataInLocalStorage(CONCERT_UID_KEY, uid); } diff --git a/modules/connectIdSystem.js b/modules/connectIdSystem.js deleted file mode 100644 index 2da2eda4c77..00000000000 --- a/modules/connectIdSystem.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * This module adds support for Yahoo ConnectID to the user ID module system. - * The {@link module:modules/userId} module is required - * @module modules/connectIdSystem - * @requires module:modules/userId - */ - -import {ajax} from '../src/ajax.js'; -import {submodule} from '../src/hook.js'; -import {formatQS, logError} from '../src/utils.js'; -import {includes} from '../src/polyfill.js'; - -const MODULE_NAME = 'connectId'; -const VENDOR_ID = 25; -const PLACEHOLDER = '__PIXEL_ID__'; -const UPS_ENDPOINT = `https://ups.analytics.yahoo.com/ups/${PLACEHOLDER}/fed`; - -function isEUConsentRequired(consentData) { - return !!(consentData && consentData.gdpr && consentData.gdpr.gdprApplies); -} - -/** @type {Submodule} */ -export const connectIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - /** - * @type {Number} - */ - gvlid: VENDOR_ID, - /** - * decode the stored id value for passing to bid requests - * @function - * @returns {{connectId: string} | undefined} - */ - decode(value) { - return (typeof value === 'object' && value.connectid) - ? {connectId: value.connectid} : undefined; - }, - /** - * Gets the Yahoo ConnectID - * @function - * @param {SubmoduleConfig} [config] - * @param {ConsentData} [consentData] - * @returns {IdResponse|undefined} - */ - getId(config, consentData) { - const params = config.params || {}; - if (!params || typeof params.he !== 'string' || - (typeof params.pixelId === 'undefined' && typeof params.endpoint === 'undefined')) { - logError('The connectId submodule requires the \'he\' and \'pixelId\' parameters to be defined.'); - return; - } - - const data = { - '1p': includes([1, '1', true], params['1p']) ? '1' : '0', - he: params.he, - gdpr: isEUConsentRequired(consentData) ? '1' : '0', - gdpr_consent: isEUConsentRequired(consentData) ? consentData.gdpr.consentString : '', - us_privacy: consentData && consentData.uspConsent ? consentData.uspConsent : '' - }; - - if (params.pixelId) { - data.pixelId = params.pixelId - } - - const resp = function (callback) { - const callbacks = { - success: response => { - let responseObj; - if (response) { - try { - responseObj = JSON.parse(response); - } catch (error) { - logError(error); - } - } - callback(responseObj); - }, - error: error => { - logError(`${MODULE_NAME}: ID fetch encountered an error`, error); - callback(); - } - }; - const endpoint = UPS_ENDPOINT.replace(PLACEHOLDER, params.pixelId); - let url = `${params.endpoint || endpoint}?${formatQS(data)}`; - connectIdSubmodule.getAjaxFn()(url, callbacks, null, {method: 'GET', withCredentials: true}); - }; - return {callback: resp}; - }, - - /** - * Return the function used to perform XHR calls. - * Utilised for each of testing. - * @returns {Function} - */ - getAjaxFn() { - return ajax; - } -}; - -submodule('userId', connectIdSubmodule); diff --git a/modules/connectIdSystem.md b/modules/connectIdSystem.md deleted file mode 100644 index f2153e1b6cb..00000000000 --- a/modules/connectIdSystem.md +++ /dev/null @@ -1,33 +0,0 @@ -## Yahoo ConnectID User ID Submodule - -Yahoo ConnectID user ID Module. - -### Prebid Params - -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'connectId', - storage: { - name: 'connectId', - type: 'html5', - expires: 15 - }, - params: { - pixelId: 58776, - he: '0bef996248d63cea1529cb86de31e9547a712d9f380146e98bbd39beec70355a' - } - }] - } -}); -``` -## Parameter Descriptions for the `usersync` Configuration Section -The below parameters apply only to the Yahoo ConnectID user ID Module. - -| Param under usersync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | ID value for the Yahoo ConnectID module - `"connectId"` | `"connectId"` | -| params | Required | Object | Data for Yahoo ConnectID initialization. | | -| params.pixelId | Required | Number | The Yahoo supplied publisher specific pixel Id | `8976` | -| params.he | Required | String | The SHA-256 hashed user email address | `"529cb86de31e9547a712d9f380146e98bbd39beec"` | diff --git a/modules/connectadBidAdapter.js b/modules/connectadBidAdapter.js index 711afd98d0f..111b6ac10e8 100644 --- a/modules/connectadBidAdapter.js +++ b/modules/connectadBidAdapter.js @@ -1,4 +1,4 @@ -import { deepSetValue, convertTypes, tryAppendQueryString, logWarn } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js' import {config} from '../src/config.js'; @@ -47,12 +47,12 @@ export const spec = { // coppa compliance if (config.getConfig('coppa') === true) { - deepSetValue(data, 'user.coppa', 1); + utils.deepSetValue(data, 'user.coppa', 1); } // adding schain object if (validBidRequests[0].schain) { - deepSetValue(data, 'source.ext.schain', validBidRequests[0].schain); + utils.deepSetValue(data, 'source.ext.schain', validBidRequests[0].schain); } // Attaching GDPR Consent Params @@ -61,18 +61,18 @@ export const spec = { if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { gdprApplies = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; } - deepSetValue(data, 'user.ext.gdpr', gdprApplies); - deepSetValue(data, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(data, 'user.ext.gdpr', gdprApplies); + utils.deepSetValue(data, 'user.ext.consent', bidderRequest.gdprConsent.consentString); } // CCPA if (bidderRequest.uspConsent) { - deepSetValue(data, 'user.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(data, 'user.ext.us_privacy', bidderRequest.uspConsent); } // EIDS Support if (validBidRequests[0].userId) { - deepSetValue(data, 'user.ext.eids', createEidsArray(validBidRequests[0].userId)); + utils.deepSetValue(data, 'user.ext.eids', createEidsArray(validBidRequests[0].userId)); } validBidRequests.map(bid => { @@ -139,7 +139,7 @@ export const spec = { }, transformBidParams: function (params, isOpenRtb) { - return convertTypes({ + return utils.convertTypes({ 'siteId': 'number', 'networkId': 'number' }, params); @@ -149,19 +149,19 @@ export const spec = { let syncEndpoint = 'https://cdn.connectad.io/connectmyusers.php?'; if (gdprConsent) { - syncEndpoint = tryAppendQueryString(syncEndpoint, 'gdpr', (gdprConsent.gdprApplies ? 1 : 0)); + syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'gdpr', (gdprConsent.gdprApplies ? 1 : 0)); } if (gdprConsent && typeof gdprConsent.consentString === 'string') { - syncEndpoint = tryAppendQueryString(syncEndpoint, 'gdpr_consent', gdprConsent.consentString); + syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'gdpr_consent', gdprConsent.consentString); } if (uspConsent) { - syncEndpoint = tryAppendQueryString(syncEndpoint, 'us_privacy', uspConsent); + syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'us_privacy', uspConsent); } if (config.getConfig('coppa') === true) { - syncEndpoint = tryAppendQueryString(syncEndpoint, 'coppa', 1); + syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'coppa', 1); } if (syncOptions.iframeEnabled) { @@ -170,7 +170,7 @@ export const spec = { url: syncEndpoint }]; } else { - logWarn('Bidder ConnectAd: Please activate iFrame Sync'); + utils.logWarn('Bidder ConnectAd: Please activate iFrame Sync'); } } }; diff --git a/modules/consentManagement.js b/modules/consentManagement.js index 5fbcc0f8ac1..6a13e73b8a2 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -4,10 +4,11 @@ * and make it available for any GDPR supported adapters to read/pass this information to * their system. */ -import {getAdUnitSizes, isFn, isNumber, isPlainObject, isStr, logError, logInfo, logWarn} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {gdprDataHandler} from '../src/adapterManager.js'; -import {includes} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { config } from '../src/config.js'; +import { gdprDataHandler } from '../src/adapterManager.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import strIncludes from 'core-js-pure/features/string/includes.js'; const DEFAULT_CMP = 'iab'; const DEFAULT_CONSENT_TIMEOUT = 10000; @@ -34,22 +35,23 @@ const cmpCallMap = { /** * This function reads the consent string from the config to obtain the consent information of the user. - * @param {function({})} onSuccess acts as a success callback when the value is read from config; pass along consentObject from CMP + * @param {function(string)} cmpSuccess acts as a success callback when the value is read from config; pass along consentObject (string) from CMP + * @param {function(string)} cmpError acts as an error callback while interacting with the config string; pass along an error message (string) + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) */ -function lookupStaticConsentData({onSuccess, onError}) { - processCmpData(staticConsentData, {onSuccess, onError}) +function lookupStaticConsentData(cmpSuccess, cmpError, hookConfig) { + cmpSuccess(staticConsentData, hookConfig); } /** * This function handles interacting with an IAB compliant CMP to obtain the consent information of the user. * Given the async nature of the CMP's API, we pass in acting success/error callback functions to exit this function * based on the appropriate result. - * @param {function({})} onSuccess acts as a success callback when CMP returns a value; pass along consentObjectfrom CMP - * @param {function(string, ...{}?)} cmpError acts as an error callback while interacting with CMP; pass along an error message (string) and any extra error arguments (purely for logging) - * @param width - * @param height size info passed to the SafeFrame API (used only for TCFv1 when Prebid is running within a safeframe) + * @param {function(string)} cmpSuccess acts as a success callback when CMP returns a value; pass along consentObject (string) from CMP + * @param {function(string)} cmpError acts as an error callback while interacting with CMP; pass along an error message (string) + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) */ -function lookupIabConsent({onSuccess, onError, width, height}) { +function lookupIabConsent(cmpSuccess, cmpError, hookConfig) { function findCMP() { let f = window; let cmpFrame; @@ -96,13 +98,13 @@ function lookupIabConsent({onSuccess, onError, width, height}) { } function v2CmpResponseCallback(tcfData, success) { - logInfo('Received a response from CMP', tcfData); + utils.logInfo('Received a response from CMP', tcfData); if (success) { if (tcfData.gdprApplies === false || tcfData.eventStatus === 'tcloaded' || tcfData.eventStatus === 'useractioncomplete') { - processCmpData(tcfData, {onSuccess, onError}); + cmpSuccess(tcfData, hookConfig); } } else { - onError('CMP unable to register callback function. Please check CMP setup.'); + cmpError('CMP unable to register callback function. Please check CMP setup.', hookConfig); } } @@ -111,8 +113,8 @@ function lookupIabConsent({onSuccess, onError, width, height}) { function afterEach() { if (cmpResponse.getConsentData && cmpResponse.getVendorConsents) { - logInfo('Received all requested responses from CMP', cmpResponse); - processCmpData(cmpResponse, {onSuccess, onError}); + utils.logInfo('Received all requested responses from CMP', cmpResponse); + cmpSuccess(cmpResponse, hookConfig); } } @@ -133,7 +135,7 @@ function lookupIabConsent({onSuccess, onError, width, height}) { let { cmpFrame, cmpFunction } = findCMP(); if (!cmpFrame) { - return onError('CMP not found.'); + return cmpError('CMP not found.', hookConfig); } // to collect the consent information from the user, we perform two calls to the CMP in parallel: // first to collect the user's consent choices represented in an encoded string (via getConsentData) @@ -145,8 +147,8 @@ function lookupIabConsent({onSuccess, onError, width, height}) { // else assume prebid may be inside an iframe and use the IAB CMP locator code to see if CMP's located in a higher parent window. this works in cross domain iframes // if the CMP is not found, the iframe function will call the cmpError exit callback to abort the rest of the CMP workflow - if (isFn(cmpFunction)) { - logInfo('Detected CMP API is directly accessible, calling it now...'); + if (utils.isFn(cmpFunction)) { + utils.logInfo('Detected CMP API is directly accessible, calling it now...'); if (cmpVersion === 1) { cmpFunction('getConsentData', null, v1CallbackHandler.consentDataCallback); cmpFunction('getVendorConsents', null, v1CallbackHandler.vendorConsentsCallback); @@ -155,11 +157,11 @@ function lookupIabConsent({onSuccess, onError, width, height}) { } } else if (cmpVersion === 1 && inASafeFrame() && typeof window.$sf.ext.cmp === 'function') { // this safeframe workflow is only supported with TCF v1 spec; the v2 recommends to use the iframe postMessage route instead (even if you are in a safeframe). - logInfo('Detected Prebid.js is encased in a SafeFrame and CMP is registered, calling it now...'); + utils.logInfo('Detected Prebid.js is encased in a SafeFrame and CMP is registered, calling it now...'); callCmpWhileInSafeFrame('getConsentData', v1CallbackHandler.consentDataCallback); callCmpWhileInSafeFrame('getVendorConsents', v1CallbackHandler.vendorConsentsCallback); } else { - logInfo('Detected CMP is outside the current iframe where Prebid.js is located, calling it now...'); + utils.logInfo('Detected CMP is outside the current iframe where Prebid.js is located, calling it now...'); if (cmpVersion === 1) { callCmpWhileInIframe('getConsentData', cmpFrame, v1CallbackHandler.consentDataCallback); callCmpWhileInIframe('getVendorConsents', cmpFrame, v1CallbackHandler.vendorConsentsCallback); @@ -180,6 +182,16 @@ function lookupIabConsent({onSuccess, onError, width, height}) { } } + // find sizes from adUnits object + let adUnits = hookConfig.adUnits; + let width = 1; + let height = 1; + if (Array.isArray(adUnits) && adUnits.length > 0) { + let sizes = utils.getAdUnitSizes(adUnits[0]); + width = sizes[0][0]; + height = sizes[0][1]; + } + window.$sf.ext.register(width, height, sfCallback); window.$sf.ext.cmp(commandName); } @@ -236,7 +248,7 @@ function lookupIabConsent({onSuccess, onError, width, height}) { function readPostMessageResponse(event) { let cmpDataPkgName = `${apiName}Return`; - let json = (typeof event.data === 'string' && includes(event.data, cmpDataPkgName)) ? JSON.parse(event.data) : event.data; + let json = (typeof event.data === 'string' && strIncludes(event.data, cmpDataPkgName)) ? JSON.parse(event.data) : event.data; if (json[cmpDataPkgName] && json[cmpDataPkgName].callId) { let payload = json[cmpDataPkgName]; // TODO - clean up this logic (move listeners?); we have duplicate messages responses because 2 eventlisteners are active from the 2 cmp requests running in parallel @@ -248,70 +260,6 @@ function lookupIabConsent({onSuccess, onError, width, height}) { } } -/** - * Look up consent data and store it in the `consentData` global as well as `adapterManager.js`' gdprDataHandler. - * - * @param cb A callback that takes: a boolean that is true if the auction should be canceled; an error message and extra - * error arguments that will be undefined if there's no error. - * @param width if we are running in an iframe, the TCFv1 spec requires us to use the SafeFrame API to find the CMP - which - * in turn requires width and height. - * @param height see width above - */ -function loadConsentData(cb, width = 1, height = 1) { - let isDone = false; - let timer = null; - - function done(consentData, shouldCancelAuction, errMsg, ...extraArgs) { - if (timer != null) { - clearTimeout(timer); - } - isDone = true; - gdprDataHandler.setConsentData(consentData); - if (cb != null) { - cb(shouldCancelAuction, errMsg, ...extraArgs); - } - } - - if (!includes(Object.keys(cmpCallMap), userCMP)) { - done(null, false, `CMP framework (${userCMP}) is not a supported framework. Aborting consentManagement module and resuming auction.`); - return; - } - - const callbacks = { - onSuccess: (data) => done(data, false), - onError: function (msg, ...extraArgs) { - let consentData = null; - let shouldCancelAuction = true; - if (allowAuction.value && cmpVersion === 1) { - // still set the consentData to undefined when there is a problem as per config options - consentData = storeConsentData(undefined); - shouldCancelAuction = false; - } - done(consentData, shouldCancelAuction, msg, ...extraArgs); - } - } - cmpCallMap[userCMP]({ - width, - height, - ...callbacks - }); - - if (!isDone) { - if (consentTimeout === 0) { - processCmpData(undefined, callbacks); - } else { - timer = setTimeout(function () { - if (cmpVersion === 2) { - // for TCFv2, we allow the auction to continue on timeout - done(storeConsentData(undefined), false, `No response from CMP, continuing auction...`) - } else { - callbacks.onError('CMP workflow exceeded timeout threshold.'); - } - }, consentTimeout); - } - } -} - /** * If consentManagement module is enabled (ie included in setConfig), this hook function will attempt to fetch the * user's encoded consent string from the supported CMP. Once obtained, the module will store this @@ -321,67 +269,55 @@ function loadConsentData(cb, width = 1, height = 1) { * @param {function} fn required; The next function in the chain, used by hook.js */ export function requestBidsHook(fn, reqBidsConfigObj) { - const load = (() => { - if (consentData) { - logInfo('User consent information already known. Pulling internally stored information...'); - return function (cb) { - // eslint-disable-next-line standard/no-callback-literal - cb(false); - } - } else { - // find sizes from adUnits object - let adUnits = reqBidsConfigObj.adUnits || $$PREBID_GLOBAL$$.adUnits; - let width = 1; - let height = 1; - if (Array.isArray(adUnits) && adUnits.length > 0) { - let sizes = getAdUnitSizes(adUnits[0]); - width = sizes?.[0]?.[0] || 1; - height = sizes?.[0]?.[1] || 1; - } + // preserves all module related variables for the current auction instance (used primiarily for concurrent auctions) + const hookConfig = { + context: this, + args: [reqBidsConfigObj], + nextFn: fn, + adUnits: reqBidsConfigObj.adUnits || $$PREBID_GLOBAL$$.adUnits, + bidsBackHandler: reqBidsConfigObj.bidsBackHandler, + haveExited: false, + timer: null + }; + + // in case we already have consent (eg during bid refresh) + if (consentData) { + utils.logInfo('User consent information already known. Pulling internally stored information...'); + return exitModule(null, hookConfig); + } - return function (cb) { - loadConsentData(cb, width, height); - } - } - })(); + if (!includes(Object.keys(cmpCallMap), userCMP)) { + utils.logWarn(`CMP framework (${userCMP}) is not a supported framework. Aborting consentManagement module and resuming auction.`); + return hookConfig.nextFn.apply(hookConfig.context, hookConfig.args); + } - load(function (shouldCancelAuction, errMsg, ...extraArgs) { - if (errMsg) { - let log = logWarn; - if (cmpVersion === 1 && !shouldCancelAuction) { - errMsg = `${errMsg} 'allowAuctionWithoutConsent' activated.`; - } else if (shouldCancelAuction) { - log = logError; - errMsg = `${errMsg} Canceling auction as per consentManagement config.`; - } - log(errMsg, ...extraArgs); - } + cmpCallMap[userCMP].call(this, processCmpData, cmpFailed, hookConfig); - if (shouldCancelAuction) { - if (typeof reqBidsConfigObj.bidsBackHandler === 'function') { - reqBidsConfigObj.bidsBackHandler(); - } else { - logError('Error executing bidsBackHandler'); - } + // only let this code run if module is still active (ie if the callbacks used by CMPs haven't already finished) + if (!hookConfig.haveExited) { + if (consentTimeout === 0) { + processCmpData(undefined, hookConfig); } else { - fn.call(this, reqBidsConfigObj); + hookConfig.timer = setTimeout(cmpTimedOut.bind(null, hookConfig), consentTimeout); } - }); + } } /** * This function checks the consent data provided by CMP to ensure it's in an expected state. - * If it's bad, we call `onError` - * If it's good, then we store the value and call `onSuccess` + * If it's bad, we exit the module depending on config settings. + * If it's good, then we store the value and exits the module. + * @param {object} consentObject required; object returned by CMP that contains user's consent choices + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) */ -function processCmpData(consentObject, {onSuccess, onError}) { +function processCmpData(consentObject, hookConfig) { function checkV1Data(consentObject) { let gdprApplies = consentObject && consentObject.getConsentData && consentObject.getConsentData.gdprApplies; return !!( (typeof gdprApplies !== 'boolean') || (gdprApplies === true && - !(isStr(consentObject.getConsentData.consentData) && - isPlainObject(consentObject.getVendorConsents) && + !(utils.isStr(consentObject.getConsentData.consentData) && + utils.isPlainObject(consentObject.getVendorConsents) && Object.keys(consentObject.getVendorConsents).length > 1 ) ) @@ -394,7 +330,7 @@ function processCmpData(consentObject, {onSuccess, onError}) { let tcString = consentObject && consentObject.tcString; return !!( (typeof gdprApplies !== 'boolean') || - (gdprApplies === true && !isStr(tcString)) + (gdprApplies === true && !utils.isStr(tcString)) ); } @@ -410,19 +346,51 @@ function processCmpData(consentObject, {onSuccess, onError}) { // determine which set of checks to run based on cmpVersion let checkFn = (cmpVersion === 1) ? checkV1Data : (cmpVersion === 2) ? checkV2Data : null; - if (isFn(checkFn)) { + // Raise deprecation warning if 'allowAuctionWithoutConsent' is used with TCF 2. + if (allowAuction.definedInConfig && cmpVersion === 2) { + utils.logWarn(`'allowAuctionWithoutConsent' ignored for TCF 2`); + } else if (!allowAuction.definedInConfig && cmpVersion === 1) { + utils.logInfo(`'allowAuctionWithoutConsent' using system default: (${DEFAULT_ALLOW_AUCTION_WO_CONSENT}).`); + } + + if (utils.isFn(checkFn)) { if (checkFn(consentObject)) { - onError(`CMP returned unexpected value during lookup process.`, consentObject); + cmpFailed(`CMP returned unexpected value during lookup process.`, hookConfig, consentObject); } else { - onSuccess(storeConsentData(consentObject)); + clearTimeout(hookConfig.timer); + storeConsentData(consentObject); + exitModule(null, hookConfig); } } else { - onError('Unable to derive CMP version to process data. Consent object does not conform to TCF v1 or v2 specs.', consentObject); + cmpFailed('Unable to derive CMP version to process data. Consent object does not conform to TCF v1 or v2 specs.', hookConfig, consentObject); } } /** - * Stores CMP data locally in module to make information available in adaptermanager.js for later in the auction + * General timeout callback when interacting with CMP takes too long. + */ +function cmpTimedOut(hookConfig) { + cmpFailed('CMP workflow exceeded timeout threshold.', hookConfig); +} + +/** + * This function contains the controlled steps to perform when there's a problem with CMP. + * @param {string} errMsg required; should be a short descriptive message for why the failure/issue happened. + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) + * @param {object} extraArgs contains additional data that's passed along in the error/warning messages for easier debugging +*/ +function cmpFailed(errMsg, hookConfig, extraArgs) { + clearTimeout(hookConfig.timer); + + // still set the consentData to undefined when there is a problem as per config options + if (allowAuction.value && cmpVersion === 1) { + storeConsentData(undefined); + } + exitModule(errMsg, hookConfig, extraArgs); +} + +/** + * Stores CMP data locally in module and then invokes gdprDataHandler.setConsentData() to make information available in adaptermanager.js for later in the auction * @param {object} cmpConsentObject required; an object representing user's consent choices (can be undefined in certain use-cases for this function only) */ function storeConsentData(cmpConsentObject) { @@ -438,12 +406,55 @@ function storeConsentData(cmpConsentObject) { vendorData: (cmpConsentObject) || undefined, gdprApplies: cmpConsentObject && typeof cmpConsentObject.gdprApplies === 'boolean' ? cmpConsentObject.gdprApplies : gdprScope }; - if (cmpConsentObject && cmpConsentObject.addtlConsent && isStr(cmpConsentObject.addtlConsent)) { + if (cmpConsentObject && cmpConsentObject.addtlConsent && utils.isStr(cmpConsentObject.addtlConsent)) { consentData.addtlConsent = cmpConsentObject.addtlConsent; }; } consentData.apiVersion = cmpVersion; - return consentData; + gdprDataHandler.setConsentData(consentData); +} + +/** + * This function handles the exit logic for the module. + * While there are several paths in the module's logic to call this function, we only allow 1 of the 3 potential exits to happen before suppressing others. + * + * We prevent multiple exits to avoid conflicting messages in the console depending on certain scenarios. + * One scenario could be auction was canceled due to timeout with CMP being reached. + * While the timeout is the accepted exit and runs first, the CMP's callback still tries to process the user's data (which normally leads to a good exit). + * In this case, the good exit will be suppressed since we already decided to cancel the auction. + * + * Three exit paths are: + * 1. good exit where auction runs (CMP data is processed normally). + * 2. bad exit but auction still continues (warning message is logged, CMP data is undefined and still passed along). + * 3. bad exit with auction canceled (error message is logged). + * @param {string} errMsg optional; only to be used when there was a 'bad' exit. String is a descriptive message for the failure/issue encountered. + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) + * @param {object} extraArgs contains additional data that's passed along in the error/warning messages for easier debugging + */ +function exitModule(errMsg, hookConfig, extraArgs) { + if (hookConfig.haveExited === false) { + hookConfig.haveExited = true; + + let context = hookConfig.context; + let args = hookConfig.args; + let nextFn = hookConfig.nextFn; + + if (errMsg) { + if (allowAuction.value && cmpVersion === 1) { + utils.logWarn(errMsg + ` 'allowAuctionWithoutConsent' activated.`, extraArgs); + nextFn.apply(context, args); + } else { + utils.logError(errMsg + ' Canceling auction as per consentManagement config.', extraArgs); + if (typeof hookConfig.bidsBackHandler === 'function') { + hookConfig.bidsBackHandler(); + } else { + utils.logError('Error executing bidsBackHandler'); + } + } + } else { + nextFn.apply(context, args); + } + } } /** @@ -453,7 +464,7 @@ export function resetConsentData() { consentData = undefined; userCMP = undefined; cmpVersion = 0; - gdprDataHandler.reset(); + gdprDataHandler.setConsentData(null); } /** @@ -465,21 +476,21 @@ export function setConsentConfig(config) { // else for backward compatability, just use `config` config = config && (config.gdpr || config.usp ? config.gdpr : config); if (!config || typeof config !== 'object') { - logWarn('consentManagement config not defined, exiting consent manager'); + utils.logWarn('consentManagement config not defined, exiting consent manager'); return; } - if (isStr(config.cmpApi)) { + if (utils.isStr(config.cmpApi)) { userCMP = config.cmpApi; } else { userCMP = DEFAULT_CMP; - logInfo(`consentManagement config did not specify cmp. Using system default setting (${DEFAULT_CMP}).`); + utils.logInfo(`consentManagement config did not specify cmp. Using system default setting (${DEFAULT_CMP}).`); } - if (isNumber(config.timeout)) { + if (utils.isNumber(config.timeout)) { consentTimeout = config.timeout; } else { consentTimeout = DEFAULT_CONSENT_TIMEOUT; - logInfo(`consentManagement config did not specify timeout. Using system default setting (${DEFAULT_CONSENT_TIMEOUT}).`); + utils.logInfo(`consentManagement config did not specify timeout. Using system default setting (${DEFAULT_CONSENT_TIMEOUT}).`); } if (typeof config.allowAuctionWithoutConsent === 'boolean') { @@ -490,28 +501,19 @@ export function setConsentConfig(config) { // if true, then gdprApplies should be set to true gdprScope = config.defaultGdprScope === true; - logInfo('consentManagement module has been activated...'); + utils.logInfo('consentManagement module has been activated...'); if (userCMP === 'static') { - if (isPlainObject(config.consentData)) { + if (utils.isPlainObject(config.consentData)) { staticConsentData = config.consentData; consentTimeout = 0; } else { - logError(`consentManagement config with cmpApi: 'static' did not specify consentData. No consents will be available to adapters.`); + utils.logError(`consentManagement config with cmpApi: 'static' did not specify consentData. No consents will be available to adapters.`); } } if (!addedConsentHook) { $$PREBID_GLOBAL$$.requestBids.before(requestBidsHook, 50); } addedConsentHook = true; - gdprDataHandler.enable(); - loadConsentData(); // immediately look up consent data to make it available without requiring an auction - - // Raise deprecation warning if 'allowAuctionWithoutConsent' is used with TCF 2. - if (allowAuction.definedInConfig && cmpVersion === 2) { - logWarn(`'allowAuctionWithoutConsent' ignored for TCF 2`); - } else if (!allowAuction.definedInConfig && cmpVersion === 1) { - logInfo(`'allowAuctionWithoutConsent' using system default: (${DEFAULT_ALLOW_AUCTION_WO_CONSENT}).`); - } } config.getConfig('consentManagement', config => setConsentConfig(config.consentManagement)); diff --git a/modules/consentManagementUsp.js b/modules/consentManagementUsp.js index d6bf913b366..cba9c2758d0 100644 --- a/modules/consentManagementUsp.js +++ b/modules/consentManagementUsp.js @@ -4,7 +4,7 @@ * information and make it available for any USP (CCPA) supported adapters to * read/pass this information to their system. */ -import { isFn, logInfo, logWarn, isStr, isNumber, isPlainObject, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { uspDataHandler } from '../src/adapterManager.js'; @@ -27,17 +27,23 @@ const uspCallMap = { /** * This function reads the consent string from the config to obtain the consent information of the user. + * @param {function(string)} cmpSuccess acts as a success callback when the value is read from config; pass along consentObject (string) from CMP + * @param {function(string)} cmpError acts as an error callback while interacting with the config string; pass along an error message (string) + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) */ -function lookupStaticConsentData({onSuccess, onError}) { - processUspData(staticConsentData, {onSuccess, onError}); +function lookupStaticConsentData(cmpSuccess, cmpError, hookConfig) { + cmpSuccess(staticConsentData, hookConfig); } /** * This function handles interacting with an USP compliant consent manager to obtain the consent information of the user. * Given the async nature of the USP's API, we pass in acting success/error callback functions to exit this function * based on the appropriate result. + * @param {function(string)} uspSuccess acts as a success callback when USPAPI returns a value; pass along consentObject (string) from USPAPI + * @param {function(string)} uspError acts as an error callback while interacting with USPAPI; pass along an error message (string) + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) */ -function lookupUspConsent({onSuccess, onError}) { +function lookupUspConsent(uspSuccess, uspError, hookConfig) { function findUsp() { let f = window; let uspapiFrame; @@ -72,9 +78,9 @@ function lookupUspConsent({onSuccess, onError}) { function afterEach() { if (uspResponse.usPrivacy) { - processUspData(uspResponse, {onSuccess, onError}) + uspSuccess(uspResponse, hookConfig); } else { - onError('Unable to get USP consent string.'); + uspError('Unable to get USP consent string.', hookConfig); } } @@ -94,7 +100,7 @@ function lookupUspConsent({onSuccess, onError}) { let { uspapiFrame, uspapiFunction } = findUsp(); if (!uspapiFrame) { - return onError('USP CMP not found.'); + return uspError('USP CMP not found.', hookConfig); } // to collect the consent information from the user, we perform a call to USPAPI @@ -105,15 +111,15 @@ function lookupUspConsent({onSuccess, onError}) { // - else assume prebid is in an iframe, and use the locator to see if the CMP is located in a higher parent window. This works in cross domain iframes. // - if USPAPI is not found, the iframe function will call the uspError exit callback to abort the rest of the USPAPI workflow - if (isFn(uspapiFunction)) { - logInfo('Detected USP CMP is directly accessible, calling it now...'); + if (utils.isFn(uspapiFunction)) { + utils.logInfo('Detected USP CMP is directly accessible, calling it now...'); uspapiFunction( 'getUSPData', USPAPI_VERSION, callbackHandler.consentDataCallback ); } else { - logInfo( + utils.logInfo( 'Detected USP CMP is outside the current iframe where Prebid.js is located, calling it now...' ); callUspApiWhileInIframe( @@ -159,92 +165,119 @@ function lookupUspConsent({onSuccess, onError}) { } /** - * Lookup consent data and store it in the `consentData` global as well as `adapterManager.js`' uspDataHanlder. - * - * @param cb a callback that takes an error message and extra error arguments; all args will be undefined if consent - * data was retrieved successfully. + * If consentManagementUSP module is enabled (ie included in setConfig), this hook function will attempt to fetch the + * user's encoded consent string from the supported USPAPI. Once obtained, the module will store this + * data as part of a uspConsent object which gets transferred to adapterManager's uspDataHandler object. + * This information is later added into the bidRequest object for any supported adapters to read/pass along to their system. + * @param {object} reqBidsConfigObj required; This is the same param that's used in pbjs.requestBids. + * @param {function} fn required; The next function in the chain, used by hook.js */ -function loadConsentData(cb) { - let timer = null; - let isDone = false; - - function done(consentData, errMsg, ...extraArgs) { - if (timer != null) { - clearTimeout(timer); - } - isDone = true; - uspDataHandler.setConsentData(consentData); - if (cb != null) { - cb(errMsg, ...extraArgs) - } - } +export function requestBidsHook(fn, reqBidsConfigObj) { + // preserves all module related variables for the current auction instance (used primiarily for concurrent auctions) + const hookConfig = { + context: this, + args: [reqBidsConfigObj], + nextFn: fn, + adUnits: reqBidsConfigObj.adUnits || $$PREBID_GLOBAL$$.adUnits, + bidsBackHandler: reqBidsConfigObj.bidsBackHandler, + haveExited: false, + timer: null + }; if (!uspCallMap[consentAPI]) { - done(null, `USP framework (${consentAPI}) is not a supported framework. Aborting consentManagement module and resuming auction.`); - return; - } - - const callbacks = { - onSuccess: done, - onError: function (errMsg, ...extraArgs) { - done(null, `${errMsg} Resuming auction without consent data as per consentManagement config.`, ...extraArgs); - } + utils.logWarn(`USP framework (${consentAPI}) is not a supported framework. Aborting consentManagement module and resuming auction.`); + return hookConfig.nextFn.apply(hookConfig.context, hookConfig.args); } - uspCallMap[consentAPI](callbacks); + uspCallMap[consentAPI].call(this, processUspData, uspapiFailed, hookConfig); - if (!isDone) { + // only let this code run if module is still active (ie if the callbacks used by USPs haven't already finished) + if (!hookConfig.haveExited) { if (consentTimeout === 0) { - processUspData(undefined, callbacks); + processUspData(undefined, hookConfig); } else { - timer = setTimeout(callbacks.onError.bind(null, 'USPAPI workflow exceeded timeout threshold.'), consentTimeout) + hookConfig.timer = setTimeout(uspapiTimeout.bind(null, hookConfig), consentTimeout); } } } -/** - * If consentManagementUSP module is enabled (ie included in setConfig), this hook function will attempt to fetch the - * user's encoded consent string from the supported USPAPI. Once obtained, the module will store this - * data as part of a uspConsent object which gets transferred to adapterManager's uspDataHandler object. - * This information is later added into the bidRequest object for any supported adapters to read/pass along to their system. - * @param {object} reqBidsConfigObj required; This is the same param that's used in pbjs.requestBids. - * @param {function} fn required; The next function in the chain, used by hook.js - */ -export function requestBidsHook(fn, reqBidsConfigObj) { - loadConsentData((errMsg, ...extraArgs) => { - if (errMsg != null) { - logWarn(errMsg, ...extraArgs); - } - fn.call(this, reqBidsConfigObj); - }); -} - /** * This function checks the consent data provided by USPAPI to ensure it's in an expected state. * If it's bad, we exit the module depending on config settings. * If it's good, then we store the value and exits the module. * @param {object} consentObject required; object returned by USPAPI that contains user's consent choices - * @param {function(string)} onSuccess callback accepting the resolved consent USP consent string - * @param {function(string, ...{}?)} onError callback accepting error message and any extra error arguments (used purely for logging) + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) */ -function processUspData(consentObject, {onSuccess, onError}) { +function processUspData(consentObject, hookConfig) { const valid = !!(consentObject && consentObject.usPrivacy); if (!valid) { - onError(`USPAPI returned unexpected value during lookup process.`, consentObject); + uspapiFailed(`USPAPI returned unexpected value during lookup process.`, hookConfig, consentObject); return; } + clearTimeout(hookConfig.timer); storeUspConsentData(consentObject); - onSuccess(consentData); + exitModule(null, hookConfig); +} + +/** + * General timeout callback when interacting with USPAPI takes too long. + */ +function uspapiTimeout(hookConfig) { + uspapiFailed('USPAPI workflow exceeded timeout threshold.', hookConfig); +} + +/** + * This function contains the controlled steps to perform when there's a problem with USPAPI. + * @param {string} errMsg required; should be a short descriptive message for why the failure/issue happened. + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) + * @param {object} extraArgs contains additional data that's passed along in the error/warning messages for easier debugging +*/ +function uspapiFailed(errMsg, hookConfig, extraArgs) { + clearTimeout(hookConfig.timer); + + exitModule(errMsg, hookConfig, extraArgs); } /** * Stores USP data locally in module and then invokes uspDataHandler.setConsentData() to make information available in adaptermanger.js for later in the auction - * @param {object} consentObject required; an object representing user's consent choices (can be undefined in certain use-cases for this function only) + * @param {object} cmpConsentObject required; an object representing user's consent choices (can be undefined in certain use-cases for this function only) */ function storeUspConsentData(consentObject) { if (consentObject && consentObject.usPrivacy) { consentData = consentObject.usPrivacy; + uspDataHandler.setConsentData(consentData); + } +} + +/** + * This function handles the exit logic for the module. + * There are a couple paths in the module's logic to call this function and we only allow 1 of the 2 potential exits to happen before suppressing others. + * + * We prevent multiple exits to avoid conflicting messages in the console depending on certain scenarios. + * One scenario could be auction was canceled due to timeout with USPAPI being reached. + * While the timeout is the accepted exit and runs first, the USP's callback still tries to process the user's data (which normally leads to a good exit). + * In this case, the good exit will be suppressed since we already decided to cancel the auction. + * + * Three exit paths are: + * 1. good exit where auction runs (USPAPI data is processed normally). + * 2. bad exit but auction still continues (warning message is logged, USPAPI data is undefined and still passed along). + * @param {string} errMsg optional; only to be used when there was a 'bad' exit. String is a descriptive message for the failure/issue encountered. + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) + * @param {object} extraArgs contains additional data that's passed along in the error/warning messages for easier debugging + */ +function exitModule(errMsg, hookConfig, extraArgs) { + if (hookConfig.haveExited === false) { + hookConfig.haveExited = true; + + let context = hookConfig.context; + let args = hookConfig.args; + let nextFn = hookConfig.nextFn; + + if (errMsg) { + utils.logWarn(errMsg + ' Resuming auction without consent data as per consentManagement config.', extraArgs); + } + nextFn.apply(context, args); } } @@ -254,7 +287,7 @@ function storeUspConsentData(consentObject) { export function resetConsentData() { consentData = undefined; consentAPI = undefined; - uspDataHandler.reset(); + uspDataHandler.setConsentData(null); } /** @@ -264,38 +297,36 @@ export function resetConsentData() { export function setConsentConfig(config) { config = config && config.usp; if (!config || typeof config !== 'object') { - logWarn('consentManagement.usp config not defined, exiting usp consent manager'); + utils.logWarn('consentManagement.usp config not defined, exiting usp consent manager'); return; } - if (isStr(config.cmpApi)) { + if (utils.isStr(config.cmpApi)) { consentAPI = config.cmpApi; } else { consentAPI = DEFAULT_CONSENT_API; - logInfo(`consentManagement.usp config did not specify cmpApi. Using system default setting (${DEFAULT_CONSENT_API}).`); + utils.logInfo(`consentManagement.usp config did not specify cmpApi. Using system default setting (${DEFAULT_CONSENT_API}).`); } - if (isNumber(config.timeout)) { + if (utils.isNumber(config.timeout)) { consentTimeout = config.timeout; } else { consentTimeout = DEFAULT_CONSENT_TIMEOUT; - logInfo(`consentManagement.usp config did not specify timeout. Using system default setting (${DEFAULT_CONSENT_TIMEOUT}).`); + utils.logInfo(`consentManagement.usp config did not specify timeout. Using system default setting (${DEFAULT_CONSENT_TIMEOUT}).`); } - logInfo('USPAPI consentManagement module has been activated...'); + utils.logInfo('USPAPI consentManagement module has been activated...'); if (consentAPI === 'static') { - if (isPlainObject(config.consentData) && isPlainObject(config.consentData.getUSPData)) { + if (utils.isPlainObject(config.consentData) && utils.isPlainObject(config.consentData.getUSPData)) { if (config.consentData.getUSPData.uspString) staticConsentData = { usPrivacy: config.consentData.getUSPData.uspString }; consentTimeout = 0; } else { - logError(`consentManagement config with cmpApi: 'static' did not specify consentData. No consents will be available to adapters.`); + utils.logError(`consentManagement config with cmpApi: 'static' did not specify consentData. No consents will be available to adapters.`); } } if (!addedConsentHook) { $$PREBID_GLOBAL$$.requestBids.before(requestBidsHook, 50); } addedConsentHook = true; - uspDataHandler.enable(); - loadConsentData(); // immediately look up consent data to make it available without requiring an auction } config.getConfig('consentManagement', config => setConsentConfig(config.consentManagement)); diff --git a/modules/consumableBidAdapter.js b/modules/consumableBidAdapter.js index de08fc8677a..92e2192b925 100644 --- a/modules/consumableBidAdapter.js +++ b/modules/consumableBidAdapter.js @@ -1,4 +1,4 @@ -import { logWarn, createTrackPixelHtml } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'consumable'; @@ -122,30 +122,10 @@ export const spec = { bid.currency = 'USD'; bid.creativeId = decision.adId; bid.ttl = 30; + bid.meta = { advertiserDomains: decision.adomain ? decision.adomain : [] } bid.netRevenue = true; bid.referrer = bidRequest.bidderRequest.refererInfo.referer; - bid.meta = { - advertiserDomains: decision.adomain || [] - }; - - if (decision.cats) { - if (decision.cats.length > 0) { - bid.meta.primaryCatId = decision.cats[0]; - if (decision.cats.length > 1) { - bid.meta.secondaryCatIds = decision.cats.slice(1); - } - } - } - - if (decision.networkId) { - bid.meta.networkId = decision.networkId; - } - - if (decision.mediaType) { - bid.meta.mediaType = decision.mediaType; - } - bidResponses.push(bid); } } @@ -156,18 +136,16 @@ export const spec = { getUserSyncs: function(syncOptions, serverResponses) { if (syncOptions.iframeEnabled) { - if (!serverResponses || serverResponses.length === 0 || !serverResponses[0].body.bdr || serverResponses[0].body.bdr !== 'cx') { - return [{ - type: 'iframe', - url: 'https://sync.serverbid.com/ss/' + siteId + '.html' - }]; - } + return [{ + type: 'iframe', + url: 'https://sync.serverbid.com/ss/' + siteId + '.html' + }]; } - if (syncOptions.pixelEnabled && serverResponses && serverResponses.length > 0) { + if (syncOptions.pixelEnabled && serverResponses.length > 0) { return serverResponses[0].body.pixels; } else { - logWarn(bidder + ': Please enable iframe based user syncing.'); + utils.logWarn(bidder + ': Please enable iframe based user syncing.'); } } }; @@ -229,7 +207,7 @@ function getSize(sizes) { } function retrieveAd(decision, unitId, unitName) { - let ad = decision.contents && decision.contents[0] && decision.contents[0].body + createTrackPixelHtml(decision.impressionUrl); + let ad = decision.contents && decision.contents[0] && decision.contents[0].body + utils.createTrackPixelHtml(decision.impressionUrl); return ad; } diff --git a/modules/consumableBidAdapter.md b/modules/consumableBidAdapter.md index ba472899c49..2189494ebd4 100644 --- a/modules/consumableBidAdapter.md +++ b/modules/consumableBidAdapter.md @@ -4,7 +4,7 @@ Module Name: Consumable Bid Adapter Module Type: Consumable Adapter -Maintainer: prebid@consumable.com +Maintainer: naffis@consumable.com # Description diff --git a/modules/contentexchangeBidAdapter.js b/modules/contentexchangeBidAdapter.js index b3a5056f816..de4cf8df933 100644 --- a/modules/contentexchangeBidAdapter.js +++ b/modules/contentexchangeBidAdapter.js @@ -1,6 +1,6 @@ -import { isFn, deepAccess, logMessage } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; const BIDDER_CODE = 'contentexchange'; @@ -69,8 +69,8 @@ function getPlacementReqData (bid) { } function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidfloor', 0); + if (!utils.isFn(bid.getFloor)) { + return utils.deepAccess(bid, 'params.bidfloor', 0); } try { @@ -123,7 +123,7 @@ export const spec = { deviceHeight = winTop.screen.height; winLocation = winTop.location; } catch (e) { - logMessage(e); + utils.logMessage(e); winLocation = window.location; } @@ -132,7 +132,7 @@ export const spec = { try { refferLocation = refferUrl && new URL(refferUrl); } catch (e) { - logMessage(e); + utils.logMessage(e); } let location = refferLocation || winLocation; diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index 7ee8b1b7681..a1ca094273b 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -1,13 +1,12 @@ -import { logWarn, isStr, deepAccess, isArray, getBidIdParameter, deepSetValue, isEmpty, _each, convertTypes, parseUrl, mergeDeep, buildUrl, _map, logError, isFn, isPlainObject } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {getStorageManager} from '../src/storageManager.js'; -import { config } from '../src/config.js'; const GVLID = 24; +export const storage = getStorageManager(GVLID); const BIDDER_CODE = 'conversant'; -export const storage = getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE}); const URL = 'https://web.hb.ad.cpe.dotomi.com/cvx/client/hb/ortb/25'; export const spec = { @@ -24,22 +23,22 @@ export const spec = { */ isBidRequestValid: function(bid) { if (!bid || !bid.params) { - logWarn(BIDDER_CODE + ': Missing bid parameters'); + utils.logWarn(BIDDER_CODE + ': Missing bid parameters'); return false; } - if (!isStr(bid.params.site_id)) { - logWarn(BIDDER_CODE + ': site_id must be specified as a string'); + if (!utils.isStr(bid.params.site_id)) { + utils.logWarn(BIDDER_CODE + ': site_id must be specified as a string'); return false; } if (isVideoRequest(bid)) { - const mimes = bid.params.mimes || deepAccess(bid, 'mediaTypes.video.mimes'); + const mimes = bid.params.mimes || utils.deepAccess(bid, 'mediaTypes.video.mimes'); if (!mimes) { // Give a warning but let it pass - logWarn(BIDDER_CODE + ': mimes should be specified for videos'); - } else if (!isArray(mimes) || !mimes.every(s => isStr(s))) { - logWarn(BIDDER_CODE + ': mimes must be an array of strings'); + utils.logWarn(BIDDER_CODE + ': mimes should be specified for videos'); + } else if (!utils.isArray(mimes) || !mimes.every(s => utils.isStr(s))) { + utils.logWarn(BIDDER_CODE + ': mimes must be an array of strings'); return false; } } @@ -65,8 +64,8 @@ export const spec = { const conversantImps = validBidRequests.map(function(bid) { const bidfloor = getBidFloor(bid); - siteId = getBidIdParameter('site_id', bid.params) || siteId; - pubcidName = getBidIdParameter('pubcid_name', bid.params) || pubcidName; + siteId = utils.getBidIdParameter('site_id', bid.params) || siteId; + pubcidName = utils.getBidIdParameter('pubcid_name', bid.params) || pubcidName; requestId = bid.auctionId; @@ -77,14 +76,11 @@ export const spec = { displaymanager: 'Prebid.js', displaymanagerver: '$prebid.version$' }; - if (bid.ortb2Imp) { - mergeDeep(imp, bid.ortb2Imp); - } copyOptProperty(bid.params.tag_id, imp, 'tagid'); if (isVideoRequest(bid)) { - const videoData = deepAccess(bid, 'mediaTypes.video') || {}; + const videoData = utils.deepAccess(bid, 'mediaTypes.video') || {}; const format = convertSizes(videoData.playerSize || bid.sizes); const video = {}; @@ -101,7 +97,7 @@ export const spec = { imp.video = video; } else { - const bannerData = deepAccess(bid, 'mediaTypes.banner') || {}; + const bannerData = utils.deepAccess(bid, 'mediaTypes.banner') || {}; const format = convertSizes(bannerData.sizes || bid.sizes); const banner = {format: format}; @@ -136,24 +132,18 @@ export const spec = { let userExt = {}; - // pass schain object if it is present - const schain = deepAccess(validBidRequests, '0.schain'); - if (schain) { - deepSetValue(payload, 'source.ext.schain', schain); - } - if (bidderRequest) { // Add GDPR flag and consent string if (bidderRequest.gdprConsent) { userExt.consent = bidderRequest.gdprConsent.consentString; if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { - deepSetValue(payload, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies ? 1 : 0); + utils.deepSetValue(payload, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies ? 1 : 0); } } if (bidderRequest.uspConsent) { - deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); } } @@ -173,13 +163,10 @@ export const spec = { } // Only add the user object if it's not empty - if (!isEmpty(userExt)) { + if (!utils.isEmpty(userExt)) { payload.user = {ext: userExt}; } - const firstPartyData = config.getConfig('ortb2') || {}; - mergeDeep(payload, firstPartyData); - return { method: 'POST', url: bidurl, @@ -199,12 +186,12 @@ export const spec = { serverResponse = serverResponse.body; if (bidRequest && bidRequest.data && bidRequest.data.imp) { - _each(bidRequest.data.imp, imp => requestMap[imp.id] = imp); + utils._each(bidRequest.data.imp, imp => requestMap[imp.id] = imp); } - if (serverResponse && isArray(serverResponse.seatbid)) { - _each(serverResponse.seatbid, function(bidList) { - _each(bidList.bid, function(conversantBid) { + if (serverResponse && utils.isArray(serverResponse.seatbid)) { + utils._each(serverResponse.seatbid, function(bidList) { + utils._each(bidList.bid, function(conversantBid) { const responseCPM = parseFloat(conversantBid.price); if (responseCPM > 0.0 && conversantBid.impid) { const responseAd = conversantBid.adm || ''; @@ -256,7 +243,7 @@ export const spec = { * @return {Object} params bid params */ transformBidParams: function(params, isOpenRtb) { - return convertTypes({ + return utils.convertTypes({ 'site_id': 'string', 'secure': 'number', 'mobile': 'number' @@ -290,12 +277,12 @@ export const spec = { }) .map((entry) => { return entry.urls.map((endpoint) => { - let urlInfo = parseUrl(endpoint); - mergeDeep(urlInfo.search, params); + let urlInfo = utils.parseUrl(endpoint); + utils.mergeDeep(urlInfo.search, params); if (Object.keys(urlInfo.search).length === 0) { delete urlInfo.search; // empty search object causes buildUrl to add a trailing ? to the url } - return {type: entry.type, url: buildUrl(urlInfo)}; + return {type: entry.type, url: utils.buildUrl(urlInfo)}; }) .reduce((x, y) => x.concat(y), []); }) @@ -346,7 +333,7 @@ function convertSizes(bidSizes) { if (bidSizes.length === 2 && typeof bidSizes[0] === 'number' && typeof bidSizes[1] === 'number') { format = [{w: bidSizes[0], h: bidSizes[1]}]; } else { - format = _map(bidSizes, d => { return {w: d[0], h: d[1]}; }); + format = utils._map(bidSizes, d => { return {w: d[0], h: d[1]}; }); } } @@ -360,7 +347,7 @@ function convertSizes(bidSizes) { * @returns {boolean} True if it's a video bid */ function isVideoRequest(bid) { - return bid.mediaType === 'video' || !!deepAccess(bid, 'mediaTypes.video'); + return bid.mediaType === 'video' || !!utils.deepAccess(bid, 'mediaTypes.video'); } /** @@ -383,10 +370,9 @@ function copyOptProperty(src, dst, dstName) { function collectEids(bidRequests) { const request = bidRequests[0]; // bidRequests have the same userId object const eids = []; - if (isArray(request.userIdAsEids) && request.userIdAsEids.length > 0) { + if (utils.isArray(request.userIdAsEids) && request.userIdAsEids.length > 0) { // later following white-list can be converted to block-list if needed const requiredSourceValues = { - 'epsilon.com': 1, 'adserver.org': 1, 'liveramp.com': 1, 'criteo.com': 1, @@ -424,11 +410,11 @@ function readStoredValue(key) { } // deserialize JSON if needed - if (isStr(storedValue) && storedValue.charAt(0) === '{') { + if (utils.isStr(storedValue) && storedValue.charAt(0) === '{') { storedValue = JSON.parse(storedValue); } } catch (e) { - logError(e); + utils.logError(e); } return storedValue; @@ -441,16 +427,16 @@ function readStoredValue(key) { * @returns {*|number} floor price */ function getBidFloor(bid) { - let floor = getBidIdParameter('bidfloor', bid.params); + let floor = utils.getBidIdParameter('bidfloor', bid.params); - if (!floor && isFn(bid.getFloor)) { + if (!floor && utils.isFn(bid.getFloor)) { const floorObj = bid.getFloor({ currency: 'USD', mediaType: '*', size: '*' }); - if (isPlainObject(floorObj) && !isNaN(floorObj.floor) && floorObj.currency === 'USD') { + if (utils.isPlainObject(floorObj) && !isNaN(floorObj.floor) && floorObj.currency === 'USD') { floor = floorObj.floor; } } diff --git a/modules/cpmstarBidAdapter.js b/modules/cpmstarBidAdapter.js index 75a7007ee36..14c0d43add7 100755 --- a/modules/cpmstarBidAdapter.js +++ b/modules/cpmstarBidAdapter.js @@ -1,4 +1,5 @@ -import { deepAccess, getBidIdParameter, logWarn, logError } from '../src/utils.js'; + +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { VIDEO, BANNER } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; @@ -25,11 +26,11 @@ export const spec = { getMediaType: function (bidRequest) { if (bidRequest == null) return BANNER; - return !deepAccess(bidRequest, 'mediaTypes.video') ? BANNER : VIDEO; + return !utils.deepAccess(bidRequest, 'mediaTypes.video') ? BANNER : VIDEO; }, getPlayerSize: function (bidRequest) { - var playerSize = deepAccess(bidRequest, 'mediaTypes.video.playerSize'); + var playerSize = utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize'); if (playerSize == null) return [640, 440]; if (playerSize[0] != null) playerSize = playerSize[0]; if (playerSize == null || playerSize[0] == null || playerSize[1] == null) return [640, 440]; @@ -47,13 +48,13 @@ export const spec = { for (var i = 0; i < validBidRequests.length; i++) { var bidRequest = validBidRequests[i]; var referer = encodeURIComponent(bidderRequest.refererInfo.referer); - var e = getBidIdParameter('endpoint', bidRequest.params); + var e = utils.getBidIdParameter('endpoint', bidRequest.params); var ENDPOINT = e == 'dev' ? ENDPOINT_DEV : e == 'staging' ? ENDPOINT_STAGING : ENDPOINT_PRODUCTION; var mediaType = spec.getMediaType(bidRequest); var playerSize = spec.getPlayerSize(bidRequest); var videoArgs = '&fv=0' + (playerSize ? ('&w=' + playerSize[0] + '&h=' + playerSize[1]) : ''); var url = ENDPOINT + '?media=' + mediaType + (mediaType == VIDEO ? videoArgs : '') + - '&json=c_b&mv=1&poolid=' + getBidIdParameter('placementId', bidRequest.params) + + '&json=c_b&mv=1&poolid=' + utils.getBidIdParameter('placementId', bidRequest.params) + '&reachedTop=' + encodeURIComponent(bidderRequest.refererInfo.reachedTop) + '&requestid=' + bidRequest.bidId + '&referer=' + encodeURIComponent(referer); @@ -116,13 +117,13 @@ export const spec = { var raw = serverResponse.body[i]; var rawBid = raw.creatives[0]; if (!rawBid) { - logWarn('cpmstarBidAdapter: server response failed check'); + utils.logWarn('cpmstarBidAdapter: server response failed check'); return; } var cpm = (parseFloat(rawBid.cpm) || 0); if (!cpm) { - logWarn('cpmstarBidAdapter: server response failed check. Missing cpm') + utils.logWarn('cpmstarBidAdapter: server response failed check. Missing cpm') return; } @@ -155,7 +156,7 @@ export const spec = { bidResponse.mediaType = VIDEO; bidResponse.vastXml = rawBid.creativemacros.HTML5VID_VASTSTRING; } else { - return logError('bad response', rawBid); + return utils.logError('bad response', rawBid); } bidResponses.push(bidResponse); diff --git a/modules/craftBidAdapter.js b/modules/craftBidAdapter.js index 61ca4f929e7..0124f96a107 100644 --- a/modules/craftBidAdapter.js +++ b/modules/craftBidAdapter.js @@ -1,24 +1,15 @@ -import { - convertCamelToUnderscore, - convertTypes, - deepAccess, - getBidRequest, - isArray, - isEmpty, - logError, - transformBidderParamKeywords -} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {auctionManager} from '../src/auctionManager.js'; -import {find, includes} from '../src/polyfill.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {ajax} from '../src/ajax.js'; +import * as utils from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { auctionManager } from '../src/auctionManager.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import { getStorageManager } from '../src/storageManager.js'; const BIDDER_CODE = 'craft'; const URL_BASE = 'https://gacraft.jp/prebid-v3'; const TTL = 360; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); +const storage = getStorageManager(); export const spec = { code: BIDDER_CODE, @@ -76,7 +67,7 @@ export const spec = { if (serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } - logError(errorMessage); + utils.logError(errorMessage); return bids; } if (serverResponse.tags) { @@ -98,17 +89,17 @@ export const spec = { }, transformBidParams: function(params, isOpenRtb) { - params = convertTypes({ + params = utils.convertTypes({ 'sitekey': 'string', 'placementId': 'string', - 'keywords': transformBidderParamKeywords + 'keywords': utils.transformBidderParamKeywords }, params); if (isOpenRtb) { if (isPopulatedArray(params.keywords)) { params.keywords.forEach(deleteValues); } Object.keys(params).forEach(paramKey => { - let convertedKey = convertCamelToUnderscore(paramKey); + let convertedKey = utils.convertCamelToUnderscore(paramKey); if (convertedKey !== paramKey) { params[convertedKey] = params[paramKey]; delete params[paramKey]; @@ -119,15 +110,14 @@ export const spec = { }, onBidWon: function(bid) { - ajax(bid._prebidWon, null, null, { - method: 'POST', - contentType: 'application/json' - }); + var xhr = new XMLHttpRequest(); + xhr.open('POST', bid._prebidWon); + xhr.send(); } }; function isPopulatedArray(arr) { - return !!(isArray(arr) && arr.length > 0); + return !!(utils.isArray(arr) && arr.length > 0); } function deleteValues(keyPairObj) { @@ -140,7 +130,7 @@ function hasPurpose1Consent(bidderRequest) { let result = true; if (bidderRequest && bidderRequest.gdprConsent) { if (bidderRequest.gdprConsent.gdprApplies && bidderRequest.gdprConsent.apiVersion === 2) { - result = !!(deepAccess(bidderRequest.gdprConsent, 'vendorData.purpose.consents.1') === true); + result = !!(utils.deepAccess(bidderRequest.gdprConsent, 'vendorData.purpose.consents.1') === true); } } return result; @@ -165,7 +155,7 @@ function formatRequest(payload, bidderRequest) { } function newBid(serverBid, rtbBid, bidderRequest) { - const bidRequest = getBidRequest(serverBid.uuid, [bidderRequest]); + const bidRequest = utils.getBidRequest(serverBid.uuid, [bidderRequest]); const bid = { requestId: serverBid.uuid, cpm: rtbBid.cpm, @@ -200,8 +190,8 @@ function bidToTag(bid) { tag.primary_size = tag.sizes[0]; tag.ad_types = []; tag.uuid = bid.bidId; - if (!isEmpty(bid.params.keywords)) { - let keywords = transformBidderParamKeywords(bid.params.keywords); + if (!utils.isEmpty(bid.params.keywords)) { + let keywords = utils.transformBidderParamKeywords(bid.params.keywords); if (keywords.length > 0) { keywords.forEach(deleteValues); } diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 1ad693fcaab..363b9322204 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -1,9 +1,9 @@ -import { deepAccess, getUniqueIdentifierStr, isArray, logError, logInfo, logWarn, parseUrl } from '../src/utils.js'; -import { loadExternalScript } from '../src/adloader.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { config } from '../src/config.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { find } from '../src/polyfill.js'; +import {loadExternalScript} from '../src/adloader.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {config} from '../src/config.js'; +import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; +import find from 'core-js-pure/features/array/find.js'; import { verify } from 'criteo-direct-rsa-validate/build/verify.js'; // ref#2 import { getStorageManager } from '../src/storageManager.js'; @@ -13,7 +13,7 @@ const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = 'https://bidder.criteo.com/cdb'; const PROFILE_ID_INLINE = 207; export const PROFILE_ID_PUBLISHERTAG = 185; -const storage = getStorageManager({ gvlid: GVLID, bidderCode: BIDDER_CODE }); +const storage = getStorageManager(GVLID); const LOG_PREFIX = 'Criteo: '; /* @@ -24,7 +24,7 @@ const LOG_PREFIX = 'Criteo: '; Unminified source code can be found in the privately shared repo: https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js */ const FAST_BID_VERSION_PLACEHOLDER = '%FAST_BID_VERSION%'; -export const FAST_BID_VERSION_CURRENT = 117; +export const FAST_BID_VERSION_CURRENT = 105; const FAST_BID_VERSION_LATEST = 'latest'; const FAST_BID_VERSION_NONE = 'none'; const PUBLISHER_TAG_URL_TEMPLATE = 'https://static.criteo.net/js/ld/publishertag.prebid' + FAST_BID_VERSION_PLACEHOLDER + '.js'; @@ -35,7 +35,7 @@ const FAST_BID_PUBKEY_N = 'ztQYwCE5BU7T9CDM5he6rKoabstXRmkzx54zFPZkWbK530dwtLBDe export const spec = { code: BIDDER_CODE, gvlid: GVLID, - supportedMediaTypes: [BANNER, VIDEO, NATIVE], + supportedMediaTypes: [ BANNER, VIDEO, NATIVE ], /** f * @param {object} bid @@ -65,11 +65,11 @@ export const spec = { buildRequests: (bidRequests, bidderRequest) => { let url; let data; - let fpd = config.getConfig('ortb2') || {}; + let fpd = config.getLegacyFpd(config.getConfig('ortb2')) || {}; Object.assign(bidderRequest, { - publisherExt: fpd.site?.ext, - userExt: fpd.user?.ext, + publisherExt: fpd.context, + userExt: fpd.user, ceh: config.getConfig('criteo.ceh') }); @@ -123,13 +123,13 @@ export const spec = { const bids = []; - if (body && body.slots && isArray(body.slots)) { + if (body && body.slots && utils.isArray(body.slots)) { body.slots.forEach(slot => { const bidRequest = find(request.bidRequests, b => b.adUnitCode === slot.impid && (!b.params.zoneId || parseInt(b.params.zoneId) === slot.zoneid)); const bidId = bidRequest.bidId; const bid = { requestId: bidId, - adId: slot.bidId || getUniqueIdentifierStr(), + adId: slot.bidId || utils.getUniqueIdentifierStr(), cpm: slot.cpm, currency: slot.currency, netRevenue: true, @@ -219,7 +219,7 @@ function buildContext(bidRequests, bidderRequest) { if (bidderRequest && bidderRequest.refererInfo) { referrer = bidderRequest.refererInfo.referer; } - const queryString = parseUrl(referrer).search; + const queryString = utils.parseUrl(referrer).search; const context = { url: referrer, @@ -265,11 +265,11 @@ function checkNativeSendId(bidRequest) { return !(bidRequest.nativeParams && ( (bidRequest.nativeParams.image && ((bidRequest.nativeParams.image.sendId !== true || bidRequest.nativeParams.image.sendTargetingKeys === true))) || - (bidRequest.nativeParams.icon && ((bidRequest.nativeParams.icon.sendId !== true || bidRequest.nativeParams.icon.sendTargetingKeys === true))) || - (bidRequest.nativeParams.clickUrl && ((bidRequest.nativeParams.clickUrl.sendId !== true || bidRequest.nativeParams.clickUrl.sendTargetingKeys === true))) || - (bidRequest.nativeParams.displayUrl && ((bidRequest.nativeParams.displayUrl.sendId !== true || bidRequest.nativeParams.displayUrl.sendTargetingKeys === true))) || - (bidRequest.nativeParams.privacyLink && ((bidRequest.nativeParams.privacyLink.sendId !== true || bidRequest.nativeParams.privacyLink.sendTargetingKeys === true))) || - (bidRequest.nativeParams.privacyIcon && ((bidRequest.nativeParams.privacyIcon.sendId !== true || bidRequest.nativeParams.privacyIcon.sendTargetingKeys === true))) + (bidRequest.nativeParams.icon && ((bidRequest.nativeParams.icon.sendId !== true || bidRequest.nativeParams.icon.sendTargetingKeys === true))) || + (bidRequest.nativeParams.clickUrl && ((bidRequest.nativeParams.clickUrl.sendId !== true || bidRequest.nativeParams.clickUrl.sendTargetingKeys === true))) || + (bidRequest.nativeParams.displayUrl && ((bidRequest.nativeParams.displayUrl.sendId !== true || bidRequest.nativeParams.displayUrl.sendTargetingKeys === true))) || + (bidRequest.nativeParams.privacyLink && ((bidRequest.nativeParams.privacyLink.sendId !== true || bidRequest.nativeParams.privacyLink.sendTargetingKeys === true))) || + (bidRequest.nativeParams.privacyIcon && ((bidRequest.nativeParams.privacyIcon.sendId !== true || bidRequest.nativeParams.privacyIcon.sendTargetingKeys === true))) )); } @@ -281,15 +281,13 @@ function checkNativeSendId(bidRequest) { */ function buildCdbRequest(context, bidRequests, bidderRequest) { let networkId; - let schain; const request = { publisher: { url: context.url, - ext: bidderRequest.publisherExt, + ext: bidderRequest.publisherExt }, slots: bidRequests.map(bidRequest => { networkId = bidRequest.params.networkId || networkId; - schain = bidRequest.schain || schain; const slot = { impid: bidRequest.adUnitCode, transactionid: bidRequest.transactionId, @@ -298,7 +296,7 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { if (bidRequest.params.zoneId) { slot.zoneid = bidRequest.params.zoneId; } - if (deepAccess(bidRequest, 'ortb2Imp.ext')) { + if (utils.deepAccess(bidRequest, 'ortb2Imp.ext')) { slot.ext = bidRequest.ortb2Imp.ext; } if (bidRequest.params.ext) { @@ -307,36 +305,28 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { if (bidRequest.params.publisherSubId) { slot.publishersubid = bidRequest.params.publisherSubId; } - if (bidRequest.params.nativeCallback || deepAccess(bidRequest, `mediaTypes.${NATIVE}`)) { + if (bidRequest.params.nativeCallback || utils.deepAccess(bidRequest, `mediaTypes.${NATIVE}`)) { slot.native = true; if (!checkNativeSendId(bidRequest)) { - logWarn(LOG_PREFIX + 'all native assets containing URL should be sent as placeholders with sendId(icon, image, clickUrl, displayUrl, privacyLink, privacyIcon)'); + utils.logWarn(LOG_PREFIX + 'all native assets containing URL should be sent as placeholders with sendId(icon, image, clickUrl, displayUrl, privacyLink, privacyIcon)'); } - slot.sizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes'), parseNativeSize); + slot.sizes = parseSizes(retrieveBannerSizes(bidRequest), parseNativeSize); } else { - slot.sizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes'), parseSize); + slot.sizes = parseSizes(retrieveBannerSizes(bidRequest), parseSize); } if (hasVideoMediaType(bidRequest)) { const video = { - playersizes: parseSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize'), parseSize), + playersizes: parseSizes(utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize'), parseSize), mimes: bidRequest.mediaTypes.video.mimes, protocols: bidRequest.mediaTypes.video.protocols, maxduration: bidRequest.mediaTypes.video.maxduration, api: bidRequest.mediaTypes.video.api, - skip: bidRequest.mediaTypes.video.skip, - placement: bidRequest.mediaTypes.video.placement, - minduration: bidRequest.mediaTypes.video.minduration, - playbackmethod: bidRequest.mediaTypes.video.playbackmethod, - startdelay: bidRequest.mediaTypes.video.startdelay + skip: bidRequest.mediaTypes.video.skip || bidRequest.params.video.skip, + placement: bidRequest.mediaTypes.video.placement || bidRequest.params.video.placement, + minduration: bidRequest.mediaTypes.video.minduration || bidRequest.params.video.minduration, + playbackmethod: bidRequest.mediaTypes.video.playbackmethod || bidRequest.params.video.playbackmethod, + startdelay: bidRequest.mediaTypes.video.startdelay || bidRequest.params.video.startdelay }; - const paramsVideo = bidRequest.params.video; - if (paramsVideo !== undefined) { - video.skip = video.skip || paramsVideo.skip || 0; - video.placement = video.placement || paramsVideo.placement; - video.minduration = video.minduration || paramsVideo.minduration; - video.playbackmethod = video.playbackmethod || paramsVideo.playbackmethod; - video.startdelay = video.startdelay || paramsVideo.startdelay || 0; - } slot.video = video; } @@ -346,13 +336,6 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { if (networkId) { request.publisher.networkid = networkId; } - if (schain) { - request.source = { - ext: { - schain: schain - } - } - }; request.user = { ext: bidderRequest.userExt }; @@ -375,10 +358,11 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { return request; } +function retrieveBannerSizes(bidRequest) { + return utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes; +} + function parseSizes(sizes, parser) { - if (sizes == undefined) { - return []; - } if (Array.isArray(sizes[0])) { // is there several sizes ? (ie. [[728,90],[200,300]]) return sizes.map(size => parser(size)); } @@ -397,7 +381,7 @@ function parseNativeSize(size) { } function hasVideoMediaType(bidRequest) { - return deepAccess(bidRequest, 'mediaTypes.video') !== undefined; + return utils.deepAccess(bidRequest, 'mediaTypes.video') !== undefined; } function hasValidVideoMediaType(bidRequest) { @@ -405,10 +389,10 @@ function hasValidVideoMediaType(bidRequest) { var requiredMediaTypesParams = ['mimes', 'playerSize', 'maxduration', 'protocols', 'api', 'skip', 'placement', 'playbackmethod']; - requiredMediaTypesParams.forEach(function (param) { - if (deepAccess(bidRequest, 'mediaTypes.video.' + param) === undefined && deepAccess(bidRequest, 'params.video.' + param) === undefined) { + requiredMediaTypesParams.forEach(function(param) { + if (utils.deepAccess(bidRequest, 'mediaTypes.video.' + param) === undefined && utils.deepAccess(bidRequest, 'params.video.' + param) === undefined) { isValid = false; - logError('Criteo Bid Adapter: mediaTypes.video.' + param + ' is required'); + utils.logError('Criteo Bid Adapter: mediaTypes.video.' + param + ' is required'); } }); @@ -484,7 +468,7 @@ export function getFastBidUrl(fastBidVersion) { } else if (fastBidVersion) { let majorVersion = String(fastBidVersion).split('.')[0]; if (majorVersion < 102) { - logWarn('Specifying a Fastbid version which is not supporting version selection.') + utils.logWarn('Specifying a Fastbid version which is not supporting version selection.') } version = '.' + fastBidVersion; } else { @@ -507,7 +491,7 @@ export function tryGetCriteoFastBid() { const firstLine = fastBidFromStorage.substr(0, firstLineEndPosition).trim(); if (firstLine.substr(0, hashPrefix.length) !== hashPrefix) { - logWarn('No hash found in FastBid'); + utils.logWarn('No hash found in FastBid'); storage.removeDataFromLocalStorage(fastBidStorageKey); } else { // Remove the hash part from the locally stored value @@ -515,10 +499,10 @@ export function tryGetCriteoFastBid() { const publisherTag = fastBidFromStorage.substr(firstLineEndPosition + 1); if (verify(publisherTag, publisherTagHash, FAST_BID_PUBKEY_N, FAST_BID_PUBKEY_E)) { - logInfo('Using Criteo FastBid'); + utils.logInfo('Using Criteo FastBid'); eval(publisherTag); // eslint-disable-line no-eval } else { - logWarn('Invalid Criteo FastBid found'); + utils.logWarn('Invalid Criteo FastBid found'); storage.removeDataFromLocalStorage(fastBidStorageKey); } } diff --git a/modules/criteoIdSystem.js b/modules/criteoIdSystem.js index c73c4422a77..ac26d34d529 100644 --- a/modules/criteoIdSystem.js +++ b/modules/criteoIdSystem.js @@ -5,25 +5,25 @@ * @requires module:modules/userId */ -import { timestamp, parseUrl, triggerPixel, logError } from '../src/utils.js'; -import { ajax } from '../src/ajax.js'; -import { getRefererInfo } from '../src/refererDetection.js'; +import * as utils from '../src/utils.js' +import * as ajax from '../src/ajax.js' +import { getRefererInfo } from '../src/refererDetection.js' import { submodule } from '../src/hook.js'; import { getStorageManager } from '../src/storageManager.js'; const gvlid = 91; const bidderCode = 'criteo'; -export const storage = getStorageManager({gvlid: gvlid, moduleName: bidderCode}); +export const storage = getStorageManager(gvlid, bidderCode); const bididStorageKey = 'cto_bidid'; const bundleStorageKey = 'cto_bundle'; const cookiesMaxAge = 13 * 30 * 24 * 60 * 60 * 1000; const pastDateString = new Date(0).toString(); -const expirationString = new Date(timestamp() + cookiesMaxAge).toString(); +const expirationString = new Date(utils.timestamp() + cookiesMaxAge).toString(); function extractProtocolHost (url, returnOnlyHost = false) { - const parsedUrl = parseUrl(url, {noDecodeWholeURL: true}) + const parsedUrl = utils.parseUrl(url, {noDecodeWholeURL: true}) return returnOnlyHost ? `${parsedUrl.hostname}` : `${parsedUrl.protocol}://${parsedUrl.hostname}${parsedUrl.port ? ':' + parsedUrl.port : ''}/`; @@ -33,37 +33,15 @@ function getFromAllStorages(key) { return storage.getCookie(key) || storage.getDataFromLocalStorage(key); } -function saveOnAllStorages(key, value, hostname) { +function saveOnAllStorages(key, value) { if (key && value) { + storage.setCookie(key, value, expirationString); storage.setDataInLocalStorage(key, value); - setCookieOnAllDomains(key, value, expirationString, hostname, true); } } -function setCookieOnAllDomains(key, value, expiration, hostname, stopOnSuccess) { - const subDomains = hostname.split('.'); - for (let i = 0; i < subDomains.length; ++i) { - // Try to write the cookie on this subdomain (we want it to be stored only on the TLD+1) - const domain = subDomains.slice(subDomains.length - i - 1, subDomains.length).join('.'); - - try { - storage.setCookie(key, value, expiration, null, '.' + domain); - - if (stopOnSuccess) { - // Try to read the cookie to check if we wrote it - const ck = storage.getCookie(key); - if (ck && ck === value) { - break; - } - } - } catch (error) { - - } - } -} - -function deleteFromAllStorages(key, hostname) { - setCookieOnAllDomains(key, '', pastDateString, hostname, true); +function deleteFromAllStorages(key) { + storage.setCookie(key, '', pastDateString); storage.removeDataFromLocalStorage(key); } @@ -87,7 +65,7 @@ function buildCriteoUsersyncUrl(topUrl, domain, bundle, areCookiesWriteable, isL return url; } -function callCriteoUserSync(parsedCriteoData, gdprString, callback) { +function callCriteoUserSync(parsedCriteoData, gdprString) { const cw = storage.cookiesAreEnabled(); const lsw = storage.localStorageIsEnabled(); const topUrl = extractProtocolHost(getRefererInfo().referer); @@ -104,32 +82,26 @@ function callCriteoUserSync(parsedCriteoData, gdprString, callback) { gdprString ); - const callbacks = { - success: response => { + ajax.ajaxBuilder()( + url, + response => { const jsonResponse = JSON.parse(response); + if (jsonResponse.bidId) { + saveOnAllStorages(bididStorageKey, jsonResponse.bidId); + } else { + deleteFromAllStorages(bididStorageKey); + } + if (jsonResponse.acwsUrl) { const urlsToCall = typeof jsonResponse.acwsUrl === 'string' ? [jsonResponse.acwsUrl] : jsonResponse.acwsUrl; - urlsToCall.forEach(url => triggerPixel(url)); + urlsToCall.forEach(url => utils.triggerPixel(url)); } else if (jsonResponse.bundle) { - saveOnAllStorages(bundleStorageKey, jsonResponse.bundle, domain); - } - - if (jsonResponse.bidId) { - saveOnAllStorages(bididStorageKey, jsonResponse.bidId, domain); - const criteoId = { criteoId: jsonResponse.bidId }; - callback(criteoId); - } else { - deleteFromAllStorages(bididStorageKey, domain); - callback(); + saveOnAllStorages(bundleStorageKey, jsonResponse.bundle); } }, - error: error => { - logError(`criteoIdSystem: unable to sync user id`, error); - callback(); - } - }; - - ajax(url, callbacks, undefined, { method: 'GET', contentType: 'application/json', withCredentials: true }); + undefined, + { method: 'GET', contentType: 'application/json', withCredentials: true } + ); } /** @type {Submodule} */ @@ -160,13 +132,9 @@ export const criteoIdSubmodule = { const gdprConsentString = hasGdprData ? consentData.consentString : undefined; let localData = getCriteoDataFromAllStorages(); + callCriteoUserSync(localData, gdprConsentString); - const result = (callback) => callCriteoUserSync(localData, gdprConsentString, callback); - - return { - id: localData.bidId ? { criteoId: localData.bidId } : undefined, - callback: result - } + return { id: localData.bidId ? { criteoId: localData.bidId } : undefined } } }; diff --git a/modules/currency.js b/modules/currency.js index 7f88c4b0aeb..0464d9b5cdb 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -1,8 +1,8 @@ -import { logInfo, logWarn, logError, logMessage } from '../src/utils.js'; import { getGlobal } from '../src/prebidGlobal.js'; import { createBid } from '../src/bidfactory.js'; -import CONSTANTS from '../src/constants.json'; +import { STATUS } from '../src/constants.json'; import { ajax } from '../src/ajax.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { getHook } from '../src/hook.js'; @@ -20,25 +20,6 @@ export var currencyRates = {}; var bidderCurrencyDefault = {}; var defaultRates; -export const ready = (() => { - let isDone, resolver, promise; - function reset() { - isDone = false; - resolver = null; - promise = new Promise((resolve) => { - resolver = resolve; - if (isDone) resolve(); - }) - } - function done() { - isDone = true; - if (resolver != null) { resolver() } - } - reset(); - - return {done, reset, promise: () => promise} -})(); - /** * Configuration function for currency * @param {string} [config.adServerCurrency = 'USD'] @@ -89,11 +70,11 @@ export function setConfig(config) { } if (typeof config.adServerCurrency === 'string') { - logInfo('enabling currency support', arguments); + utils.logInfo('enabling currency support', arguments); adServerCurrency = config.adServerCurrency; if (config.conversionRateFile) { - logInfo('currency using override conversionRateFile:', config.conversionRateFile); + utils.logInfo('currency using override conversionRateFile:', config.conversionRateFile); url = config.conversionRateFile; } @@ -118,7 +99,7 @@ export function setConfig(config) { initCurrency(url); } else { // currency support is disabled, setting defaults - logInfo('disabling currency support'); + utils.logInfo('disabling currency support'); resetCurrency(); } if (typeof config.bidderCurrencyDefault === 'object') { @@ -129,10 +110,10 @@ config.getConfig('currency', config => setConfig(config.currency)); function errorSettingsRates(msg) { if (defaultRates) { - logWarn(msg); - logWarn('Currency failed loading rates, falling back to currency.defaultRates'); + utils.logWarn(msg); + utils.logWarn('Currency failed loading rates, falling back to currency.defaultRates'); } else { - logError(msg); + utils.logError(msg); } } @@ -140,7 +121,7 @@ function initCurrency(url) { conversionCache = {}; currencySupportEnabled = true; - logInfo('Installing addBidResponse decorator for currency module', arguments); + utils.logInfo('Installing addBidResponse decorator for currency module', arguments); // Adding conversion function to prebid global for external module and on page use getGlobal().convertCurrency = (cpm, fromCurrency, toCurrency) => parseFloat(cpm) * getCurrencyConversion(fromCurrency, toCurrency); @@ -154,27 +135,21 @@ function initCurrency(url) { success: function (response) { try { currencyRates = JSON.parse(response); - logInfo('currencyRates set to ' + JSON.stringify(currencyRates)); + utils.logInfo('currencyRates set to ' + JSON.stringify(currencyRates)); currencyRatesLoaded = true; processBidResponseQueue(); - ready.done(); } catch (e) { errorSettingsRates('Failed to parse currencyRates response: ' + response); } }, - error: function (...args) { - errorSettingsRates(...args); - ready.done(); - } + error: errorSettingsRates } ); - } else { - ready.done(); } } function resetCurrency() { - logInfo('Uninstalling addBidResponse decorator for currency module', arguments); + utils.logInfo('Uninstalling addBidResponse decorator for currency module', arguments); getHook('addBidResponse').getHooks({hook: addBidResponseHook}).remove(); delete getGlobal().convertCurrency; @@ -197,7 +172,7 @@ export function addBidResponseHook(fn, adUnitCode, bid) { if (bidderCurrencyDefault[bidder]) { let currencyDefault = bidderCurrencyDefault[bidder]; if (bid.currency && currencyDefault !== bid.currency) { - logWarn(`Currency default '${bidder}: ${currencyDefault}' ignored. adapter specified '${bid.currency}'`); + utils.logWarn(`Currency default '${bidder}: ${currencyDefault}' ignored. adapter specified '${bid.currency}'`); } else { bid.currency = currencyDefault; } @@ -205,7 +180,7 @@ export function addBidResponseHook(fn, adUnitCode, bid) { // default to USD if currency not set if (!bid.currency) { - logWarn('Currency not specified on bid. Defaulted to "USD"'); + utils.logWarn('Currency not specified on bid. Defaulted to "USD"'); bid.currency = 'USD'; } @@ -222,8 +197,6 @@ export function addBidResponseHook(fn, adUnitCode, bid) { bidResponseQueue.push(wrapFunction(fn, this, [adUnitCode, bid])); if (!currencySupportEnabled || currencyRatesLoaded) { processBidResponseQueue(); - } else { - fn.bail(ready.promise()); } } @@ -245,8 +218,11 @@ function wrapFunction(fn, context, params) { bid.currency = adServerCurrency; } } catch (e) { - logWarn('Returning NO_BID, getCurrencyConversion threw error: ', e); - params[1] = createBid(CONSTANTS.STATUS.NO_BID, bid.getIdentifiers()); + utils.logWarn('Returning NO_BID, getCurrencyConversion threw error: ', e); + params[1] = createBid(STATUS.NO_BID, { + bidder: bid.bidderCode || bid.bidder, + bidId: bid.requestId + }); } } return fn.apply(context, params); @@ -259,7 +235,7 @@ function getCurrencyConversion(fromCurrency, toCurrency = adServerCurrency) { let cacheKey = `${fromCurrency}->${toCurrency}`; if (cacheKey in conversionCache) { conversionRate = conversionCache[cacheKey]; - logMessage('Using conversionCache value ' + conversionRate + ' for ' + cacheKey); + utils.logMessage('Using conversionCache value ' + conversionRate + ' for ' + cacheKey); } else if (currencySupportEnabled === false) { if (fromCurrency === 'USD') { conversionRate = 1; @@ -277,7 +253,7 @@ function getCurrencyConversion(fromCurrency, toCurrency = adServerCurrency) { throw new Error('Specified adServerCurrency in config \'' + toCurrency + '\' not found in the currency rates file'); } conversionRate = rates[toCurrency]; - logInfo('getCurrencyConversion using direct ' + fromCurrency + ' to ' + toCurrency + ' conversionRate ' + conversionRate); + utils.logInfo('getCurrencyConversion using direct ' + fromCurrency + ' to ' + toCurrency + ' conversionRate ' + conversionRate); } else if (toCurrency in currencyRates.conversions) { // using reciprocal of conversion rate from toCurrency to fromCurrency rates = currencyRates.conversions[toCurrency]; @@ -286,7 +262,7 @@ function getCurrencyConversion(fromCurrency, toCurrency = adServerCurrency) { throw new Error('Specified fromCurrency \'' + fromCurrency + '\' not found in the currency rates file'); } conversionRate = roundFloat(1 / rates[fromCurrency], CURRENCY_RATE_PRECISION); - logInfo('getCurrencyConversion using reciprocal ' + fromCurrency + ' to ' + toCurrency + ' conversionRate ' + conversionRate); + utils.logInfo('getCurrencyConversion using reciprocal ' + fromCurrency + ' to ' + toCurrency + ' conversionRate ' + conversionRate); } else { // first defined currency base used as intermediary var anyBaseCurrency = Object.keys(currencyRates.conversions)[0]; @@ -304,11 +280,11 @@ function getCurrencyConversion(fromCurrency, toCurrency = adServerCurrency) { var fromIntermediateConversionRate = currencyRates.conversions[anyBaseCurrency][toCurrency]; conversionRate = roundFloat(toIntermediateConversionRate * fromIntermediateConversionRate, CURRENCY_RATE_PRECISION); - logInfo('getCurrencyConversion using intermediate ' + fromCurrency + ' thru ' + anyBaseCurrency + ' to ' + toCurrency + ' conversionRate ' + conversionRate); + utils.logInfo('getCurrencyConversion using intermediate ' + fromCurrency + ' thru ' + anyBaseCurrency + ' to ' + toCurrency + ' conversionRate ' + conversionRate); } } if (!(cacheKey in conversionCache)) { - logMessage('Adding conversionCache value ' + conversionRate + ' for ' + cacheKey); + utils.logMessage('Adding conversionCache value ' + conversionRate + ' for ' + cacheKey); conversionCache[cacheKey] = conversionRate; } return conversionRate; diff --git a/modules/cwireBidAdapter.js b/modules/cwireBidAdapter.js deleted file mode 100644 index c0a24b49a3c..00000000000 --- a/modules/cwireBidAdapter.js +++ /dev/null @@ -1,302 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {OUTSTREAM} from '../src/video.js'; -import { - deepAccess, - generateUUID, - getBidIdParameter, - getParameterByName, - getValue, - isArray, - isNumber, - logError, - logWarn, - parseSizesInput, -} from '../src/utils.js'; -import {Renderer} from '../src/Renderer.js'; -import {find} from '../src/polyfill.js'; - -// ------------------------------------ -const BIDDER_CODE = 'cwire'; -export const ENDPOINT_URL = 'https://embed.cwi.re/delivery/prebid'; -export const RENDERER_URL = 'https://cdn.cwi.re/prebid/renderer/LATEST/renderer.min.js'; -// ------------------------------------ -export const CW_PAGE_VIEW_ID = generateUUID(); -const LS_CWID_KEY = 'cw_cwid'; -const CW_GROUPS_QUERY = 'cwgroups'; -const CW_CREATIVE_QUERY = 'cwcreative'; - -const storage = getStorageManager({bidderCode: BIDDER_CODE}); - -/** - * ------------------------------------ - * ------------------------------------ - * @param bid - * @returns {Array} - */ -export function getSlotSizes(bid) { - return parseSizesInput(getAllMediaSizes(bid)); -} - -/** - * ------------------------------------ - * ------------------------------------ - * @param bid - * @returns {*[]} - */ -export function getAllMediaSizes(bid) { - let playerSizes = deepAccess(bid, 'mediaTypes.video.playerSize'); - let videoSizes = deepAccess(bid, 'mediaTypes.video.sizes'); - let bannerSizes = deepAccess(bid, 'mediaTypes.banner.sizes'); - - const sizes = []; - - if (isArray(playerSizes)) { - playerSizes.forEach((s) => { - sizes.push(s); - }) - } - - if (isArray(videoSizes)) { - videoSizes.forEach((s) => { - sizes.push(s); - }) - } - - if (isArray(bannerSizes)) { - bannerSizes.forEach((s) => { - sizes.push(s); - }) - } - return sizes; -} - -const getQueryVariable = (variable) => { - let value = getParameterByName(variable); - if (value === '') { - value = null; - } - return value; -}; - -/** - * ------------------------------------ - * ------------------------------------ - * @param validBidRequests - * @returns {*[]} - */ -export const mapSlotsData = function(validBidRequests) { - const slots = []; - validBidRequests.forEach(bid => { - const bidObj = {}; - // get testing / debug params - let cwcreative = getValue(bid.params, 'cwcreative'); - let refgroups = getValue(bid.params, 'refgroups'); - let cwapikey = getValue(bid.params, 'cwapikey'); - - // get the pacement and page ids - let placementId = getValue(bid.params, 'placementId'); - let pageId = getValue(bid.params, 'pageId'); - // get the rest of the auction/bid/transaction info - bidObj.auctionId = getBidIdParameter('auctionId', bid); - bidObj.adUnitCode = getBidIdParameter('adUnitCode', bid); - bidObj.bidId = getBidIdParameter('bidId', bid); - bidObj.bidderRequestId = getBidIdParameter('bidderRequestId', bid); - bidObj.placementId = placementId; - bidObj.pageId = pageId; - bidObj.mediaTypes = getBidIdParameter('mediaTypes', bid); - bidObj.transactionId = getBidIdParameter('transactionId', bid); - bidObj.sizes = getSlotSizes(bid); - bidObj.cwcreative = cwcreative; - bidObj.refgroups = refgroups; - bidObj.cwapikey = cwapikey; - slots.push(bidObj); - }); - - return slots; -}; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO], - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function(bid) { - bid.params = bid.params || {}; - - if (!bid.params.placementId || !isNumber(bid.params.placementId)) { - logError('placementId not provided or invalid'); - return false; - } - - if (!bid.params.pageId || !isNumber(bid.params.pageId)) { - logError('pageId not provided'); - return false; - } - - return true; - }, - - /** - * ------------------------------------ - * itterate trough slots array and try - * to extract first occurence of a given - * key, if not found - return null - * ------------------------------------ - */ - getFirstValueOrNull: function(slots, key) { - const found = slots.find((item) => { - return (typeof item[key] !== 'undefined'); - }); - - return (found) ? found[key] : null; - }, - - /** - * ------------------------------------ - * Make a server request from the - * list of BidRequests. - * ------------------------------------ - * @param {validBidRequests[]} - an array of bids - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function(validBidRequests, bidderRequest) { - let slots = []; - let referer; - try { - referer = getRefererInfo().referer; - slots = mapSlotsData(validBidRequests); - } catch (e) { - logWarn(e); - } - - let refgroups = []; - - const cwCreativeId = parseInt(getQueryVariable(CW_CREATIVE_QUERY), 10) || null; - const cwCreativeIdFromConfig = this.getFirstValueOrNull(slots, 'cwcreative'); - const refGroupsFromConfig = this.getFirstValueOrNull(slots, 'refgroups'); - const cwApiKeyFromConfig = this.getFirstValueOrNull(slots, 'cwapikey'); - const rgQuery = getQueryVariable(CW_GROUPS_QUERY); - - if (refGroupsFromConfig !== null) { - refgroups = refGroupsFromConfig.split(','); - } - - if (rgQuery !== null) { - // override if query param is present - refgroups = []; - refgroups = rgQuery.split(','); - } - - const localStorageCWID = storage.localStorageIsEnabled() ? storage.getDataFromLocalStorage(LS_CWID_KEY) : null; - - const payload = { - cwid: localStorageCWID, - refgroups, - cwcreative: cwCreativeId || cwCreativeIdFromConfig, - slots: slots, - cwapikey: cwApiKeyFromConfig, - httpRef: referer || '', - pageViewId: CW_PAGE_VIEW_ID, - }; - - return { - method: 'POST', - url: ENDPOINT_URL, - data: payload - }; - }, - - /** - * Unpack the response from the server into a list of bids. - * - * @param {ServerResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function(serverResponse, bidRequest) { - const bidResponses = []; - - try { - if (typeof bidRequest.data === 'string') { - bidRequest.data = JSON.parse(bidRequest.data); - } - const serverBody = serverResponse.body; - serverBody.bids.forEach((br) => { - const bidReq = find(bidRequest.data.slots, bid => bid.bidId === br.requestId); - - let mediaType = BANNER; - - const bidResponse = { - requestId: br.requestId, - cpm: br.cpm, - bidderCode: BIDDER_CODE, - width: br.dimensions[0], - height: br.dimensions[1], - creativeId: br.creativeId, - currency: br.currency, - netRevenue: br.netRevenue, - ttl: br.ttl, - meta: { - advertiserDomains: br.adomains ? br.advertiserDomains : [], - }, - - }; - - // ------------------------------------ - // IF BANNER - // ------------------------------------ - - if (deepAccess(bidReq, 'mediaTypes.banner')) { - bidResponse.ad = br.html; - } - // ------------------------------------ - // IF VIDEO - // ------------------------------------ - if (deepAccess(bidReq, 'mediaTypes.video')) { - mediaType = VIDEO; - bidResponse.vastXml = br.vastXml; - bidResponse.videoScript = br.html; - const mediaTypeContext = deepAccess(bidReq, 'mediaTypes.video.context'); - if (mediaTypeContext === OUTSTREAM) { - const r = Renderer.install({ - id: bidResponse.requestId, - adUnitCode: bidReq.adUnitCode, - url: RENDERER_URL, - loaded: false, - config: { - ...deepAccess(bidReq, 'mediaTypes.video'), - ...deepAccess(br, 'outstream', {}) - } - }); - - // set renderer - try { - bidResponse.renderer = r; - bidResponse.renderer.setRender(function(bid) { - if (window.CWIRE && window.CWIRE.outstream) { - window.CWIRE.outstream.renderAd(bid); - } - }); - } catch (err) { - logWarn('Prebid Error calling setRender on newRenderer', err); - } - } - } - - bidResponse.mediaType = mediaType; - bidResponses.push(bidResponse); - }); - } catch (e) { - logWarn(e); - } - - return bidResponses; - }, -} -registerBidder(spec); diff --git a/modules/cwireBidAdapter.md b/modules/cwireBidAdapter.md deleted file mode 100644 index b42c7a02489..00000000000 --- a/modules/cwireBidAdapter.md +++ /dev/null @@ -1,48 +0,0 @@ -# Overview - -Module Name: C-WIRE Bid Adapter -Module Type: Adagio Adapter -Maintainer: publishers@cwire.ch - -## Description - -Connects to C-WIRE demand source to fetch bids. - -## Configuration - - -Below, the list of C-WIRE params and where they can be set. - -| Param name | Global config | AdUnit config | Type | Required | -| ---------- | ------------- | ------------- | ---- | ---------| -| pageId | | x | number | YES | -| placementId | | x | number | YES | -| refgroups | | x | string | NO | -| cwcreative | | x | integer | NO | -| cwapikey | | x | string | NO | - - -### adUnit configuration - -```javascript -var adUnits = [ - { - code: 'target_div_id', // REQUIRED - bids: [{ - bidder: 'cwire', - mediaTypes: { - banner: { - sizes: [[1, 1]], - } - }, - params: { - pageId: 1422, // required - number - placementId: 2211521, // required - number - cwcreative: 42, // optional - id of creative to force - refgroups: 'test-user', // optional - name of group or coma separated list of groups to force - cwapikey: 'api_key_xyz', // optional - api key for integration testing - } - }] - } -]; -``` diff --git a/modules/dacIdSystem.js b/modules/dacIdSystem.js deleted file mode 100644 index 73b5c7420cf..00000000000 --- a/modules/dacIdSystem.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * This module adds dacId to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/dacIdSystem - * @requires module:modules/userId - */ - -import { submodule } from '../src/hook.js'; -import { getStorageManager } from '../src/storageManager.js'; - -export const storage = getStorageManager(); - -export const cookieKey = '_a1_f'; - -export const dacIdSystemSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: 'dacId', - - /** - * performs action to obtain id - * @function - * @returns { {id: {dacId: string}} | undefined } - */ - getId: function() { - const newId = storage.getCookie(cookieKey); - if (!newId) { - return undefined; - } - const result = { - dacId: newId - } - return {id: result}; - }, - - /** - * decode the stored id value for passing to bid requests - * @function - * @param { {dacId: string} } value - * @returns { {dacId: {id: string} } | undefined } - */ - decode: function(value) { - if (value && typeof value === 'object') { - const result = {}; - if (value.dacId) { - result.id = value.dacId - } - return {dacId: result}; - } - return undefined; - }, - -} - -submodule('userId', dacIdSystemSubmodule); diff --git a/modules/dacIdSystem.md b/modules/dacIdSystem.md deleted file mode 100644 index b422d0a536d..00000000000 --- a/modules/dacIdSystem.md +++ /dev/null @@ -1,28 +0,0 @@ -## DAC User ID Submodule - -DAC ID, provided by [D.A.Consortium Inc.](https://www.dac.co.jp/), is ID for ad targeting by using 1st party cookie. -Please contact D.A.Consortium Inc. before using this ID. - -## Building Prebid with DAC ID Support - -First, make sure to add the DAC ID submodule to your Prebid.js package with: - -``` -gulp build --modules=dacIdSystem -``` - -The following configuration parameters are available: - -```javascript -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'dacId' - }] - } -}); -``` - -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `"dacId"` | diff --git a/modules/dailyhuntBidAdapter.js b/modules/dailyhuntBidAdapter.js deleted file mode 100644 index ffa84ff88fd..00000000000 --- a/modules/dailyhuntBidAdapter.js +++ /dev/null @@ -1,435 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import * as mediaTypes from '../src/mediaTypes.js'; -import {_map, deepAccess, isEmpty} from '../src/utils.js'; -import {ajax} from '../src/ajax.js'; -import {find} from '../src/polyfill.js'; -import {INSTREAM, OUTSTREAM} from '../src/video.js'; - -const BIDDER_CODE = 'dailyhunt'; -const BIDDER_ALIAS = 'dh'; -const SUPPORTED_MEDIA_TYPES = [mediaTypes.BANNER, mediaTypes.NATIVE, mediaTypes.VIDEO]; - -const PROD_PREBID_ENDPOINT_URL = 'https://pbs.dailyhunt.in/openrtb2/auction?partner='; -const PROD_PREBID_TEST_ENDPOINT_URL = 'https://qa-pbs-van.dailyhunt.in/openrtb2/auction?partner='; - -const ORTB_NATIVE_TYPE_MAPPING = { - img: { - '3': 'image', - '1': 'icon' - }, - data: { - '1': 'sponsoredBy', - '2': 'body', - '3': 'rating', - '4': 'likes', - '5': 'downloads', - '6': 'price', - '7': 'salePrice', - '8': 'phone', - '9': 'address', - '10': 'body2', - '11': 'displayUrl', - '12': 'cta' - } -} - -const ORTB_NATIVE_PARAMS = { - title: { - id: 0, - name: 'title' - }, - icon: { - id: 1, - type: 1, - name: 'img' - }, - image: { - id: 2, - type: 3, - name: 'img' - }, - sponsoredBy: { - id: 3, - name: 'data', - type: 1 - }, - body: { - id: 4, - name: 'data', - type: 2 - }, - cta: { - id: 5, - type: 12, - name: 'data' - }, - body2: { - id: 4, - name: 'data', - type: 10 - }, -}; - -// Encode URI. -const _encodeURIComponent = function (a) { - let b = window.encodeURIComponent(a); - b = b.replace(/'/g, '%27'); - return b; -} - -// Extract key from collections. -const extractKeyInfo = (collection, key) => { - for (let i = 0, result; i < collection.length; i++) { - result = deepAccess(collection[i].params, key); - if (result) { - return result; - } - } - return undefined -} - -// Flattern Array. -const flatten = (arr) => { - return [].concat(...arr); -} - -const createOrtbRequest = (validBidRequests, bidderRequest) => { - let device = createOrtbDeviceObj(validBidRequests); - let user = createOrtbUserObj(validBidRequests) - let site = createOrtbSiteObj(validBidRequests, bidderRequest.refererInfo.referer) - return { - id: bidderRequest.auctionId, - imp: [], - site, - device, - user, - }; -} - -const createOrtbDeviceObj = (validBidRequests) => { - let device = { ...extractKeyInfo(validBidRequests, `device`) }; - device.ua = navigator.userAgent; - return device; -} - -const createOrtbUserObj = (validBidRequests) => ({ ...extractKeyInfo(validBidRequests, `user`) }) - -const createOrtbSiteObj = (validBidRequests, page) => { - let site = { ...extractKeyInfo(validBidRequests, `site`), page }; - let publisher = createOrtbPublisherObj(validBidRequests); - if (!site.publisher) { - site.publisher = publisher - } - return site -} - -const createOrtbPublisherObj = (validBidRequests) => ({ ...extractKeyInfo(validBidRequests, `publisher`) }) - -// get bidFloor Function for different creatives -function getBidFloor(bid, creative) { - let floorInfo = typeof (bid.getFloor) == 'function' ? bid.getFloor({ currency: 'USD', mediaType: creative, size: '*' }) : {}; - return Math.floor(floorInfo.floor || (bid.params.bidfloor ? bid.params.bidfloor : 0.0)); -} - -const createOrtbImpObj = (bid) => { - let params = bid.params - let testMode = !!bid.params.test_mode - - // Validate Banner Request. - let bannerObj = deepAccess(bid.mediaTypes, `banner`); - let nativeObj = deepAccess(bid.mediaTypes, `native`); - let videoObj = deepAccess(bid.mediaTypes, `video`); - - let imp = { - id: bid.bidId, - ext: { - dailyhunt: { - placement_id: params.placement_id, - publisher_id: params.publisher_id, - partner: params.partner_name - } - } - }; - - // Test Mode Campaign. - if (testMode) { - imp.ext.test_mode = testMode; - } - - if (bannerObj) { - imp.banner = { - ...createOrtbImpBannerObj(bid, bannerObj) - } - imp.bidfloor = getBidFloor(bid, 'banner'); - } else if (nativeObj) { - imp.native = { - ...createOrtbImpNativeObj(bid, nativeObj) - } - imp.bidfloor = getBidFloor(bid, 'native'); - } else if (videoObj) { - imp.video = { - ...createOrtbImpVideoObj(bid, videoObj) - } - imp.bidfloor = getBidFloor(bid, 'video'); - } - return imp; -} - -const createOrtbImpBannerObj = (bid, bannerObj) => { - let format = []; - bannerObj.sizes.forEach(size => format.push({ w: size[0], h: size[1] })) - - return { - id: 'banner-' + bid.bidId, - format - } -} - -const createOrtbImpNativeObj = (bid, nativeObj) => { - const assets = _map(bid.nativeParams, (bidParams, key) => { - const props = ORTB_NATIVE_PARAMS[key]; - const asset = { - required: bidParams.required & 1, - }; - if (props) { - let h = 0; - let w = 0; - - asset.id = props.id; - - if (bidParams.sizes) { - const sizes = flatten(bidParams.sizes); - w = sizes[0]; - h = sizes[1]; - } - - asset[props.name] = { - len: bidParams.len ? bidParams.len : 20, - type: props.type, - w, - h - }; - - return asset; - } - }).filter(Boolean); - let request = { - assets, - ver: '1,0' - } - return { request: JSON.stringify(request) }; -} - -const createOrtbImpVideoObj = (bid, videoObj) => { - let obj = {}; - let params = bid.params - if (!isEmpty(bid.params.video)) { - obj = { - topframe: 1, - skip: params.video.skippable || 0, - linearity: params.video.linearity || 1, - minduration: params.video.minduration || 5, - maxduration: params.video.maxduration || 60, - mimes: params.video.mimes || ['video/mp4'], - protocols: getProtocols(params.video), - w: params.video.playerSize[0][0], - h: params.video.playerSize[0][1], - }; - } else { - obj = { - mimes: ['video/mp4'], - }; - } - obj.ext = { - ...videoObj, - } - return obj; -} - -export function getProtocols({protocols}) { - let defaultValue = [2, 3, 5, 6, 7, 8]; - let listProtocols = [ - {key: 'VAST_1_0', value: 1}, - {key: 'VAST_2_0', value: 2}, - {key: 'VAST_3_0', value: 3}, - {key: 'VAST_1_0_WRAPPER', value: 4}, - {key: 'VAST_2_0_WRAPPER', value: 5}, - {key: 'VAST_3_0_WRAPPER', value: 6}, - {key: 'VAST_4_0', value: 7}, - {key: 'VAST_4_0_WRAPPER', value: 8} - ]; - if (protocols) { - return listProtocols.filter(p => { - return protocols.indexOf(p.key) !== -1 - }).map(p => p.value); - } else { - return defaultValue; - } -} - -const createServerRequest = (ortbRequest, validBidRequests, isTestMode = 'false') => ({ - method: 'POST', - url: isTestMode === 'true' ? PROD_PREBID_TEST_ENDPOINT_URL + validBidRequests[0].params.partner_name : PROD_PREBID_ENDPOINT_URL + validBidRequests[0].params.partner_name, - data: JSON.stringify(ortbRequest), - options: { - contentType: 'application/json', - withCredentials: true - }, - bids: validBidRequests -}) - -const createPrebidBannerBid = (bid, bidResponse) => ({ - requestId: bid.bidId, - cpm: bidResponse.price.toFixed(2), - creativeId: bidResponse.crid, - width: bidResponse.w, - height: bidResponse.h, - ttl: 360, - netRevenue: bid.netRevenue === 'net', - currency: 'USD', - ad: bidResponse.adm, - mediaType: 'banner', - winUrl: bidResponse.nurl, - adomain: bidResponse.adomain -}) - -const createPrebidNativeBid = (bid, bidResponse) => ({ - requestId: bid.bidId, - cpm: bidResponse.price.toFixed(2), - creativeId: bidResponse.crid, - currency: 'USD', - ttl: 360, - netRevenue: bid.netRevenue === 'net', - native: parseNative(bidResponse), - mediaType: 'native', - winUrl: bidResponse.nurl, - width: bidResponse.w, - height: bidResponse.h, - adomain: bidResponse.adomain -}) - -const parseNative = (bid) => { - let adm = JSON.parse(bid.adm) - const { assets, link, imptrackers, jstracker } = adm.native; - const result = { - clickUrl: _encodeURIComponent(link.url), - clickTrackers: link.clicktrackers || [], - impressionTrackers: imptrackers || [], - javascriptTrackers: jstracker ? [ jstracker ] : [] - }; - assets.forEach(asset => { - if (!isEmpty(asset.title)) { - result.title = asset.title.text - } else if (!isEmpty(asset.img)) { - result[ORTB_NATIVE_TYPE_MAPPING.img[asset.img.type]] = { - url: asset.img.url, - height: asset.img.h, - width: asset.img.w - } - } else if (!isEmpty(asset.data)) { - result[ORTB_NATIVE_TYPE_MAPPING.data[asset.data.type]] = asset.data.value - } - }); - - return result; -} - -const createPrebidVideoBid = (bid, bidResponse) => { - let videoBid = { - requestId: bid.bidId, - cpm: bidResponse.price.toFixed(2), - creativeId: bidResponse.crid, - width: bidResponse.w, - height: bidResponse.h, - ttl: 360, - netRevenue: bid.netRevenue === 'net', - currency: 'USD', - mediaType: 'video', - winUrl: bidResponse.nurl, - adomain: bidResponse.adomain - }; - - let videoContext = bid.mediaTypes.video.context; - switch (videoContext) { - case OUTSTREAM: - videoBid.vastXml = bidResponse.adm; - break; - case INSTREAM: - videoBid.videoCacheKey = bidResponse.ext.bidder.cacheKey; - videoBid.vastUrl = bidResponse.ext.bidder.vastUrl; - break; - } - return videoBid; -} - -const getQueryVariable = (variable) => { - let query = window.location.search.substring(1); - let vars = query.split('&'); - for (var i = 0; i < vars.length; i++) { - let pair = vars[i].split('='); - if (decodeURIComponent(pair[0]) == variable) { - return decodeURIComponent(pair[1]); - } - } - return false; -} - -export const spec = { - code: BIDDER_CODE, - - aliases: [BIDDER_ALIAS], - - supportedMediaTypes: SUPPORTED_MEDIA_TYPES, - - isBidRequestValid: bid => !!bid.params.placement_id && !!bid.params.publisher_id && !!bid.params.partner_name, - - buildRequests: function (validBidRequests, bidderRequest) { - let serverRequests = []; - - // ORTB Request. - let ortbReq = createOrtbRequest(validBidRequests, bidderRequest); - - validBidRequests.forEach((bid) => { - let imp = createOrtbImpObj(bid) - ortbReq.imp.push(imp); - }); - - serverRequests.push({ ...createServerRequest(ortbReq, validBidRequests, getQueryVariable('dh_test')) }); - - return serverRequests; - }, - - interpretResponse: function (serverResponse, request) { - const { seatbid } = serverResponse.body; - let bids = request.bids; - let prebidResponse = []; - - let seatBids = seatbid[0].bid; - - seatBids.forEach(ortbResponseBid => { - let bidId = ortbResponseBid.impid; - let actualBid = find(bids, (bid) => bid.bidId === bidId); - let bidMediaType = ortbResponseBid.ext.prebid.type - switch (bidMediaType) { - case mediaTypes.BANNER: - prebidResponse.push(createPrebidBannerBid(actualBid, ortbResponseBid)); - break; - case mediaTypes.NATIVE: - prebidResponse.push(createPrebidNativeBid(actualBid, ortbResponseBid)); - break; - case mediaTypes.VIDEO: - prebidResponse.push(createPrebidVideoBid(actualBid, ortbResponseBid)); - break; - } - }) - return prebidResponse; - }, - - onBidWon: function(bid) { - ajax(bid.winUrl, null, null, { - method: 'GET' - }) - } -} - -registerBidder(spec); diff --git a/modules/dailyhuntBidAdapter.md b/modules/dailyhuntBidAdapter.md index a08b66fb826..acfd20a4de0 100644 --- a/modules/dailyhuntBidAdapter.md +++ b/modules/dailyhuntBidAdapter.md @@ -99,7 +99,3 @@ Dailyhunt bid adapter supports Banner, Native and Video. } ]; ``` - -## latest commit has all the required support for latest version of prebid above 6.x -## Dailyhunt adapter was there till 4.x and then removed in version 5.x of prebid. -## this doc has been also submitted to https://github.com/prebid/prebid.github.io \ No newline at end of file diff --git a/modules/datablocksBidAdapter.js b/modules/datablocksBidAdapter.js index b240db1dd25..bfbe7a16fc6 100644 --- a/modules/datablocksBidAdapter.js +++ b/modules/datablocksBidAdapter.js @@ -1,10 +1,10 @@ -import { getWindowTop, isGptPubadsDefined, deepAccess, getAdUnitSizes, isEmpty } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; +import * as utils from '../src/utils.js'; import { BANNER, NATIVE } from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; import { ajax } from '../src/ajax.js'; -export const storage = getStorageManager({bidderCode: 'datablocks'}); +export const storage = getStorageManager(); const NATIVE_ID_MAP = {}; const NATIVE_PARAMS = { @@ -94,7 +94,7 @@ export const spec = { code: 'datablocks', // DATABLOCKS SCOPED OBJECT - db_obj: {metrics_host: 'prebid.dblks.net', metrics: [], metrics_timer: null, metrics_queue_time: 1000, vis_optout: false, source_id: 0}, + db_obj: {metrics_host: 'prebid.datablocks.net', metrics: [], metrics_timer: null, metrics_queue_time: 1000, vis_optout: false, source_id: 0}, // STORE THE DATABLOCKS BUYERID IN STORAGE store_dbid: function(dbid) { @@ -199,7 +199,7 @@ export const spec = { // GET BASIC CLIENT INFORMATION get_client_info: function () { let botTest = new BotClientTests(); - let win = getWindowTop(); + let win = utils.getWindowTop(); return { 'wiw': win.innerWidth, 'wih': win.innerHeight, @@ -226,7 +226,7 @@ export const spec = { // ADD GPT EVENT LISTENERS let scope = this; - if (isGptPubadsDefined()) { + if (utils.isGptPubadsDefined()) { if (typeof window['googletag'].pubads().addEventListener == 'function') { window['googletag'].pubads().addEventListener('impressionViewable', function(event) { scope.queue_metric({type: 'slot_view', source_id: scope.db_obj.source_id, auction_id: bid.auctionId, div_id: event.slot.getSlotElementId(), slot_id: event.slot.getSlotId().getAdUnitPath()}); @@ -306,7 +306,7 @@ export const spec = { tagid: bidRequest.params.tagid || bidRequest.adUnitCode, placement_id: bidRequest.params.placement_id || 0, secure: window.location.protocol == 'https:', - ortb2: deepAccess(bidRequest, `ortb2Imp`) || {}, + ortb2: utils.deepAccess(bidRequest, `ortb2Imp`) || {}, floor: {} } @@ -320,8 +320,8 @@ export const spec = { } // BUILD THE SIZES - if (deepAccess(bidRequest, `mediaTypes.banner`)) { - let sizes = getAdUnitSizes(bidRequest); + if (utils.deepAccess(bidRequest, `mediaTypes.banner`)) { + let sizes = utils.getAdUnitSizes(bidRequest); if (sizes.length) { imp.banner = { w: sizes[0][0], @@ -332,7 +332,7 @@ export const spec = { // ADD TO THE LIST OF IMP REQUESTS imps.push(imp); } - } else if (deepAccess(bidRequest, `mediaTypes.native`)) { + } else if (utils.deepAccess(bidRequest, `mediaTypes.native`)) { // ADD TO THE LIST OF IMP REQUESTS imp.native = createNativeRequest(bidRequest); imps.push(imp); @@ -388,12 +388,12 @@ export const spec = { }; let sourceId = validRequests[0].params.source_id || 0; - let host = validRequests[0].params.host || 'prebid.dblks.net'; + let host = validRequests[0].params.host || 'prebid.datablocks.net'; // RETURN WITH THE REQUEST AND PAYLOAD return { method: 'POST', - url: `https://${host}/openrtb/?sid=${sourceId}`, + url: `https://${sourceId}.${host}/openrtb/?sid=${sourceId}`, data: { id: bidderRequest.auctionId, imp: imps, @@ -521,15 +521,15 @@ export const spec = { const {id, img, data, title} = asset; const key = NATIVE_ID_MAP[id]; if (key) { - if (!isEmpty(title)) { + if (!utils.isEmpty(title)) { result.title = title.text - } else if (!isEmpty(img)) { + } else if (!utils.isEmpty(img)) { result[key] = { url: img.url, height: img.h, width: img.w } - } else if (!isEmpty(data)) { + } else if (!utils.isEmpty(data)) { result[key] = data.value; } } @@ -539,11 +539,11 @@ export const spec = { } let bids = []; - let resBids = deepAccess(rtbResponse, 'body.seatbid') || []; + let resBids = utils.deepAccess(rtbResponse, 'body.seatbid') || []; resBids.forEach(bid => { let resultItem = {requestId: bid.id, cpm: bid.price, creativeId: bid.crid, currency: bid.currency || 'USD', netRevenue: true, ttl: bid.ttl || 360, meta: {advertiserDomains: bid.adomain}}; - let mediaType = deepAccess(bid, 'ext.mtype') || ''; + let mediaType = utils.deepAccess(bid, 'ext.mtype') || ''; switch (mediaType) { case 'banner': bids.push(Object.assign({}, resultItem, {mediaType: BANNER, width: bid.w, height: bid.h, ad: bid.adm})); diff --git a/modules/dchain.js b/modules/dchain.js deleted file mode 100644 index fbe78fc5c86..00000000000 --- a/modules/dchain.js +++ /dev/null @@ -1,149 +0,0 @@ -import {includes} from '../src/polyfill.js'; -import {config} from '../src/config.js'; -import {getHook} from '../src/hook.js'; -import {_each, deepAccess, deepClone, hasOwn, isArray, isPlainObject, isStr, logError, logWarn} from '../src/utils.js'; - -const shouldBeAString = ' should be a string'; -const shouldBeAnObject = ' should be an object'; -const shouldBeAnArray = ' should be an Array'; -const shouldBeValid = ' is not a valid dchain property'; -const MODE = { - STRICT: 'strict', - RELAXED: 'relaxed', - OFF: 'off' -}; -const MODES = []; // an array of modes -_each(MODE, mode => MODES.push(mode)); - -export function checkDchainSyntax(bid, mode) { - let dchainObj = deepClone(bid.meta.dchain); - let failPrefix = 'Detected something wrong in bid.meta.dchain object for bid:'; - let failMsg = ''; - const dchainPropList = ['ver', 'complete', 'nodes', 'ext']; - - function appendFailMsg(msg) { - failMsg += '\n' + msg; - } - - function printFailMsg() { - if (mode === MODE.STRICT) { - logError(failPrefix, bid, '\n', dchainObj, failMsg); - } else { - logWarn(failPrefix, bid, `\n`, dchainObj, failMsg); - } - } - - let dchainProps = Object.keys(dchainObj); - dchainProps.forEach(prop => { - if (!includes(dchainPropList, prop)) { - appendFailMsg(`dchain.${prop}` + shouldBeValid); - } - }); - - if (dchainObj.complete !== 0 && dchainObj.complete !== 1) { - appendFailMsg(`dchain.complete should be 0 or 1`); - } - - if (!isStr(dchainObj.ver)) { - appendFailMsg(`dchain.ver` + shouldBeAString); - } - - if (hasOwn(dchainObj, 'ext')) { - if (!isPlainObject(dchainObj.ext)) { - appendFailMsg(`dchain.ext` + shouldBeAnObject); - } - } - - if (!isArray(dchainObj.nodes)) { - appendFailMsg(`dchain.nodes` + shouldBeAnArray); - printFailMsg(); - if (mode === MODE.STRICT) return false; - } else { - const nodesPropList = ['asi', 'bsid', 'rid', 'name', 'domain', 'ext']; - dchainObj.nodes.forEach((node, index) => { - if (!isPlainObject(node)) { - appendFailMsg(`dchain.nodes[${index}]` + shouldBeAnObject); - } else { - let nodeProps = Object.keys(node); - nodeProps.forEach(prop => { - if (!includes(nodesPropList, prop)) { - appendFailMsg(`dchain.nodes[${index}].${prop}` + shouldBeValid); - } - - if (prop === 'ext') { - if (!isPlainObject(node.ext)) { - appendFailMsg(`dchain.nodes[${index}].ext` + shouldBeAnObject); - } - } else { - if (!isStr(node[prop])) { - appendFailMsg(`dchain.nodes[${index}].${prop}` + shouldBeAString); - } - } - }); - } - }); - } - - if (failMsg.length > 0) { - printFailMsg(); - if (mode === MODE.STRICT) { - return false; - } - } - return true; -} - -function isValidDchain(bid) { - let mode = MODE.STRICT; - const dchainConfig = config.getConfig('dchain'); - - if (dchainConfig && isStr(dchainConfig.validation) && MODES.indexOf(dchainConfig.validation) != -1) { - mode = dchainConfig.validation; - } - - if (mode === MODE.OFF) { - return true; - } else { - return checkDchainSyntax(bid, mode); - } -} - -export function addBidResponseHook(fn, adUnitCode, bid) { - const basicDchain = { - ver: '1.0', - complete: 0, - nodes: [] - }; - - if (deepAccess(bid, 'meta.networkId') && deepAccess(bid, 'meta.networkName')) { - basicDchain.nodes.push({ name: bid.meta.networkName, bsid: bid.meta.networkId.toString() }); - } - basicDchain.nodes.push({ name: bid.bidderCode }); - - let bidDchain = deepAccess(bid, 'meta.dchain'); - if (bidDchain && isPlainObject(bidDchain)) { - let result = isValidDchain(bid); - - if (result) { - // extra check in-case mode is OFF and there is a setup issue - if (isArray(bidDchain.nodes)) { - bid.meta.dchain.nodes.push({ asi: bid.bidderCode }); - } else { - logWarn('bid.meta.dchain.nodes did not exist or was not an array; did not append prebid dchain.', bid); - } - } else { - // remove invalid dchain - delete bid.meta.dchain; - } - } else { - bid.meta.dchain = basicDchain; - } - - fn(adUnitCode, bid); -} - -export function init() { - getHook('addBidResponse').before(addBidResponseHook, 35); -} - -init(); diff --git a/modules/dchain.md b/modules/dchain.md deleted file mode 100644 index f01b3483f3c..00000000000 --- a/modules/dchain.md +++ /dev/null @@ -1,45 +0,0 @@ -# dchain module - -Refer: -- https://iabtechlab.com/buyers-json-demand-chain/ - -## Sample code for dchain setConfig and dchain object -``` -pbjs.setConfig({ - "dchain": { - "validation": "strict" - } -}); -``` - -``` -bid.meta.dchain: { - "complete": 0, - "ver": "1.0", - "ext": {...}, - "nodes": [{ - "asi": "abc", - "bsid": "123", - "rid": "d4e5f6", - "name": "xyz", - "domain": "mno", - "ext": {...} - }, ...] -} -``` - -## Workflow -The dchain module is not enabled by default as it may not be necessary for all publishers. -If required, dchain module can be included as following -``` - $ gulp build --modules=dchain,pubmaticBidAdapter,openxBidAdapter,rubiconBidAdapter,sovrnBidAdapter -``` - -The dchain module will validate a bidder's dchain object (if it was defined). Bidders should assign their dchain object into `bid.meta` field. If the dchain object is valid, it will remain in the bid object for later use. - -If it was not defined, the dchain will create a default dchain object for prebid. - -## Validation modes -- ```strict```: It is the default validation mode. In this mode, dchain object will not be accpeted from adapters if it is invalid. Errors are thrown for invalid dchain object. -- ```relaxed```: In this mode, errors are thrown for an invalid dchain object but the invalid dchain object is still accepted from adapters. -- ```off```: In this mode, no validations are performed and dchain object is accepted as is from adapters. \ No newline at end of file diff --git a/modules/debugging/bidInterceptor.js b/modules/debugging/bidInterceptor.js deleted file mode 100644 index 2a179641424..00000000000 --- a/modules/debugging/bidInterceptor.js +++ /dev/null @@ -1,229 +0,0 @@ -import { - deepAccess, - deepClone, - deepEqual, - delayExecution, - prefixLog, - mergeDeep -} from '../../src/utils.js'; -const { logMessage, logWarn, logError } = prefixLog('DEBUG:'); - -/** - * @typedef {Number|String|boolean|null|undefined} Scalar - */ - -export function BidInterceptor(opts = {}) { - ({setTimeout: this.setTimeout = window.setTimeout.bind(window)} = opts); - this.rules = []; -} - -Object.assign(BidInterceptor.prototype, { - DEFAULT_RULE_OPTIONS: { - delay: 0 - }, - serializeConfig(ruleDefs) { - function isSerializable(ruleDef, i) { - const serializable = deepEqual(ruleDef, JSON.parse(JSON.stringify(ruleDef)), {checkTypes: true}); - if (!serializable && !deepAccess(ruleDef, 'options.suppressWarnings')) { - logWarn(`Bid interceptor rule definition #${i + 1} is not serializable and will be lost after a refresh. Rule definition: `, ruleDef); - } - return serializable; - } - return ruleDefs.filter(isSerializable); - }, - updateConfig(config) { - this.rules = (config.intercept || []).map((ruleDef, i) => this.rule(ruleDef, i + 1)) - }, - /** - * @typedef {Object} RuleOptions - * @property {Number} [delay=0] delay between bid interception and mocking of response (to simulate network delay) - * @property {boolean} [suppressWarnings=false] if enabled, do not warn about unserializable rules - * - * @typedef {Object} Rule - * @property {Number} no rule number (used only as an identifier for logging) - * @property {function({}, {}): boolean} match a predicate function that tests a bid against this rule - * @property {ReplacerFn} replacer generator function for mock bid responses - * @property {RuleOptions} options - */ - - /** - * @param {{}} ruleDef - * @param {Number} ruleNo - * @returns {Rule} - */ - rule(ruleDef, ruleNo) { - return { - no: ruleNo, - match: this.matcher(ruleDef.when, ruleNo), - replace: this.replacer(ruleDef.then || {}, ruleNo), - options: Object.assign({}, this.DEFAULT_RULE_OPTIONS, ruleDef.options), - } - }, - /** - * @typedef {Function} MatchPredicate - * @param {*} candidate a bid to match, or a portion of it if used inside an ObjectMather. - * e.g. matcher((bid, bidRequest) => ....) or matcher({property: (property, bidRequest) => ...}) - * @param {BidRequest} bidRequest the request `candidate` belongs to - * @returns {boolean} - * - * @typedef {{[key]: Scalar|RegExp|MatchPredicate|ObjectMatcher}} ObjectMatcher - */ - - /** - * @param {MatchPredicate|ObjectMatcher} matchDef matcher definition - * @param {Number} ruleNo - * @returns {MatchPredicate} a predicate function that matches a bid against the given `matchDef` - */ - matcher(matchDef, ruleNo) { - if (typeof matchDef === 'function') { - return matchDef; - } - if (typeof matchDef !== 'object') { - logError(`Invalid 'when' definition for debug bid interceptor (in rule #${ruleNo})`); - return () => false; - } - function matches(candidate, {ref = matchDef, args = []}) { - return Object.entries(ref).map(([key, val]) => { - const cVal = candidate[key]; - if (val instanceof RegExp) { - return val.exec(cVal) != null; - } - if (typeof val === 'function') { - return !!val(cVal, ...args); - } - if (typeof val === 'object') { - return matches(cVal, {ref: val, args}); - } - return cVal === val; - }).every((i) => i); - } - return (candidate, ...args) => matches(candidate, {args}); - }, - /** - * @typedef {Function} ReplacerFn - * @param {*} bid a bid that was intercepted - * @param {BidRequest} bidRequest the request `bid` belongs to - * @returns {*} the response to mock for `bid`, or a portion of it if used inside an ObjectReplacer. - * e.g. replacer((bid, bidRequest) => mockResponse) or replacer({property: (bid, bidRequest) => mockProperty}) - * - * @typedef {{[key]: ReplacerFn|ObjectReplacer|*}} ObjectReplacer - */ - - /** - * @param {ReplacerFn|ObjectReplacer} replDef replacer definition - * @param ruleNo - * @return {ReplacerFn} - */ - replacer(replDef, ruleNo) { - let replFn; - if (typeof replDef === 'function') { - replFn = ({args}) => replDef(...args); - } else if (typeof replDef !== 'object') { - logError(`Invalid 'then' definition for debug bid interceptor (in rule #${ruleNo})`); - replFn = () => ({}); - } else { - replFn = ({args, ref = replDef}) => { - const result = {}; - Object.entries(ref).forEach(([key, val]) => { - if (typeof val === 'function') { - result[key] = val(...args); - } else if (typeof val === 'object') { - result[key] = replFn({args, ref: val}) - } else { - result[key] = val; - } - }); - return result; - } - } - return (bid, ...args) => { - const response = this.responseDefaults(bid); - mergeDeep(response, replFn({args: [bid, ...args]})); - if (!response.ad) { - response.ad = this.defaultAd(bid, response); - } - response.isDebug = true; - return response; - } - }, - responseDefaults(bid) { - return { - requestId: bid.bidId, - cpm: 3.5764, - currency: 'EUR', - width: 300, - height: 250, - ttl: 360, - creativeId: 'mock-creative-id', - netRevenue: false, - meta: {} - }; - }, - defaultAd(bid, bidResponse) { - return ``; - }, - /** - * Match a candidate bid against all registered rules. - * - * @param {{}} candidate - * @param args - * @returns {Rule|undefined} the first matching rule, or undefined if no match was found. - */ - match(candidate, ...args) { - return this.rules.find((rule) => rule.match(candidate, ...args)); - }, - /** - * Match a set of bids against all registered rules. - * - * @param bids - * @param bidRequest - * @returns {[{bid: *, rule: Rule}[], *[]]} a 2-tuple for matching bids (decorated with the matching rule) and - * non-matching bids. - */ - matchAll(bids, bidRequest) { - const [matches, remainder] = [[], []]; - bids.forEach((bid) => { - const rule = this.match(bid, bidRequest); - if (rule != null) { - matches.push({rule: rule, bid: bid}); - } else { - remainder.push(bid); - } - }) - return [matches, remainder]; - }, - /** - * Run a set of bids against all registered rules, filter out those that match, - * and generate mock responses for them. - * - * @param {{}[]} bids? - * @param {BidRequest} bidRequest - * @param {function(*)} addBid called once for each mock response - * @param {function()} done called once after all mock responses have been run through `addBid` - * @returns {{bids: {}[], bidRequest: {}} remaining bids that did not match any rule (this applies also to - * bidRequest.bids) - */ - intercept({bids, bidRequest, addBid, done}) { - if (bids == null) { - bids = bidRequest.bids; - } - const [matches, remainder] = this.matchAll(bids, bidRequest); - if (matches.length > 0) { - const callDone = delayExecution(done, matches.length); - matches.forEach((match) => { - const mockResponse = match.rule.replace(match.bid, bidRequest); - const delay = match.rule.options.delay; - logMessage(`Intercepted bid request (matching rule #${match.rule.no}), mocking response in ${delay}ms. Request, response:`, match.bid, mockResponse) - this.setTimeout(() => { - addBid(mockResponse, match.bid); - callDone(); - }, delay) - }); - bidRequest = deepClone(bidRequest); - bids = bidRequest.bids = remainder; - } else { - this.setTimeout(done, 0); - } - return {bids, bidRequest}; - } -}); diff --git a/modules/debugging/index.js b/modules/debugging/index.js deleted file mode 100644 index 72692c3fc98..00000000000 --- a/modules/debugging/index.js +++ /dev/null @@ -1,62 +0,0 @@ -import {deepClone, delayExecution} from '../../src/utils.js'; -import {processBidderRequests} from '../../src/adapters/bidderFactory.js'; -import {BidInterceptor} from './bidInterceptor.js'; -import {hook} from '../../src/hook.js'; -import {pbsBidInterceptor} from './pbsInterceptor.js'; -import { - onDisableOverrides, - onEnableOverrides, - saveDebuggingConfig -} from '../../src/debugging.js'; - -const interceptorHooks = []; -const bidInterceptor = new BidInterceptor(); - -saveDebuggingConfig.before(function (next, debugConfig, ...args) { - if (debugConfig.intercept) { - debugConfig = deepClone(debugConfig); - debugConfig.intercept = bidInterceptor.serializeConfig(debugConfig.intercept); - } - next(debugConfig, ...args); -}); - -function resetHooks(enable) { - interceptorHooks.forEach(([getHookFn, interceptor]) => { - getHookFn().getHooks({hook: interceptor}).remove(); - }); - if (enable) { - interceptorHooks.forEach(([getHookFn, interceptor]) => { - getHookFn().before(interceptor); - }) - } -} - -onEnableOverrides.push((overrides) => { - bidInterceptor.updateConfig(overrides); - resetHooks(true); -}); - -onDisableOverrides.push(() => { - bidInterceptor.updateConfig({}); - resetHooks(false); -}) - -function registerBidInterceptor(getHookFn, interceptor) { - const interceptBids = (...args) => bidInterceptor.intercept(...args); - interceptorHooks.push([getHookFn, function (next, ...args) { - interceptor(next, interceptBids, ...args) - }]); -} - -export function bidderBidInterceptor(next, interceptBids, spec, bids, bidRequest, ajax, wrapCallback, cbs) { - const done = delayExecution(cbs.onCompletion, 2); - ({bids, bidRequest} = interceptBids({bids, bidRequest, addBid: cbs.onBid, done})); - if (bids.length === 0) { - done(); - } else { - next(spec, bids, bidRequest, ajax, wrapCallback, {...cbs, onCompletion: done}); - } -} - -registerBidInterceptor(() => processBidderRequests, bidderBidInterceptor); -registerBidInterceptor(() => hook.get('processPBSRequest'), pbsBidInterceptor); diff --git a/modules/debugging/pbsInterceptor.js b/modules/debugging/pbsInterceptor.js deleted file mode 100644 index c8de1ed9753..00000000000 --- a/modules/debugging/pbsInterceptor.js +++ /dev/null @@ -1,38 +0,0 @@ -import {deepClone, delayExecution} from '../../src/utils.js'; -import {createBid} from '../../src/bidfactory.js'; -import {default as CONSTANTS} from '../../src/constants.json'; - -export function pbsBidInterceptor (next, interceptBids, s2sBidRequest, bidRequests, ajax, { - onResponse, - onError, - onBid -}) { - let responseArgs; - const done = delayExecution(() => onResponse(...responseArgs), bidRequests.length + 1) - function signalResponse(...args) { - responseArgs = args; - done(); - } - function addBid(bid, bidRequest) { - onBid({ - adUnit: bidRequest.adUnitCode, - bid: Object.assign(createBid(CONSTANTS.STATUS.GOOD, bidRequest), bid) - }) - } - bidRequests = bidRequests - .map((req) => interceptBids({bidRequest: req, addBid, done}).bidRequest) - .filter((req) => req.bids.length > 0) - - if (bidRequests.length > 0) { - const bidIds = new Set(); - bidRequests.forEach((req) => req.bids.forEach((bid) => bidIds.add(bid.bidId))); - s2sBidRequest = deepClone(s2sBidRequest); - s2sBidRequest.ad_units.forEach((unit) => { - unit.bids = unit.bids.filter((bid) => bidIds.has(bid.bid_id)); - }) - s2sBidRequest.ad_units = s2sBidRequest.ad_units.filter((unit) => unit.bids.length > 0); - next(s2sBidRequest, bidRequests, ajax, {onResponse: signalResponse, onError, onBid}); - } else { - signalResponse(true, []); - } -} diff --git a/modules/deepintentBidAdapter.js b/modules/deepintentBidAdapter.js index 94167b92bb0..25c6ee9b25b 100644 --- a/modules/deepintentBidAdapter.js +++ b/modules/deepintentBidAdapter.js @@ -1,38 +1,13 @@ -import { generateUUID, deepSetValue, deepAccess, isArray, isInteger, logError, logWarn } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import {BANNER} from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'deepintent'; const BIDDER_ENDPOINT = 'https://prebid.deepintent.com/prebid'; const USER_SYNC_URL = 'https://cdn.deepintent.com/syncpixel.html'; const DI_M_V = '1.0.0'; -export const ORTB_VIDEO_PARAMS = { - 'mimes': (value) => Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string'), - 'minduration': (value) => isInteger(value), - 'maxduration': (value) => isInteger(value), - 'protocols': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 10), - 'w': (value) => isInteger(value), - 'h': (value) => isInteger(value), - 'startdelay': (value) => isInteger(value), - 'placement': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 5), - 'linearity': (value) => [1, 2].indexOf(value) !== -1, - 'skip': (value) => [0, 1].indexOf(value) !== -1, - 'skipmin': (value) => isInteger(value), - 'skipafter': (value) => isInteger(value), - 'sequence': (value) => isInteger(value), - 'battr': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 17), - 'maxextended': (value) => isInteger(value), - 'minbitrate': (value) => isInteger(value), - 'maxbitrate': (value) => isInteger(value), - 'boxingallowed': (value) => [0, 1].indexOf(value) !== -1, - 'playbackmethod': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6), - 'playbackend': (value) => [1, 2, 3].indexOf(value) !== -1, - 'delivery': (value) => [1, 2, 3].indexOf(value) !== -1, - 'pos': (value) => [0, 1, 2, 3, 4, 5, 6, 7].indexOf(value) !== -1, - 'api': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6) -}; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO], + supportedMediaTypes: [BANNER], aliases: [], // tagId is mandatory param @@ -40,38 +15,16 @@ export const spec = { let valid = false; if (bid && bid.params && bid.params.tagId) { if (typeof bid.params.tagId === 'string' || bid.params.tagId instanceof String) { - if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(VIDEO)) { - if (bid.mediaTypes[VIDEO].hasOwnProperty('context')) { - valid = true; - } - } else { - valid = true; - } + valid = true; } } return valid; }, - interpretResponse: function(bidResponse, bidRequest) { + interpretResponse: function(bidResponse, request) { let responses = []; if (bidResponse && bidResponse.body) { - try { - let bids = bidResponse.body.seatbid && bidResponse.body.seatbid[0] ? bidResponse.body.seatbid[0].bid : []; - if (bids) { - bids.forEach(bidObj => { - let newBid = formatResponse(bidObj); - let mediaType = _checkMediaType(bidObj); - if (mediaType === BANNER) { - newBid.mediaType = BANNER; - } else if (mediaType === VIDEO) { - newBid.mediaType = VIDEO; - newBid.vastXml = bidObj.adm; - } - responses.push(newBid); - }); - } - } catch (err) { - logError(err); - } + let bids = bidResponse.body.seatbid && bidResponse.body.seatbid[0] ? bidResponse.body.seatbid[0].bid : []; + responses = bids.map(bid => formatResponse(bid)) } return responses; }, @@ -79,7 +32,7 @@ export const spec = { var user = validBidRequests.map(bid => buildUser(bid)); clean(user); const openRtbBidRequest = { - id: generateUUID(), + id: utils.generateUUID(), at: 1, imp: validBidRequests.map(bid => buildImpression(bid)), site: buildSite(bidderRequest), @@ -88,12 +41,12 @@ export const spec = { }; if (bidderRequest && bidderRequest.uspConsent) { - deepSetValue(openRtbBidRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(openRtbBidRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); } if (bidderRequest && bidderRequest.gdprConsent) { - deepSetValue(openRtbBidRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(openRtbBidRequest, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + utils.deepSetValue(openRtbBidRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(openRtbBidRequest, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); } injectEids(openRtbBidRequest, validBidRequests); @@ -120,17 +73,6 @@ export const spec = { } }; -function _checkMediaType(bid) { - let videoRegex = new RegExp(/VAST\s+version/); - let mediaType; - if (bid.adm && bid.adm.indexOf('deepintent_wrapper') >= 0) { - mediaType = BANNER; - } else if (videoRegex.test(bid.adm)) { - mediaType = VIDEO; - } - return mediaType; -} - function clean(obj) { for (let propName in obj) { if (obj[propName] === null || obj[propName] === undefined) { @@ -158,55 +100,16 @@ function formatResponse(bid) { } function buildImpression(bid) { - let impression = {}; - impression = { + return { id: bid.bidId, tagid: bid.params.tagId || '', - secure: window.location.protocol === 'https:' ? 1 : 0, + secure: window.location.protocol === 'https' ? 1 : 0, + banner: buildBanner(bid), displaymanager: 'di_prebid', displaymanagerver: DI_M_V, ext: buildCustomParams(bid) }; - if (deepAccess(bid, 'mediaTypes.banner')) { - impression['banner'] = buildBanner(bid); - } - if (deepAccess(bid, 'mediaTypes.video')) { - impression['video'] = _buildVideo(bid); - } - return impression; } - -function _buildVideo(bid) { - const videoObj = {}; - const videoAdUnitParams = deepAccess(bid, 'mediaTypes.video', {}); - const videoBidderParams = deepAccess(bid, 'params.video', {}); - const computedParams = {}; - - if (Array.isArray(videoAdUnitParams.playerSize)) { - const tempSize = (Array.isArray(videoAdUnitParams.playerSize[0])) ? videoAdUnitParams.playerSize[0] : videoAdUnitParams.playerSize; - computedParams.w = tempSize[0]; - computedParams.h = tempSize[1]; - } - - const videoParams = { - ...computedParams, - ...videoAdUnitParams, - ...videoBidderParams - }; - - Object.keys(ORTB_VIDEO_PARAMS).forEach(paramName => { - if (videoParams.hasOwnProperty(paramName)) { - if (ORTB_VIDEO_PARAMS[paramName](videoParams[paramName])) { - videoObj[paramName] = videoParams[paramName]; - } else { - logWarn(`The OpenRTB video param ${paramName} has been skipped due to misformating. Please refer to OpenRTB 2.5 spec.`); - } - } - }); - - return videoObj; -}; - function buildCustomParams(bid) { if (bid.params && bid.params.custom) { return { @@ -231,19 +134,19 @@ function buildUser(bid) { } function injectEids(openRtbBidRequest, validBidRequests) { - const bidUserIdAsEids = deepAccess(validBidRequests, '0.userIdAsEids'); - if (isArray(bidUserIdAsEids) && bidUserIdAsEids.length > 0) { - deepSetValue(openRtbBidRequest, 'user.eids', bidUserIdAsEids); - deepSetValue(openRtbBidRequest, 'user.ext.eids', bidUserIdAsEids); + const bidUserIdAsEids = utils.deepAccess(validBidRequests, '0.userIdAsEids'); + if (utils.isArray(bidUserIdAsEids) && bidUserIdAsEids.length > 0) { + utils.deepSetValue(openRtbBidRequest, 'user.eids', bidUserIdAsEids); + utils.deepSetValue(openRtbBidRequest, 'user.ext.eids', bidUserIdAsEids); } } function buildBanner(bid) { - if (deepAccess(bid, 'mediaTypes.banner')) { + if (utils.deepAccess(bid, 'mediaTypes.banner')) { // Get Sizes from MediaTypes Object, Will always take first size, will be overrided by params for exact w,h - if (deepAccess(bid, 'mediaTypes.banner.sizes') && !bid.params.height && !bid.params.width) { - let sizes = deepAccess(bid, 'mediaTypes.banner.sizes'); - if (isArray(sizes) && sizes.length > 0) { + if (utils.deepAccess(bid, 'mediaTypes.banner.sizes') && !bid.params.height && !bid.params.width) { + let sizes = utils.deepAccess(bid, 'mediaTypes.banner.sizes'); + if (utils.isArray(sizes) && sizes.length > 0) { return { h: sizes[0][1], w: sizes[0][0], diff --git a/modules/deepintentBidAdapter.md b/modules/deepintentBidAdapter.md index 84c375d69a4..79a6a1679e2 100644 --- a/modules/deepintentBidAdapter.md +++ b/modules/deepintentBidAdapter.md @@ -8,7 +8,7 @@ Maintainer: prebid@deepintent.com # Description -Deepintent currently supports the BANNER and VIDEO type ads through prebid js +Deepintent currently supports the BANNER type ads through prebid js Module that connects to Deepintent's demand sources. @@ -40,41 +40,6 @@ Module that connects to Deepintent's demand sources. ]; ``` -# Sample Video Ad Unit -``` -var adVideoAdUnits = [ -{ - code: 'test-div-video', - mediaTypes: { - video: { - playerSize: [640, 480], // required - context: 'instream' //required - } - }, - bids: [{ - bidder: 'deepintent', - params: { - tagId: '1300', // Required parameter // required - video: { - mimes: ['video/mp4','video/x-flv'], // required - skippable: true, // optional - minduration: 5, // optional - maxduration: 30, // optional - startdelay: 5, // optional - playbackmethod: [1,3], // optional - api: [ 1, 2 ], // optional - protocols: [ 2, 3 ], // optional - battr: [ 13, 14 ], // optional - linearity: 1, // optional - placement: 2, // optional - minbitrate: 10, // optional - maxbitrate: 10 // optional - } - } - }] -}] -``` - ###Recommended User Sync Configuration ```javascript diff --git a/modules/deepintentDpesIdSystem.js b/modules/deepintentDpesIdSystem.js index 43c7af1b3cc..375c8c07ed1 100644 --- a/modules/deepintentDpesIdSystem.js +++ b/modules/deepintentDpesIdSystem.js @@ -9,7 +9,7 @@ import { submodule } from '../src/hook.js'; import { getStorageManager } from '../src/storageManager.js'; const MODULE_NAME = 'deepintentId'; -export const storage = getStorageManager({gvlid: null, moduleName: MODULE_NAME}); +export const storage = getStorageManager(null, MODULE_NAME); /** @type {Submodule} */ export const deepintentDpesSubmodule = { diff --git a/modules/deltaprojectsBidAdapter.js b/modules/deltaprojectsBidAdapter.js deleted file mode 100644 index 33df5bd252e..00000000000 --- a/modules/deltaprojectsBidAdapter.js +++ /dev/null @@ -1,252 +0,0 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER } from '../src/mediaTypes.js'; -import { - _each, _map, isFn, isNumber, createTrackPixelHtml, deepAccess, parseUrl, logWarn, logError -} from '../src/utils.js'; -import {config} from '../src/config.js'; - -export const BIDDER_CODE = 'deltaprojects'; -export const BIDDER_ENDPOINT_URL = 'https://d5p.de17a.com/dogfight/prebid'; -export const USERSYNC_URL = 'https://userservice.de17a.com/getuid/prebid'; - -/** -- isBidRequestValid --**/ -function isBidRequestValid(bid) { - if (!bid) return false; - - if (bid.bidder !== BIDDER_CODE) return false; - - // publisher id is required - const publisherId = deepAccess(bid, 'params.publisherId') - if (!publisherId) { - logError('Invalid bid request, missing publisher id in params'); - return false; - } - - return true; -} - -/** -- Build requests --**/ -function buildRequests(validBidRequests, bidderRequest) { - /** == shared ==**/ - // -- build id - const id = bidderRequest.auctionId; - - // -- build site - const loc = parseUrl(bidderRequest.refererInfo.referer); - const publisherId = setOnAny(validBidRequests, 'params.publisherId'); - const siteId = setOnAny(validBidRequests, 'params.siteId'); - const site = { - id: siteId, - domain: loc.hostname, - page: loc.href, - ref: loc.href, - publisher: { id: publisherId }, - }; - - // -- build device - const ua = navigator.userAgent; - const device = { - ua, - w: screen.width, - h: screen.height - } - - // -- build user, reg - let user = { ext: {} }; - const regs = { ext: {} }; - const gdprConsent = bidderRequest && bidderRequest.gdprConsent; - if (gdprConsent) { - user.ext = { consent: gdprConsent.consentString }; - if (typeof gdprConsent.gdprApplies == 'boolean') { - regs.ext.gdpr = gdprConsent.gdprApplies ? 1 : 0 - } - } - - // -- build tmax - let tmax = (bidderRequest && bidderRequest.timeout > 0) ? bidderRequest.timeout : undefined; - - // build bid specific - return validBidRequests.map(validBidRequest => { - const openRTBRequest = buildOpenRTBRequest(validBidRequest, id, site, device, user, tmax, regs); - return { - method: 'POST', - url: BIDDER_ENDPOINT_URL, - data: openRTBRequest, - options: { contentType: 'application/json' }, - bids: [validBidRequest], - }; - }); -} - -function buildOpenRTBRequest(validBidRequest, id, site, device, user, tmax, regs) { - // build cur - const currency = config.getConfig('currency.adServerCurrency') || deepAccess(validBidRequest, 'params.currency'); - const cur = currency && [currency]; - - // build impression - const impression = buildImpression(validBidRequest, currency); - - // build test - const test = deepAccess(validBidRequest, 'params.test') ? 1 : 0 - - const at = 1 - - // build source - const source = { - tid: validBidRequest.transactionId, - fd: 1, - } - - return { - id, - at, - imp: [impression], - site, - device, - user, - test, - tmax, - cur, - source, - regs, - ext: {}, - }; -} - -function buildImpression(bid, currency) { - const impression = { - id: bid.bidId, - tagid: bid.params.tagId, - ext: {}, - }; - - const bannerMediaType = deepAccess(bid, `mediaTypes.${BANNER}`); - impression.banner = buildImpressionBanner(bid, bannerMediaType); - - // bid floor - const bidFloor = getBidFloor(bid, BANNER, '*', currency); - if (bidFloor) { - impression.bidfloor = bidFloor.floor; - impression.bidfloorcur = bidFloor.currency; - } - - return impression; -} - -function buildImpressionBanner(bid, bannerMediaType) { - const bannerSizes = (bannerMediaType && bannerMediaType.sizes) || bid.sizes; - return { - format: _map(bannerSizes, ([width, height]) => ({ w: width, h: height })), - }; -} - -/** -- Interpret response --**/ -function interpretResponse(serverResponse) { - if (!serverResponse.body) { - logWarn('Response body is invalid, return !!'); - return []; - } - - const { body: { id, seatbid, cur } } = serverResponse; - if (!id || !seatbid) { - logWarn('Id / seatbid of response is invalid, return !!'); - return []; - } - - const bidResponses = []; - - _each(seatbid, seatbid => { - _each(seatbid.bid, bid => { - const bidObj = { - requestId: bid.impid, - cpm: parseFloat(bid.price), - width: parseInt(bid.w), - height: parseInt(bid.h), - creativeId: bid.crid || bid.id, - dealId: bid.dealid || null, - currency: cur, - netRevenue: true, - ttl: 60, - }; - - bidObj.mediaType = BANNER; - bidObj.ad = bid.adm; - if (bid.nurl) { - bidObj.ad += createTrackPixelHtml(decodeURIComponent(bid.nurl)); - } - if (bid.ext) { - bidObj[BIDDER_CODE] = bid.ext; - } - bidResponses.push(bidObj); - }); - }); - return bidResponses; -} - -/** -- On Bid Won -- **/ -function onBidWon(bid) { - let cpm = bid.cpm; - if (bid.currency && bid.currency !== bid.originalCurrency && typeof bid.getCpmInNewCurrency === 'function') { - cpm = bid.getCpmInNewCurrency(bid.originalCurrency); - } - const wonPrice = Math.round(cpm * 1000000); - const wonPriceMacroPatten = /\$\{AUCTION_PRICE:B64\}/g; - bid.ad = bid.ad.replace(wonPriceMacroPatten, wonPrice); -} - -/** -- Get user syncs --**/ -function getUserSyncs(syncOptions, serverResponses, gdprConsent) { - const syncs = [] - - if (syncOptions.pixelEnabled) { - let gdprParams; - if (gdprConsent) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - gdprParams = `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - gdprParams = `?gdpr_consent=${gdprConsent.consentString}`; - } - } else { - gdprParams = ''; - } - syncs.push({ - type: 'image', - url: USERSYNC_URL + gdprParams - }); - } - return syncs; -} - -/** -- Get bid floor --**/ -export function getBidFloor(bid, mediaType, size, currency) { - if (isFn(bid.getFloor)) { - const bidFloorCurrency = currency || 'USD'; - const bidFloor = bid.getFloor({currency: bidFloorCurrency, mediaType: mediaType, size: size}); - if (isNumber(bidFloor.floor)) { - return bidFloor; - } - } -} - -/** -- Helper methods --**/ -function setOnAny(collection, key) { - for (let i = 0, result; i < collection.length; i++) { - result = deepAccess(collection[i], key); - if (result) { - return result; - } - } -} - -/** -- Register -- */ -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER], - isBidRequestValid, - buildRequests, - interpretResponse, - onBidWon, - getUserSyncs, -}; - -registerBidder(spec); diff --git a/modules/deltaprojectsBidAdapter.md b/modules/deltaprojectsBidAdapter.md deleted file mode 100644 index 97cef4dd228..00000000000 --- a/modules/deltaprojectsBidAdapter.md +++ /dev/null @@ -1,32 +0,0 @@ -# Overview - -``` -Module Name: Delta Projects Bid Adapter -Module Type: Bidder Adapter -Maintainer: dev@deltaprojects.com -``` - -# Description - -Connects to Delta Projects DSP for bids. - -# Test Parameters -``` -// define banner unit -var bannerUnit = { - code: 'div-gpt-ad-1460505748561-0', - mediaTypes: { - banner: { - sizes: [[300, 250], [300,600]], - } - }, - // Replace this object to test a new Adapter! - bids: [{ - bidder: 'deltaprojects', - params: { - publisherId: '4' //required - } - }] -}; -``` - diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 7f8ad3351fa..79cb03ec001 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -9,7 +9,7 @@ import { config } from '../src/config.js'; import { getHook, submodule } from '../src/hook.js'; import { auctionManager } from '../src/auctionManager.js'; import { gdprDataHandler, uspDataHandler } from '../src/adapterManager.js'; -import * as events from '../src/events.js'; +import events from '../src/events.js'; import CONSTANTS from '../src/constants.json'; /** @@ -88,14 +88,7 @@ export function buildDfpVideoUrl(options) { sz: parseSizesInput(deepAccess(adUnit, 'mediaTypes.video.playerSize')).join('|'), url: encodeURIComponent(location.href), }; - - const urlSearchComponent = urlComponents.search; - const urlSzParam = urlSearchComponent && urlSearchComponent.sz - if (urlSzParam) { - derivedParams.sz = urlSzParam + '|' + derivedParams.sz; - } - - let encodedCustomParams = getCustParams(bid, options, urlSearchComponent && urlSearchComponent.cust_params); + const encodedCustomParams = getCustParams(bid, options); const queryParams = Object.assign({}, defaultParamConstants, @@ -118,11 +111,12 @@ export function buildDfpVideoUrl(options) { const uspConsent = uspDataHandler.getConsentData(); if (uspConsent) { queryParams.us_privacy = uspConsent; } - return buildUrl(Object.assign({ + return buildUrl({ protocol: 'https', host: 'securepubads.g.doubleclick.net', - pathname: '/gampad/ads' - }, urlComponents, { search: queryParams })); + pathname: '/gampad/ads', + search: queryParams + }); } export function notifyTranslationModule(fn) { @@ -233,7 +227,9 @@ function buildUrlFromAdserverUrlComponents(components, bid, options) { const descriptionUrl = getDescriptionUrl(bid, components, 'search'); if (descriptionUrl) { components.search.description_url = descriptionUrl; } - components.search.cust_params = getCustParams(bid, options, components.search.cust_params); + const encodedCustomParams = getCustParams(bid, options); + components.search.cust_params = (components.search.cust_params) ? components.search.cust_params + '%26' + encodedCustomParams : encodedCustomParams; + return buildUrl(components); } @@ -262,7 +258,7 @@ function getDescriptionUrl(bid, components, prop) { * @param {Object} options this is the options passed in from the `buildDfpVideoUrl` function * @return {Object} Encoded key value pairs for cust_params */ -function getCustParams(bid, options, urlCustParams) { +function getCustParams(bid, options) { const adserverTargeting = (bid && bid.adserverTargeting) || {}; let allTargetingData = {}; @@ -285,12 +281,7 @@ function getCustParams(bid, options, urlCustParams) { // merge the prebid + publisher targeting sets const publisherTargetingSet = deepAccess(options, 'params.cust_params'); const targetingSet = Object.assign({}, prebidTargetingSet, publisherTargetingSet); - let encodedParams = encodeURIComponent(formatQS(targetingSet)); - if (urlCustParams) { - encodedParams = urlCustParams + '%26' + encodedParams; - } - - return encodedParams; + return encodeURIComponent(formatQS(targetingSet)); } registerVideoSupport('dfp', { diff --git a/modules/dgkeywordRtdProvider.js b/modules/dgkeywordRtdProvider.js index 26a8257077a..58cec36a6b9 100644 --- a/modules/dgkeywordRtdProvider.js +++ b/modules/dgkeywordRtdProvider.js @@ -7,7 +7,7 @@ * @requires module:modules/realTimeData */ -import { logMessage, deepSetValue, logError, logInfo } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { ajax } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; import { getGlobal } from '../src/prebidGlobal.js'; @@ -26,19 +26,19 @@ export function getDgKeywordsAndSet(reqBidsConfigObj, callback, moduleConfig, us const url = (moduleConfig && moduleConfig.params && moduleConfig.params.url) ? moduleConfig.params.url : URL + encodeURIComponent(window.location.href); const adUnits = reqBidsConfigObj.adUnits || getGlobal().adUnits; let isFinish = false; - logMessage('[dgkeyword sub module]', adUnits, timeout); + utils.logMessage('[dgkeyword sub module]', adUnits, timeout); let setKeywordTargetBidders = getTargetBidderOfDgKeywords(adUnits); if (setKeywordTargetBidders.length <= 0) { - logMessage('[dgkeyword sub module] no dgkeyword targets.'); + utils.logMessage('[dgkeyword sub module] no dgkeyword targets.'); callback(); } else { - logMessage('[dgkeyword sub module] dgkeyword targets:', setKeywordTargetBidders); - logMessage('[dgkeyword sub module] get targets from profile api start.'); + utils.logMessage('[dgkeyword sub module] dgkeyword targets:', setKeywordTargetBidders); + utils.logMessage('[dgkeyword sub module] get targets from profile api start.'); ajax(url, { success: function(response) { const res = JSON.parse(response); if (!isFinish) { - logMessage('[dgkeyword sub module] get targets from profile api end.'); + utils.logMessage('[dgkeyword sub module] get targets from profile api end.'); if (res) { let keywords = {}; if (res['s'] != null && res['s'].length > 0) { @@ -60,8 +60,8 @@ export function getDgKeywordsAndSet(reqBidsConfigObj, callback, moduleConfig, us if (!reqBidsConfigObj._ignoreSetOrtb2) { // set keywrods to ortb2 let addOrtb2 = {}; - deepSetValue(addOrtb2, 'site.keywords', keywords); - deepSetValue(addOrtb2, 'user.keywords', keywords); + utils.deepSetValue(addOrtb2, 'site.keywords', keywords); + utils.deepSetValue(addOrtb2, 'user.keywords', keywords); const ortb2 = {ortb2: addOrtb2}; reqBidsConfigObj.setBidderConfig({ bidders: Object.keys(targetBidKeys), config: ortb2 }); } @@ -73,16 +73,17 @@ export function getDgKeywordsAndSet(reqBidsConfigObj, callback, moduleConfig, us }, error: function(errorStatus) { // error occur - logError('[dgkeyword sub module] profile api access error.', errorStatus); + utils.logError('[dgkeyword sub module] profile api access error.', errorStatus); callback(); } }, null, { withCredentials: true, + contentType: 'application/json', }); setTimeout(function () { if (!isFinish) { // profile api timeout - logInfo('[dgkeyword sub module] profile api timeout. [timeout: ' + timeout + 'ms]'); + utils.logInfo('[dgkeyword sub module] profile api timeout. [timeout: ' + timeout + 'ms]'); isFinish = true; } callback(); diff --git a/modules/displayioBidAdapter.js b/modules/displayioBidAdapter.js deleted file mode 100644 index 55a2f4a8604..00000000000 --- a/modules/displayioBidAdapter.js +++ /dev/null @@ -1,157 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; - -const BIDDER_VERSION = '1.0.0'; -const BIDDER_CODE = 'displayio'; -const GVLID = 999; -const BID_TTL = 300; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; -const DEFAULT_CURRENCY = 'USD'; - -export const spec = { - code: BIDDER_CODE, - gvlid: GVLID, - supportedMediaTypes: SUPPORTED_AD_TYPES, - isBidRequestValid: function(bid) { - return !!(bid.params && bid.params.placementId && bid.params.siteId && - bid.params.adsSrvDomain && bid.params.cdnDomain); - }, - buildRequests: function (bidRequests, bidderRequest) { - return bidRequests.map(bid => { - let url = '//' + bid.params.adsSrvDomain + '/srv?method=getPlacement&app=' + - bid.params.siteId + '&placement=' + bid.params.placementId; - const data = this._getPayload(bid, bidderRequest); - return { - method: 'POST', - headers: {'Content-Type': 'application/json;charset=utf-8'}, - url, - data - }; - }); - }, - interpretResponse: function (serverResponse, serverRequest) { - const ads = serverResponse.body.data.ads; - const bidResponses = []; - const { data } = serverRequest.data; - if (ads.length) { - const adData = ads[0].ad.data; - const bidResponse = { - requestId: data.id, - cpm: adData.ecpm, - width: adData.w, - height: adData.h, - netRevenue: true, - ttl: BID_TTL, - creativeId: adData.adId || 0, - currency: DEFAULT_CURRENCY, - referrer: data.data.ref, - mediaType: ads[0].ad.subtype, - ad: adData.markup, - placement: data.placement, - adData: adData - }; - if (bidResponse.vastUrl === 'videoVast') { - bidResponse.vastUrl = adData.videos[0].url - } - bidResponses.push(bidResponse); - } - return bidResponses; - }, - _getPayload: function (bid, bidderRequest) { - const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection; - const userSession = 'us_web_xxxxxxxxxxxx'.replace(/[x]/g, c => { - let r = Math.random() * 16 | 0; - let v = c === 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); - const { params } = bid; - const { siteId, placementId } = params; - const { refererInfo, uspConsent, gdprConsent } = bidderRequest; - const mediation = {consent: '-1', gdpr: '-1'}; - if (gdprConsent) { - if (gdprConsent.consentString !== undefined) { - mediation.consent = gdprConsent.consentString; - } - if (gdprConsent.gdprApplies !== undefined) { - mediation.gdpr = gdprConsent.gdprApplies ? '1' : '0'; - } - } - const payload = { - userSession, - data: { - id: bid.bidId, - action: 'getPlacement', - app: siteId, - placement: placementId, - data: { - pagecat: params.pageCategory ? params.pageCategory.split(',').map(k => k.trim()) : [], - keywords: params.keywords ? params.keywords.split(',').map(k => k.trim()) : [], - lang_content: document.documentElement.lang, - lang: window.navigator.language, - domain: window.location.hostname, - page: window.location.href, - ref: refererInfo.referer, - userids: _getUserIDs(), - geo: '', - }, - complianceData: { - child: '-1', - us_privacy: uspConsent, - dnt: window.navigator.doNotTrack, - iabConsent: {}, - mediation: { - consent: mediation.consent, - gdpr: mediation.gdpr, - } - }, - integration: 'JS', - omidpn: 'Displayio', - mediationPlatform: 0, - prebidVersion: BIDDER_VERSION, - device: { - w: window.screen.width, - h: window.screen.height, - connection_type: connection ? connection.effectiveType : '', - } - } - } - if (navigator.permissions) { - navigator.permissions.query({ name: 'geolocation' }) - .then((result) => { - if (result.state === 'granted') { - payload.data.data.geo = _getGeoData(); - } - }); - } - return payload - } -}; - -function _getUserIDs () { - let ids = {}; - try { - ids = window.owpbjs.getUserIdsAsEids(); - } catch (e) {} - return ids; -} - -async function _getGeoData () { - let geoData = null; - const getCurrentPosition = () => { - return new Promise((resolve, reject) => - navigator.geolocation.getCurrentPosition(resolve, reject) - ); - } - try { - const position = await getCurrentPosition(); - let {latitude, longitude, accuracy} = position.coords; - geoData = { - 'lat': latitude, - 'lng': longitude, - 'precision': accuracy - }; - } catch (e) {} - return geoData -} - -registerBidder(spec); diff --git a/modules/displayioBidAdapter.md b/modules/displayioBidAdapter.md deleted file mode 100644 index 41505ee966e..00000000000 --- a/modules/displayioBidAdapter.md +++ /dev/null @@ -1,148 +0,0 @@ -# Overview - -``` -Module Name: DisplayIO Bidder Adapter -Module Type: Bidder Adapter -``` - -# Description - -Module that connects to display.io's demand sources. -Web mobile (not relevant for web desktop). - - -#Features -| Feature | | Feature | | -|---------------|---------------------------------------------------------|-----------------------|-----| -| Bidder Code | displayio | Prebid member | no | -| Media Types | Banner, video.
Sizes (display 320x480 / vertical video) | GVL ID | no | -| GDPR Support | yes | Prebid.js Adapter | yes | -| USP Support | yes | Prebid Server Adapter | no | - - -#Global configuration -```javascript - - - -`; - let data = { - bidderCode: BIDDER_CODE, - requestId: res.id, - currency: res.cur, - cpm: parseFloat(bid.price) || 0, - netRevenue: NET_REVENUE, - width: bid.w, - height: bid.h, - creativeId: bid.crid, - ttl: TTL, - ad: bid.adm + callImpBeacon, - meta: { - advertiserDomains: bid.adomain || [], - }, - }; - if (!isEmpty(dealId)) { - data.dealId = dealId; - } - bidResponses.push(data); - } - return bidResponses; - }, - - /* - * Register the user sync pixels which should be dropped after the auction. - * - * @params {syncOptions} syncOptions which user syncs are allowed? - * @params {ServerResponse[]} serverResponses List of server's responses. - * @return {UserSync[]} The user syncs which should be dropped. - * - */ - getUserSyncs: (syncOptions, serverResponses) => { - return []; - }, -}; - -registerBidder(spec); diff --git a/modules/freewheel-sspBidAdapter.js b/modules/freewheel-sspBidAdapter.js index eca31dd5a95..fa2f7b4cd6b 100644 --- a/modules/freewheel-sspBidAdapter.js +++ b/modules/freewheel-sspBidAdapter.js @@ -1,4 +1,4 @@ -import { logWarn, isArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; @@ -72,7 +72,7 @@ function getPricing(xmlNode) { price: priceNode.textContent || priceNode.innerText }; } else { - logWarn('PREBID - ' + BIDDER_CODE + ': No bid received or missing pricing extension.'); + utils.logWarn('PREBID - ' + BIDDER_CODE + ': No bid received or missing pricing extension.'); } return princingData; @@ -312,12 +312,6 @@ export const spec = { requestParams._fw_us_privacy = bidderRequest.uspConsent; } - // Add schain object - var schain = currentBidRequest.schain; - if (schain) { - requestParams.schain = schain; - } - var vastParams = currentBidRequest.params.vastUrlParams; if (typeof vastParams === 'object') { for (var key in vastParams) { @@ -335,7 +329,7 @@ export const spec = { var playerSize = []; if (currentBidRequest.mediaTypes.video && currentBidRequest.mediaTypes.video.playerSize) { // If mediaTypes is video, get size from mediaTypes.video.playerSize per http://prebid.org/blog/pbjs-3 - if (isArray(currentBidRequest.mediaTypes.video.playerSize[0])) { + if (utils.isArray(currentBidRequest.mediaTypes.video.playerSize[0])) { playerSize = currentBidRequest.mediaTypes.video.playerSize[0]; } else { playerSize = currentBidRequest.mediaTypes.video.playerSize; @@ -377,7 +371,7 @@ export const spec = { var playerSize = []; if (bidrequest.mediaTypes.video && bidrequest.mediaTypes.video.playerSize) { // If mediaTypes is video, get size from mediaTypes.video.playerSize per http://prebid.org/blog/pbjs-3 - if (isArray(bidrequest.mediaTypes.video.playerSize[0])) { + if (utils.isArray(bidrequest.mediaTypes.video.playerSize[0])) { playerSize = bidrequest.mediaTypes.video.playerSize[0]; } else { playerSize = bidrequest.mediaTypes.video.playerSize; @@ -399,7 +393,7 @@ export const spec = { var parser = new DOMParser(); xmlDoc = parser.parseFromString(serverResponse, 'application/xml'); } catch (err) { - logWarn('Prebid.js - ' + BIDDER_CODE + ' : ' + err); + utils.logWarn('Prebid.js - ' + BIDDER_CODE + ' : ' + err); return; } @@ -426,7 +420,7 @@ export const spec = { currency: princingData.currency, netRevenue: true, ttl: 360, - meta: { advertiserDomains: princingData.adomain && isArray(princingData.adomain) ? princingData.adomain : [] }, + meta: { advertiserDomains: princingData.adomain && utils.isArray(princingData.adomain) ? princingData.adomain : [] }, dealId: dealId, campaignId: campaignId, bannerId: bannerId diff --git a/modules/ftrackIdSystem.js b/modules/ftrackIdSystem.js deleted file mode 100644 index 21206109ee0..00000000000 --- a/modules/ftrackIdSystem.js +++ /dev/null @@ -1,198 +0,0 @@ -/** - * This module adds ftrack to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/ftrack - * @requires module:modules/userId - */ - -import * as utils from '../src/utils.js'; -import { submodule } from '../src/hook.js'; -import { getStorageManager } from '../src/storageManager.js'; -import { uspDataHandler } from '../src/adapterManager.js'; - -const MODULE_NAME = 'ftrackId'; -const LOG_PREFIX = 'FTRACK - '; -const LOCAL_STORAGE_EXP_DAYS = 30; -const VENDOR_ID = null; -const LOCAL_STORAGE = 'html5'; -const FTRACK_STORAGE_NAME = 'ftrackId'; -const FTRACK_PRIVACY_STORAGE_NAME = `${FTRACK_STORAGE_NAME}_privacy`; -const FTRACK_URL = 'https://d9.flashtalking.com/d9core'; -const storage = getStorageManager({gvlid: VENDOR_ID, moduleName: MODULE_NAME}); - -let consentInfo = { - gdpr: { - applies: 0, - consentString: null, - pd: null - }, - usPrivacy: { - value: null - } -}; - -/** @type {Submodule} */ -export const ftrackIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: `ftrack`, - - /** - * Decodes the 'value' - * @function decode (required method) - * @param {(Object|string)} value - * @param {SubmoduleConfig|undefined} config - * @returns {(Object|undefined)} an object with the key being ideally camel case - * similar to the module name and ending in id or Id - */ - decode (value, config) { - return { - ftrackId: value - }; - }, - - /** - * performs action(s) to obtain ids from D9 and return the Device IDs - * should be the only method that gets a new ID (from ajax calls or a cookie/local storage) - * @function getId (required method) - * @param {SubmoduleConfig} config - * @param {ConsentData} consentData - * @param {(Object|undefined)} cacheIdObj - * @returns {IdResponse|undefined} - */ - getId (config, consentData, cacheIdObj) { - if (this.isConfigOk(config) === false || this.isThereConsent(consentData) === false) return undefined; - - return { - callback: function () { - window.D9v = { - UserID: '99999999999999', - CampID: '3175', - CCampID: '148556' - }; - window.D9r = { - callback: function(response) { - if (response) { - storage.setDataInLocalStorage(`${FTRACK_STORAGE_NAME}_exp`, (new Date(Date.now() + (1000 * 60 * 60 * 24 * LOCAL_STORAGE_EXP_DAYS))).toUTCString()); - storage.setDataInLocalStorage(`${FTRACK_STORAGE_NAME}`, JSON.stringify(response)); - - storage.setDataInLocalStorage(`${FTRACK_PRIVACY_STORAGE_NAME}_exp`, (new Date(Date.now() + (1000 * 60 * 60 * 24 * LOCAL_STORAGE_EXP_DAYS))).toUTCString()); - storage.setDataInLocalStorage(`${FTRACK_PRIVACY_STORAGE_NAME}`, JSON.stringify(consentInfo)); - }; - - return response; - } - }; - - // If config.params.ids does not exist, set defaults - if (!config.params.hasOwnProperty('ids')) { - window.D9r.DeviceID = true; - window.D9r.SingleDeviceID = true; - } else { - if (config.params.ids.hasOwnProperty('device id') && config.params.ids['device id'] === true) { - window.D9r.DeviceID = true; - } - if (config.params.ids.hasOwnProperty('single device id') && config.params.ids['single device id'] === true) { - window.D9r.SingleDeviceID = true; - } - if (config.params.ids.hasOwnProperty('household id') && config.params.ids['household id'] === true) { - window.D9r.HHID = true; - } - } - - if (config.params && config.params.url && config.params.url === FTRACK_URL) { - var ftrackScript = document.createElement('script'); - ftrackScript.setAttribute('src', config.params.url); - window.document.body.appendChild(ftrackScript); - } - } - }; - }, - - /** - * Called when IDs are already in localStorage - * should just be adding additional data to the cacheIdObj object - * @function extendId (optional method) - * @param {SubmoduleConfig} config - * @param {ConsentData} consentData - * @param {(Object|undefined)} cacheIdObj - * @returns {IdResponse|undefined} - */ - extendId (config, consentData, cacheIdObj) { - this.isConfigOk(config); - return cacheIdObj; - }, - - /* - * Validates the config, if it is not correct, then info cannot be saved in localstorage - * @function isConfigOk - * @param {SubmoduleConfig} config from HTML - * @returns {true|false} - */ - isConfigOk: function(config) { - if (!config.storage || !config.storage.type || !config.storage.name) { - utils.logError(LOG_PREFIX + 'config.storage required to be set.'); - return false; - } - - // in a future release, we may return false if storage type or name are not set as required - if (config.storage.type !== LOCAL_STORAGE) { - utils.logWarn(LOG_PREFIX + 'config.storage.type recommended to be "' + LOCAL_STORAGE + '".'); - } - // in a future release, we may return false if storage type or name are not set as required - if (config.storage.name !== FTRACK_STORAGE_NAME) { - utils.logWarn(LOG_PREFIX + 'config.storage.name recommended to be "' + FTRACK_STORAGE_NAME + '".'); - } - - if (!config.hasOwnProperty('params') || !config.params.hasOwnProperty('url') || config.params.url !== FTRACK_URL) { - utils.logWarn(LOG_PREFIX + 'config.params.url is required for ftrack to run. Url should be "' + FTRACK_URL + '".'); - return false; - } - - return true; - }, - - isThereConsent: function(consentData) { - let consentValue = true; - - /* - * Scenario 1: GDPR - * if GDPR Applies is true|1, we do not have consent - * if GDPR Applies does not exist or is false|0, we do not NOT have consent - */ - if (consentData && consentData.gdprApplies && (consentData.gdprApplies === true || consentData.gdprApplies === 1)) { - consentInfo.gdpr.applies = 1; - consentValue = false; - } - // If consentString exists, then we store it even though we are not using it - if (consentData && consentData.consentString !== 'undefined' && !utils.isEmpty(consentData.consentString) && !utils.isEmptyStr(consentData.consentString)) { - consentInfo.gdpr.consentString = consentData.consentString; - } - - /* - * Scenario 2: CCPA/us_privacy - * if usp exists (assuming this check determines the location of the device to be within the California) - * parse the us_privacy string to see if we have consent - * for version 1 of us_privacy strings, if 'Opt-Out Sale' is 'Y' we do not track - */ - const usp = uspDataHandler.getConsentData(); - let usPrivacyVersion; - // let usPrivacyOptOut; - let usPrivacyOptOutSale; - // let usPrivacyLSPA; - if (typeof usp !== 'undefined' && !utils.isEmpty(usp) && !utils.isEmptyStr(usp)) { - consentInfo.usPrivacy.value = usp; - usPrivacyVersion = usp[0]; - // usPrivacyOptOut = usp[1]; - usPrivacyOptOutSale = usp[2]; - // usPrivacyLSPA = usp[3]; - } - if (usPrivacyVersion == 1 && usPrivacyOptOutSale === 'Y') consentValue = false; - - return consentValue; - } -}; - -submodule('userId', ftrackIdSubmodule); diff --git a/modules/ftrackIdSystem.md b/modules/ftrackIdSystem.md deleted file mode 100644 index 0c92f5afab1..00000000000 --- a/modules/ftrackIdSystem.md +++ /dev/null @@ -1,83 +0,0 @@ -# Flashtalking's FTrack Identity Framework User ID Module - -*The FTrack Identity Framework User ID Module allows publishers to take advantage of Flashtalking's FTrack ID during the bidding process.* - -### [FTrack](https://www.flashtalking.com/identity-framework#FTrack) - -Flashtalking’s cookieless tracking technology uses probabilistic device recognition to derive a privacy-friendly persistent ID for each device. - -**ANTI-FINGERPRINTING** -FTrack operates in strict compliance with [Google’s definition of anti-fingerprinting](https://blog.google/products/ads-commerce/2021-01-privacy-sandbox/). FTrack does not access PII or sensitive information and provides consumers with notification and choice on every impression. We do not participate in the types of activities that most concern privacy advocates (profiling consumers, building audience segments, and/or monetizing consumer data). - -**GDPR COMPLIANT** -Flashtalking is integrated with the IAB EU’s Transparency & Consent Framework (TCF) and operates on a Consent legal basis where required. As a Data Processor under GDPR, Flashtalking does not combine data across customers nor sell data to third parties. - ---- - -### Support or Maintenance: - -Questions? Comments? Bugs? Praise? Please contact FlashTalking's Prebid Support at [prebid-support@flashtalking.com](mailto:prebid-support@flashtalking.com) - ---- - -### FTrack User ID Configuration - -The following configuration parameters are available: - -```javascript -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'FTrack', - params: { - url: 'https://d9.flashtalking.com/d9core', // required, if not populated ftrack will not run - ids: { - 'device id': true, - 'single device id': true, - 'household id': true - } - }, - storage: { - type: 'html5', // "html5" is the required storage type - name: 'FTrackId', // "FTrackId" is the required storage name - expires: 90, // storage lasts for 90 days - refreshInSeconds: 8*3600 // refresh ID every 8 hours to ensure it's fresh - } - }], - auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules - } -}); -``` - -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| :-- | :-- | :-- | :-- | :-- | -| name | Required | String | The name of this module: `"FTrack"` | `"FTrack"` | -| params | Required | Object | The IDs available, if not populated then the defaults "Device ID" and "Single Device ID" will be returned | | -| params.url | Required | String | The URL for the ftrack library reference. If not populate, ftrack will not run. | 'https://d9.flashtalking.com/d9core' | -| params.ids | Optional | Object | The ftrack IDs available, if not populated then the defaults "Device ID" and "Single Device ID" will be returned | | -| params.ids['device id'] | Optional | Boolean | Should ftrack return "device id". Set to `true` to return it. If set to `undefined` or `false`, ftrack will not return "device id". Default is `false` | `true` | -| params.ids['single device id'] | Optional | Boolean | Should ftrack return "single device id". Set to `true` to return it. If set to `undefined` or `false`, ftrack will not return "single device id". Default is `false` | `true` | -| params.ids['household id'] | Optional; _Requires pairing with either "device id" or "single device id"_ | Boolean | __1.__ Should ftrack return "household id". Set to `true` to attempt to return it. If set to `undefined` or `false`, ftrack will not return "household id". Default is `false`. __2.__ _This will only return "household id" if value of this field is `true` **AND** "household id" is defined on the device._ __3.__ _"household id" requires either "device id" or "single device id" to be also set to `true`, otherwise ftrack will not return "household id"._ | `true` | -| storage | Required | Object | Storage settings for how the User ID module will cache the FTrack ID locally | | -| storage.type | Required | String | This is where the results of the user ID will be stored. FTrack **requires** `"html5"`. | `"html5"` | -| storage.name | Required | String | The name of the local storage where the user ID will be stored. FTrack **requires** `"FTrackId"`. | `"FTrackId"` | -| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. FTrack recommends `90`. | `90` | -| storage.refreshInSeconds | Optional | Integer | How many seconds until the FTrack ID will be refreshed. FTrack strongly recommends 8 hours between refreshes | `8*3600` | - ---- - -### Privacy Policies. - -Complete information available on the Flashtalking [privacy policy page](https://www.flashtalking.com/privacypolicy). - -#### OPTING OUT OF INTEREST-BASED ADVERTISING & COLLECTION OF PERSONAL INFORMATION - -Please visit our [Opt Out Page](https://www.flashtalking.com/optout). - -#### REQUEST REMOVAL OF YOUR PERSONAL DATA (WHERE APPLICABLE) - -You may request by emailing [mailto:privacy@flashtalking.com](privacy@flashtalking.com). - -#### GDPR - -In its current state, Flashtalking’s FTrack Identity Framework User ID Module does not create an ID if a user's consentData is "truthy" (true, 1). In other words, if GDPR applies in any way to a user, FTrack does not create an ID. \ No newline at end of file diff --git a/modules/futureads.md b/modules/futureads.md deleted file mode 100644 index 7b1c1d55b7f..00000000000 --- a/modules/futureads.md +++ /dev/null @@ -1,48 +0,0 @@ -# Overview -Module Name: Future Ads Bidder Adapter -Module Type: Bidder Adapter -Maintainer: contact@futureads.io -# Description -Connects to Future Ads demand source to fetch bids. -Banner and Video formats are supported. -Please use ```futureads``` as the bidder code. -# Test Parameters -``` -var adUnits = [ - { - code: 'desktop-banner-ad-div', - sizes: [[300, 250]], // a display size - bids: [ - { - bidder: "futureads", - params: { - zone: '2eb6bd58-865c-47ce-af7f-a918108c3fd2' - } - } - ] - },{ - code: 'mobile-banner-ad-div', - sizes: [[300, 50]], // a mobile size - bids: [ - { - bidder: "futureads", - params: { - zone: '62211486-c50b-4356-9f0f-411778d31fcc' - } - } - ] - },{ - code: 'video-ad', - sizes: [[300, 50]], - mediaType: 'video', - bids: [ - { - bidder: "futureads", - params: { - zone: 'ebeb1e79-8cb4-4473-b2d0-2e24b7ff47fd' - } - } - ] - }, -]; -``` diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 22a70db0fab..68233ce7814 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -1,21 +1,9 @@ -import { - deepAccess, - deepSetValue, - getDNT, - inIframe, - isArray, - isFn, - isNumber, - isPlainObject, - isStr, - logError, - logWarn -} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; import {Renderer} from '../src/Renderer.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {includes} from '../src/polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js'; const ENDPOINTS = { 'gamoshi': 'https://rtb.gamoshi.io' @@ -52,7 +40,7 @@ export const helper = { return BANNER; }, getBidFloor(bid) { - if (!isFn(bid.getFloor)) { + if (!utils.isFn(bid.getFloor)) { return bid.params.bidfloor ? bid.params.bidfloor : null; } @@ -62,7 +50,7 @@ export const helper = { currency: 'USD' }); - if (isPlainObject(bidFloor) && !isNaN(bidFloor.floor) && bidFloor.currency === 'USD') { + if (utils.isPlainObject(bidFloor) && !isNaN(bidFloor.floor) && bidFloor.currency === 'USD') { return bidFloor.floor; } @@ -76,10 +64,10 @@ export const spec = { supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { - return !!bid.params.supplyPartnerId && isStr(bid.params.supplyPartnerId) && - (!bid.params['rtbEndpoint'] || isStr(bid.params['rtbEndpoint'])) && - (!bid.params.bidfloor || isNumber(bid.params.bidfloor)) && - (!bid.params['adpos'] || isNumber(bid.params['adpos'])) && + return !!bid.params.supplyPartnerId && utils.isStr(bid.params.supplyPartnerId) && + (!bid.params['rtbEndpoint'] || utils.isStr(bid.params['rtbEndpoint'])) && + (!bid.params.bidfloor || utils.isNumber(bid.params.bidfloor)) && + (!bid.params['adpos'] || utils.isNumber(bid.params['adpos'])) && (!bid.params['protocols'] || Array.isArray(bid.params['protocols'])) && (!bid.params.instl || bid.params.instl === 0 || bid.params.instl === 1); }, @@ -100,7 +88,7 @@ export const spec = { }, device: { ua: navigator.userAgent, - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, h: screen.height, w: screen.width, language: navigator.language @@ -111,18 +99,24 @@ export const spec = { source: {ext: {}}, regs: {ext: {}} }; + const gdprConsent = bidderRequest.gdprConsent; - const gdprConsent = getGdprConsent(bidderRequest); - rtbBidRequest.ext.gdpr_consent = gdprConsent; - deepSetValue(rtbBidRequest, 'regs.ext.gdpr', gdprConsent.consent_required === true ? 1 : 0); - deepSetValue(rtbBidRequest, 'user.ext.consent', gdprConsent.consent_string); + if (gdprConsent && gdprConsent.consentString && gdprConsent.gdprApplies) { + rtbBidRequest.ext.gdpr_consent = { + consent_string: gdprConsent.consentString, + consent_required: gdprConsent.gdprApplies + }; + + utils.deepSetValue(rtbBidRequest, 'regs.ext.gdpr', gdprConsent.gdprApplies === true ? 1 : 0); + utils.deepSetValue(rtbBidRequest, 'user.ext.consent', gdprConsent.consentString); + } if (validBidRequests[0].schain) { - deepSetValue(rtbBidRequest, 'source.ext.schain', validBidRequests[0].schain); + utils.deepSetValue(rtbBidRequest, 'source.ext.schain', validBidRequests[0].schain); } if (bidderRequest && bidderRequest.uspConsent) { - deepSetValue(rtbBidRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(rtbBidRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); } const imp = { @@ -144,7 +138,7 @@ export const spec = { w: sizes.length ? sizes[0][0] : 300, h: sizes.length ? sizes[0][1] : 250, pos: params.pos || 0, - topframe: inIframe() ? 0 : 1 + topframe: utils.inIframe() ? 0 : 1 } }); rtbBidRequest.imp.push(bannerImp); @@ -172,10 +166,10 @@ export const spec = { } }); - if (isArray(playerSize[0])) { + if (utils.isArray(playerSize[0])) { videoImp.video.w = playerSize[0][0]; videoImp.video.h = playerSize[0][1]; - } else if (isNumber(playerSize[0])) { + } else if (utils.isNumber(playerSize[0])) { videoImp.video.w = playerSize[0]; videoImp.video.h = playerSize[1]; } else { @@ -189,9 +183,8 @@ export const spec = { let eids = []; if (bidRequest && bidRequest.userId) { - addExternalUserId(eids, deepAccess(bidRequest, `userId.id5id.uid`), 'id5-sync.com', 'ID5ID'); - addExternalUserId(eids, deepAccess(bidRequest, `userId.tdid`), 'adserver.org', 'TDID'); - addExternalUserId(eids, deepAccess(bidRequest, `userId.idl_env`), 'liveramp.com', 'idl'); + addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.id5id.uid`), 'id5-sync.com', 'ID5ID'); + addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.tdid`), 'adserver.org', 'TDID'); } if (eids.length > 0) { rtbBidRequest.user.ext.eids = eids; @@ -213,7 +206,7 @@ export const spec = { interpretResponse: function (serverResponse, bidRequest) { const response = serverResponse && serverResponse.body; if (!response) { - logError('empty response'); + utils.logError('empty response'); return []; } @@ -239,11 +232,11 @@ export const spec = { } } - if (deepAccess(bidRequest.bidRequest, 'mediaTypes.' + outBid.mediaType)) { + if (utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.' + outBid.mediaType)) { if (outBid.mediaType === BANNER) { outBids.push(Object.assign({}, outBid, {ad: bid.adm})); } else if (outBid.mediaType === VIDEO) { - const context = deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); + const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); outBids.push(Object.assign({}, outBid, { vastUrl: bid.ext.vast_url, vastXml: bid.adm, @@ -322,7 +315,7 @@ function newRenderer(bidRequest, bid, rendererOptions = {}) { try { renderer.setRender(renderOutstream); } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); + utils.logWarn('Prebid Error calling setRender on renderer', err); } return renderer; } @@ -348,7 +341,7 @@ function renderOutstream(bid) { } function addExternalUserId(eids, value, source, rtiPartner) { - if (isStr(value)) { + if (utils.isStr(value)) { eids.push({ source, uids: [{ @@ -368,20 +361,4 @@ function replaceMacros(url, macros) { .replace('[US_PRIVACY]', macros.uspConsent); } -function getGdprConsent(bidderRequest) { - const gdprConsent = bidderRequest.gdprConsent; - - if (gdprConsent && gdprConsent.consentString && gdprConsent.gdprApplies) { - return { - consent_string: gdprConsent.consentString, - consent_required: gdprConsent.gdprApplies - }; - } - - return { - consent_required: false, - consent_string: '', - }; -} - registerBidder(spec); diff --git a/modules/gdprEnforcement.js b/modules/gdprEnforcement.js index 161f530f202..02a2da3a7a4 100644 --- a/modules/gdprEnforcement.js +++ b/modules/gdprEnforcement.js @@ -2,14 +2,16 @@ * This module gives publishers extra set of features to enforce individual purposes of TCF v2 */ -import {deepAccess, hasDeviceAccess, isArray, logWarn} from '../src/utils.js'; -import {config} from '../src/config.js'; -import adapterManager, {gdprDataHandler} from '../src/adapterManager.js'; -import {find, includes} from '../src/polyfill.js'; -import {registerSyncInner} from '../src/adapters/bidderFactory.js'; -import {getHook} from '../src/hook.js'; -import {validateStorageEnforcement} from '../src/storageManager.js'; -import * as events from '../src/events.js'; +import * as utils from '../src/utils.js'; +import { config } from '../src/config.js'; +import { hasDeviceAccess } from '../src/utils.js'; +import adapterManager, { gdprDataHandler } from '../src/adapterManager.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import { registerSyncInner } from '../src/adapters/bidderFactory.js'; +import { getHook } from '../src/hook.js'; +import { validateStorageEnforcement } from '../src/storageManager.js'; +import events from '../src/events.js'; import CONSTANTS from '../src/constants.json'; const TCF2 = { @@ -134,9 +136,9 @@ export function validateRules(rule, consentData, currentModule, gvlId) { } // get data from the consent string - const purposeConsent = deepAccess(consentData, `vendorData.purpose.consents.${purposeId}`); - const vendorConsent = deepAccess(consentData, `vendorData.vendor.consents.${gvlId}`); - const liTransparency = deepAccess(consentData, `vendorData.purpose.legitimateInterests.${purposeId}`); + const purposeConsent = utils.deepAccess(consentData, `vendorData.purpose.consents.${purposeId}`); + const vendorConsent = utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlId}`); + const liTransparency = utils.deepAccess(consentData, `vendorData.purpose.legitimateInterests.${purposeId}`); /* Since vendor exceptions have already been handled, the purpose as a whole is allowed if it's not being enforced @@ -168,7 +170,7 @@ export function deviceAccessHook(fn, gvlid, moduleName, result) { hasEnforcementHook: true }); if (!hasDeviceAccess()) { - logWarn('Device access is disabled by Publisher'); + utils.logWarn('Device access is disabled by Publisher'); result.valid = false; fn.call(this, gvlid, moduleName, result); } else { @@ -188,7 +190,7 @@ export function deviceAccessHook(fn, gvlid, moduleName, result) { result.valid = true; fn.call(this, gvlid, moduleName, result); } else { - curModule && logWarn(`TCF2 denied device access for ${curModule}`); + curModule && utils.logWarn(`TCF2 denied device access for ${curModule}`); result.valid = false; storageBlocked.push(curModule); fn.call(this, gvlid, moduleName, result); @@ -220,7 +222,7 @@ export function userSyncHook(fn, ...args) { if (isAllowed) { fn.call(this, ...args); } else { - logWarn(`User sync not allowed for ${curBidder}`); + utils.logWarn(`User sync not allowed for ${curBidder}`); storageBlocked.push(curBidder); } } else { @@ -248,7 +250,7 @@ export function userIdHook(fn, submodules, consentData) { if (isAllowed) { return submodule; } else { - logWarn(`User denied permission to fetch user id for ${moduleName} User id module`); + utils.logWarn(`User denied permission to fetch user id for ${moduleName} User id module`); storageBlocked.push(moduleName); } return undefined; @@ -280,7 +282,7 @@ export function makeBidRequestsHook(fn, adUnits, ...args) { if (includes(biddersBlocked, currBidder)) return false; const isAllowed = !!validateRules(purpose2Rule, consentData, currBidder, gvlId); if (!isAllowed) { - logWarn(`TCF2 blocked auction for ${currBidder}`); + utils.logWarn(`TCF2 blocked auction for ${currBidder}`); biddersBlocked.push(currBidder); } return isAllowed; @@ -306,7 +308,7 @@ export function enableAnalyticsHook(fn, config) { const consentData = gdprDataHandler.getConsentData(); if (consentData && consentData.gdprApplies) { if (consentData.apiVersion === 2) { - if (!isArray(config)) { + if (!utils.isArray(config)) { config = [config] } config = config.filter(conf => { @@ -315,7 +317,7 @@ export function enableAnalyticsHook(fn, config) { const isAllowed = !!validateRules(purpose7Rule, consentData, analyticsAdapterCode, gvlid); if (!isAllowed) { analyticsBlocked.push(analyticsAdapterCode); - logWarn(`TCF2 blocked analytics adapter ${conf.provider}`); + utils.logWarn(`TCF2 blocked analytics adapter ${conf.provider}`); } return isAllowed; }); @@ -360,9 +362,9 @@ const hasPurpose7 = (rule) => { return rule.purpose === TCF2.purpose7.name } * @param {Object} config - GDPR enforcement config object */ export function setEnforcementConfig(config) { - const rules = deepAccess(config, 'gdpr.rules'); + const rules = utils.deepAccess(config, 'gdpr.rules'); if (!rules) { - logWarn('TCF2: enforcing P1 and P2 by default'); + utils.logWarn('TCF2: enforcing P1 and P2 by default'); enforcementRules = DEFAULT_RULES; } else { enforcementRules = rules; diff --git a/modules/getintentBidAdapter.js b/modules/getintentBidAdapter.js index 98659cc25e2..9127bc4be6e 100644 --- a/modules/getintentBidAdapter.js +++ b/modules/getintentBidAdapter.js @@ -1,5 +1,6 @@ -import { getBidIdParameter, isFn, isInteger } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { isInteger } from '../src/utils.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'getintent'; const IS_NET_REVENUE = true; @@ -123,7 +124,7 @@ function buildGiBidRequest(bidRequest) { giBidRequest.size = produceSize(bidRequest.sizes); } - const currency = getBidIdParameter(CURRENCY_PARAM, bidRequest.params); + const currency = utils.getBidIdParameter(CURRENCY_PARAM, bidRequest.params); const floorInfo = getBidFloor(bidRequest, currency); if (floorInfo.floor) { giBidRequest[FLOOR_PARAM] = floorInfo.floor; @@ -142,7 +143,7 @@ function buildGiBidRequest(bidRequest) { function getBidFloor(bidRequest, currency) { let floorInfo = {}; - if (isFn(bidRequest.getFloor)) { + if (utils.isFn(bidRequest.getFloor)) { floorInfo = bidRequest.getFloor({ currency: currency || DEFAULT_CURRENCY, mediaType: bidRequest.mediaType, diff --git a/modules/gjirafaBidAdapter.js b/modules/gjirafaBidAdapter.js index 48b2cd43c3b..df33369d6ad 100644 --- a/modules/gjirafaBidAdapter.js +++ b/modules/gjirafaBidAdapter.js @@ -1,15 +1,10 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { getStorageManager } from '../src/storageManager.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; const BIDDER_CODE = 'gjirafa'; const ENDPOINT_URL = 'https://central.gjirafa.com/bid'; const DIMENSION_SEPARATOR = 'x'; const SIZE_SEPARATOR = ';'; -const BISKO_ID = 'biskoId'; -const STORAGE_ID = 'bisko-sid'; -const SEGMENTS = 'biskoSegments'; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); export const spec = { code: BIDDER_CODE, @@ -30,12 +25,9 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function (validBidRequests, bidderRequest) { - const storageId = storage.localStorageIsEnabled() ? storage.getDataFromLocalStorage(STORAGE_ID) || '' : ''; - const biskoId = storage.localStorageIsEnabled() ? storage.getDataFromLocalStorage(BISKO_ID) || '' : ''; - const segments = storage.localStorageIsEnabled() ? JSON.parse(storage.getDataFromLocalStorage(SEGMENTS)) || [] : []; - let propertyId = ''; let pageViewGuid = ''; + let storageId = ''; let bidderRequestId = ''; let url = ''; let contents = []; @@ -44,6 +36,7 @@ export const spec = { let placements = validBidRequests.map(bidRequest => { if (!propertyId) { propertyId = bidRequest.params.propertyId; } if (!pageViewGuid && bidRequest.params) { pageViewGuid = bidRequest.params.pageViewGuid || ''; } + if (!storageId && bidRequest.params) { storageId = bidRequest.params.storageId || ''; } if (!bidderRequestId) { bidderRequestId = bidRequest.bidderRequestId; } if (!url && bidderRequest) { url = bidderRequest.refererInfo.referer; } if (!contents.length && bidRequest.params.contents && bidRequest.params.contents.length) { contents = bidRequest.params.contents; } @@ -67,8 +60,6 @@ export const spec = { propertyId: propertyId, pageViewGuid: pageViewGuid, storageId: storageId, - biskoId: biskoId, - segments: segments, url: url, requestid: bidderRequestId, placements: placements, diff --git a/modules/glimpseBidAdapter.js b/modules/glimpseBidAdapter.js index 35aaf56c604..9ef46f62f1d 100644 --- a/modules/glimpseBidAdapter.js +++ b/modules/glimpseBidAdapter.js @@ -1,201 +1,69 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { config } from '../src/config.js'; import { BANNER } from '../src/mediaTypes.js'; -import { getStorageManager } from '../src/storageManager.js'; -import { - isArray, - isEmpty, - isEmptyStr, - isStr, - isPlainObject, -} from '../src/utils.js'; -const GVLID = 1012; const BIDDER_CODE = 'glimpse'; -const storageManager = getStorageManager({ - gvlid: GVLID, - bidderCode: BIDDER_CODE, -}); -const ENDPOINT = 'https://market.glimpsevault.io/public/v1/prebid'; -const LOCAL_STORAGE_KEY = { - vault: { - jwt: 'gp_vault_jwt', - }, -}; + +function transformEachBidResponse(glimpseBid) { + const bid = glimpseBid; + bid.meta = { advertiserDomains: [] }; + + if (glimpseBid.adomain) { + bid.meta.advertiserDomains = glimpseBid.adomain; + } + + return bid; +} export const spec = { - gvlid: GVLID, code: BIDDER_CODE, + url: 'https://api.glimpseprotocol.io/cloud/v1/vault/prebid', supportedMediaTypes: [BANNER], - /** - * Determines if the bid request is valid - * @param bid {BidRequest} The bid to validate - * @return {boolean} - */ isBidRequestValid: (bid) => { - const pid = bid?.params?.pid; - return isStr(pid) && !isEmptyStr(pid); + try { + const { placementId } = bid.params; + return typeof placementId === 'string' && placementId.length > 0; + } catch (error) { + return false; + } }, - /** - * Builds the http request - * @param validBidRequests {BidRequest[]} - * @param bidderRequest {BidderRequest} - * @returns {ServerRequest} - */ buildRequests: (validBidRequests, bidderRequest) => { - const url = buildQuery(bidderRequest); - const auth = getVaultJwt(); - const referer = getReferer(bidderRequest); - const imp = validBidRequests.map(processBidRequest); - const fpd = getFirstPartyData(); + const { url, code: bidderCode } = spec; + + const bids = validBidRequests.map((request) => { + delete request.mediaTypes; + return request; + }); + + const sdk = { + source: 'pbjs', + version: '$prebid.version$', + }; - const data = { - auth, - data: { - referer, - imp, - fpd, - }, + const payload = { + ...bidderRequest, + bidderCode, + bids, + sdk, }; return { method: 'POST', url, - data: JSON.stringify(data), - options: {}, + data: JSON.stringify(payload), }; }, - /** - * Parse http response - * @param response {ServerResponse} - * @returns {Bid[]} - */ - interpretResponse: (response) => { - if (isValidResponse(response)) { - const { auth, data } = response.body; - setVaultJwt(auth); - const bids = data.bids.map(processBidResponse); - return bids; - } - return []; + interpretResponse: (serverResponse, _) => { + let bids = []; + try { + const { body } = serverResponse; + bids = body.map(transformEachBidResponse); + } catch (error) {} + + return bids; }, }; -function setVaultJwt(auth) { - storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.vault.jwt, auth); -} - -function getVaultJwt() { - return ( - storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.vault.jwt) || '' - ); -} - -function getReferer(bidderRequest) { - return bidderRequest?.refererInfo?.referer || ''; -} - -function buildQuery(bidderRequest) { - let url = appendQueryParam(ENDPOINT, 'ver', '$prebid.version$'); - - const timeout = config.getConfig('bidderTimeout'); - url = appendQueryParam(url, 'tmax', timeout); - - if (gdprApplies(bidderRequest)) { - const consentString = bidderRequest.gdprConsent.consentString; - url = appendQueryParam(url, 'gdpr', consentString); - } - - if (ccpaApplies(bidderRequest)) { - url = appendQueryParam(url, 'ccpa', bidderRequest.uspConsent); - } - - return url; -} - -function appendQueryParam(url, key, value) { - if (!value) { - return url; - } - const prefix = url.includes('?') ? '&' : '?'; - return `${url}${prefix}${key}=${encodeURIComponent(value)}`; -} - -function gdprApplies(bidderRequest) { - return Boolean(bidderRequest?.gdprConsent?.gdprApplies); -} - -function ccpaApplies(bidderRequest) { - return ( - isStr(bidderRequest.uspConsent) && - !isEmptyStr(bidderRequest.uspConsent) && - bidderRequest.uspConsent?.substr(1, 3) !== '---' - ); -} - -function processBidRequest(bid) { - const sizes = normalizeSizes(bid.sizes); - - return { - bid: bid.bidId, - pid: bid.params.pid, - sizes, - }; -} - -function normalizeSizes(sizes) { - const isSingleSize = - isArray(sizes) && - sizes.length === 2 && - !isArray(sizes[0]) && - !isArray(sizes[1]); - - if (isSingleSize) { - return [sizes]; - } - - return sizes; -} - -function getFirstPartyData() { - let fpd = config.getConfig('ortb2') || {}; - optimizeObject(fpd); - return fpd; -} - -function optimizeObject(obj) { - if (!isPlainObject(obj)) { - return; - } - for (const [key, value] of Object.entries(obj)) { - optimizeObject(value); - // only delete empty object, array, or string - if ( - (isPlainObject(value) || isArray(value) || isStr(value)) && - isEmpty(value) - ) { - delete obj[key]; - } - } -} - -function isValidResponse(bidResponse) { - const auth = bidResponse?.body?.auth; - const bids = bidResponse?.body?.data?.bids; - return isStr(auth) && isArray(bids) && !isEmpty(bids); -} - -function processBidResponse(bid) { - const meta = bid.meta || {}; - meta.advertiserDomains = bid.meta?.advertiserDomains || []; - - return { - ...bid, - meta, - }; -} - registerBidder(spec); diff --git a/modules/glimpseBidAdapter.md b/modules/glimpseBidAdapter.md index e82c5d8f32e..024cc9ebfa7 100644 --- a/modules/glimpseBidAdapter.md +++ b/modules/glimpseBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Glimpse Protocol Bid Adapter Module Type: Bidder Adapter -Maintainer: publisher@glimpseprotocol.io +Maintainer: hello@glimpseprotocol.io ``` # Description @@ -11,12 +11,12 @@ Maintainer: publisher@glimpseprotocol.io This module connects publishers to Glimpse Protocol's demand sources via Prebid.js. Our innovative marketplace protects consumer privacy while allowing precise targeting. It is compliant with GDPR, DPA and CCPA. -The Glimpse Adapter supports banner formats. +This adapter supports Banner. # Test Parameters ```javascript -const adUnits = [ +var adUnits = [ { code: 'banner-div-a', mediaTypes: { @@ -28,7 +28,71 @@ const adUnits = [ { bidder: 'glimpse', params: { - pid: 'e53a7f564f8f44cc913b', + placementId: 'glimpse-demo-300x250', + }, + }, + ], + }, + { + code: 'banner-div-b', + mediaTypes: { + banner: { + sizes: [[320, 50]], + }, + }, + bids: [ + { + bidder: 'glimpse', + params: { + placementId: 'glimpse-demo-320x50', + }, + }, + ], + }, + { + code: 'banner-div-c', + mediaTypes: { + banner: { + sizes: [[970, 250]], + }, + }, + bids: [ + { + bidder: 'glimpse', + params: { + placementId: 'glimpse-demo-970x250', + }, + }, + ], + }, + { + code: 'banner-div-d', + mediaTypes: { + banner: { + sizes: [[728, 90]], + }, + }, + bids: [ + { + bidder: 'glimpse', + params: { + placementId: 'glimpse-demo-728x90', + }, + }, + ], + }, + { + code: 'banner-div-e', + mediaTypes: { + banner: { + sizes: [[300, 600]], + }, + }, + bids: [ + { + bidder: 'glimpse', + params: { + placementId: 'glimpse-demo-300x600', }, }, ], diff --git a/modules/glomexBidAdapter.js b/modules/glomexBidAdapter.js index 5cabd2515a9..617a1a3d721 100644 --- a/modules/glomexBidAdapter.js +++ b/modules/glomexBidAdapter.js @@ -1,6 +1,6 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {find} from '../src/polyfill.js'; -import {BANNER} from '../src/mediaTypes.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js' +import find from 'core-js-pure/features/array/find.js' +import { BANNER } from '../src/mediaTypes.js' const ENDPOINT = 'https://prebid.mes.glomex.cloud/request-bid' const BIDDER_CODE = 'glomex' diff --git a/modules/gmosspBidAdapter.js b/modules/gmosspBidAdapter.js index 087f74906fb..2b9bd6db034 100644 --- a/modules/gmosspBidAdapter.js +++ b/modules/gmosspBidAdapter.js @@ -1,9 +1,12 @@ -import { deepAccess, getDNT, getBidIdParameter, tryAppendQueryString, isEmpty, createTrackPixelHtml, logError, deepSetValue, getWindowTop, getWindowLocation } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { BANNER } from '../src/mediaTypes.js'; +import { getStorageManager } from '../src/storageManager.js'; + const BIDDER_CODE = 'gmossp'; const ENDPOINT = 'https://sp.gmossp-sp.jp/hb/prebid/query.ad'; +const storage = getStorageManager(); export const spec = { code: BIDDER_CODE, @@ -30,7 +33,8 @@ export const spec = { const urlInfo = getUrlInfo(bidderRequest.refererInfo); const cur = getCurrencyType(); - const dnt = getDNT() ? '1' : '0'; + const dnt = utils.getDNT() ? '1' : '0'; + const imuid = storage.getCookie('_im_uid.1000283') || ''; for (let i = 0; i < validBidRequests.length; i++) { let queryString = ''; @@ -38,24 +42,18 @@ export const spec = { const request = validBidRequests[i]; const tid = request.transactionId; const bid = request.bidId; - const imuid = deepAccess(request, 'userId.imuid'); - const sharedId = deepAccess(request, 'userId.pubcid'); - const idlEnv = deepAccess(request, 'userId.idl_env'); const ver = '$prebid.version$'; - const sid = getBidIdParameter('sid', request.params); - - queryString = tryAppendQueryString(queryString, 'tid', tid); - queryString = tryAppendQueryString(queryString, 'bid', bid); - queryString = tryAppendQueryString(queryString, 'ver', ver); - queryString = tryAppendQueryString(queryString, 'sid', sid); - queryString = tryAppendQueryString(queryString, 'im_uid', imuid); - queryString = tryAppendQueryString(queryString, 'shared_id', sharedId); - queryString = tryAppendQueryString(queryString, 'idl_env', idlEnv); - queryString = tryAppendQueryString(queryString, 'url', urlInfo.url); - queryString = tryAppendQueryString(queryString, 'meta_url', urlInfo.canonicalLink); - queryString = tryAppendQueryString(queryString, 'ref', urlInfo.ref); - queryString = tryAppendQueryString(queryString, 'cur', cur); - queryString = tryAppendQueryString(queryString, 'dnt', dnt); + const sid = utils.getBidIdParameter('sid', request.params); + + queryString = utils.tryAppendQueryString(queryString, 'tid', tid); + queryString = utils.tryAppendQueryString(queryString, 'bid', bid); + queryString = utils.tryAppendQueryString(queryString, 'ver', ver); + queryString = utils.tryAppendQueryString(queryString, 'sid', sid); + queryString = utils.tryAppendQueryString(queryString, 'im_uid', imuid); + queryString = utils.tryAppendQueryString(queryString, 'url', urlInfo.url); + queryString = utils.tryAppendQueryString(queryString, 'ref', urlInfo.ref); + queryString = utils.tryAppendQueryString(queryString, 'cur', cur); + queryString = utils.tryAppendQueryString(queryString, 'dnt', dnt); bidRequests.push({ method: 'GET', @@ -75,17 +73,17 @@ export const spec = { interpretResponse: function (bidderResponse, requests) { const res = bidderResponse.body; - if (isEmpty(res)) { + if (utils.isEmpty(res)) { return []; } try { res.imps.forEach(impTracker => { - const tracker = createTrackPixelHtml(impTracker); + const tracker = utils.createTrackPixelHtml(impTracker); res.ad += tracker; }); } catch (error) { - logError('Error appending tracking pixel', error); + utils.logError('Error appending tracking pixel', error); } const bid = { @@ -101,7 +99,7 @@ export const spec = { }; if (res.adomains) { - deepSetValue(bid, 'meta.advertiserDomains', Array.isArray(res.adomains) ? res.adomains : [res.adomains]); + utils.deepSetValue(bid, 'meta.advertiserDomains', Array.isArray(res.adomains) ? res.adomains : [res.adomains]); } return [bid]; @@ -114,7 +112,7 @@ export const spec = { * @param {ServerResponse[]} serverResponses List of server's responses. * @return {UserSync[]} The user syncs which should be dropped. */ - getUserSyncs: function (syncOptions, serverResponses) { + getUserSyncs: function(syncOptions, serverResponses) { const syncs = []; if (!serverResponses.length) { return syncs; @@ -143,47 +141,27 @@ function getCurrencyType() { } function getUrlInfo(refererInfo) { - let canonicalLink = refererInfo.canonicalUrl; - - if (!canonicalLink) { - let metaElements = getMetaElements(); - for (let i = 0; i < metaElements.length && !canonicalLink; i++) { - if (metaElements[i].getAttribute('property') == 'og:url') { - canonicalLink = metaElements[i].content; - } - } - } - return { url: getUrl(refererInfo), - canonicalLink: canonicalLink, ref: getReferrer(), }; } -function getMetaElements() { - try { - return getWindowTop.document.getElementsByTagName('meta'); - } catch (e) { - return document.getElementsByTagName('meta'); - } -} - function getUrl(refererInfo) { if (refererInfo && refererInfo.referer) { return refererInfo.referer; } try { - return getWindowTop.location.href; + return window.top.location.href; } catch (e) { - return getWindowLocation.href; + return window.location.href; } } function getReferrer() { try { - return getWindowTop.document.referrer; + return window.top.document.referrer; } catch (e) { return document.referrer; } diff --git a/modules/gnetBidAdapter.js b/modules/gnetBidAdapter.js index 274e8db2b50..f45c10195cd 100644 --- a/modules/gnetBidAdapter.js +++ b/modules/gnetBidAdapter.js @@ -1,13 +1,9 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { _each, isEmpty, parseSizesInput } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { BANNER } from '../src/mediaTypes.js'; -import { getStorageManager } from '../src/storageManager.js'; -import {ajax} from '../src/ajax.js'; - -const storage = getStorageManager(); const BIDDER_CODE = 'gnet'; -const ENDPOINT = 'https://service.gnetrtb.com/api'; +const ENDPOINT = 'https://adserver.gnetproject.com/prebid.php'; export const spec = { code: BIDDER_CODE, @@ -20,7 +16,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - return !!(bid.params.websiteId && bid.params.adunitId); + return !!(bid.params.websiteId); }, /** @@ -33,16 +29,15 @@ export const spec = { const bidRequests = []; const referer = bidderRequest.refererInfo.referer; - _each(validBidRequests, (request) => { + utils._each(validBidRequests, (request) => { const data = {}; data.referer = referer; data.adUnitCode = request.adUnitCode; data.bidId = request.bidId; data.transactionId = request.transactionId; - data.gftuid = _getCookie(); - data.sizes = parseSizesInput(request.sizes); + data.sizes = utils.parseSizesInput(request.sizes); data.params = request.params; @@ -50,7 +45,8 @@ export const spec = { bidRequests.push({ method: 'POST', - url: ENDPOINT + '/adrequest', + url: ENDPOINT, + mode: 'no-cors', options: { withCredentials: false, }, @@ -74,13 +70,13 @@ export const spec = { const res = serverResponse && serverResponse.body; - if (isEmpty(res)) { + if (utils.isEmpty(res)) { return []; } if (res.bids) { const bids = []; - _each(res.bids, (bidData) => { + utils._each(res.bids, (bidData) => { const bid = { requestId: bidData.bidId, cpm: bidData.cpm, @@ -103,18 +99,6 @@ export const spec = { return []; }, - - onBidWon: function (bid) { - ajax(ENDPOINT + '/bid-won', null, JSON.stringify(bid), { - method: 'POST', - }); - - return true; - }, }; -function _getCookie() { - return storage.cookiesAreEnabled() ? storage.getCookie('gftuid') : null; -} - registerBidder(spec); diff --git a/modules/gnetBidAdapter.md b/modules/gnetBidAdapter.md index efab45a35b1..447d00d8ff2 100644 --- a/modules/gnetBidAdapter.md +++ b/modules/gnetBidAdapter.md @@ -1,14 +1,14 @@ # Overview ``` -Module Name: Gnet RTB Bidder Adapter +Module Name: Gnet Bidder Adapter Module Type: Bidder Adapter -Maintainer: bruno.bonanho@grumft.com +Maintainer: roberto.wu@grumft.com ``` # Description -Connect to Gnet RTB exchange for bids. +Connect to Gnet Project exchange for bids. # Test Parameters ``` @@ -24,7 +24,7 @@ Connect to Gnet RTB exchange for bids. { bidder: 'gnet', params: { - websiteId: '1', adunitId: '1' + websiteId: '4' } } ] diff --git a/modules/goldbachBidAdapter.js b/modules/goldbachBidAdapter.js deleted file mode 100644 index 46ae3054188..00000000000 --- a/modules/goldbachBidAdapter.js +++ /dev/null @@ -1,1177 +0,0 @@ -import {Renderer} from '../src/Renderer.js'; -import { - chunk, - convertCamelToUnderscore, - convertTypes, - createTrackPixelHtml, - deepAccess, - deepClone, - fill, - getBidRequest, - getMaxValueFromArray, - getMinValueFromArray, - getParameterByName, - isArray, - isArrayOfNums, - isEmpty, - isFn, - isNumber, - isPlainObject, - isStr, - logError, - logInfo, - logMessage, - transformBidderParamKeywords -} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {getIabSubCategory, registerBidder} from '../src/adapters/bidderFactory.js'; -import {ADPOD, BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {auctionManager} from '../src/auctionManager.js'; -import {find, includes} from '../src/polyfill.js'; -import {INSTREAM, OUTSTREAM} from '../src/video.js'; - -const BIDDER_CODE = 'goldbach'; -const URL = 'https://ib.adnxs.com/ut/v3/prebid'; -const PRICING_URL = 'https://templates.da-services.ch/01_universal/burda_prebid/1.0/json/sizeCPMMapping.json'; -const URL_SIMPLE = 'https://ib.adnxs-simple.com/ut/v3/prebid'; -const VIDEO_TARGETING = ['id', 'minduration', 'maxduration', - 'skippable', 'playback_method', 'frameworks', 'context', 'skipoffset']; -const VIDEO_RTB_TARGETING = ['minduration', 'maxduration', 'skip', 'skipafter', 'playbackmethod', 'api']; -const USER_PARAMS = ['age', 'externalUid', 'segments', 'gender', 'dnt', 'language']; -const APP_DEVICE_PARAMS = ['geo', 'device_id']; // appid is collected separately -const DEBUG_PARAMS = ['enabled', 'dongle', 'member_id', 'debug_timeout']; -const DEFAULT_PRICE_MAPPING = { - '0x0': 2.5, - '300x600': 5, - '800x250': 6, - '350x600': 6 -}; -let PRICE_MAPPING; -const VIDEO_MAPPING = { - playback_method: { - 'unknown': 0, - 'auto_play_sound_on': 1, - 'auto_play_sound_off': 2, - 'click_to_play': 3, - 'mouse_over': 4, - 'auto_play_sound_unknown': 5 - }, - context: { - 'unknown': 0, - 'pre_roll': 1, - 'mid_roll': 2, - 'post_roll': 3, - 'outstream': 4, - 'in-banner': 5 - } -}; -const NATIVE_MAPPING = { - body: 'description', - body2: 'desc2', - cta: 'ctatext', - image: { - serverName: 'main_image', - requiredParams: { required: true } - }, - icon: { - serverName: 'icon', - requiredParams: { required: true } - }, - sponsoredBy: 'sponsored_by', - privacyLink: 'privacy_link', - salePrice: 'saleprice', - displayUrl: 'displayurl' -}; -const SOURCE = 'pbjs'; -const MAX_IMPS_PER_REQUEST = 15; -const mappingFileUrl = 'https://acdn.adnxs-simple.com/prebid/appnexus-mapping/mappings.json'; -const SCRIPT_TAG_START = ' { - if (Array.isArray(bid.params.placementId)) { - const ids = bid.params.placementId; - for (let i = 0; i < ids.length; i++) { - const newBid = Object.assign({}, bid, {params: {placementId: ids[i]}}); - localBidRequests.push(newBid) - } - } else { - localBidRequests.push(bid); - } - }); - const tags = localBidRequests.map(bidToTag); - const userObjBid = find(bidRequests, hasUserInfo); - let userObj = {}; - if (config.getConfig('coppa') === true) { - userObj = { 'coppa': true }; - } - if (userObjBid) { - Object.keys(userObjBid.params.user) - .filter(param => includes(USER_PARAMS, param)) - .forEach((param) => { - let uparam = convertCamelToUnderscore(param); - if (param === 'segments' && isArray(userObjBid.params.user[param])) { - let segs = []; - userObjBid.params.user[param].forEach(val => { - if (isNumber(val)) { - segs.push({'id': val}); - } else if (isPlainObject(val)) { - segs.push(val); - } - }); - userObj[uparam] = segs; - } else if (param !== 'segments') { - userObj[uparam] = userObjBid.params.user[param]; - } - }); - } - - const appDeviceObjBid = find(bidRequests, hasAppDeviceInfo); - let appDeviceObj; - if (appDeviceObjBid && appDeviceObjBid.params && appDeviceObjBid.params.app) { - appDeviceObj = {}; - Object.keys(appDeviceObjBid.params.app) - .filter(param => includes(APP_DEVICE_PARAMS, param)) - .forEach(param => appDeviceObj[param] = appDeviceObjBid.params.app[param]); - } - - const appIdObjBid = find(bidRequests, hasAppId); - let appIdObj; - if (appIdObjBid && appIdObjBid.params && appDeviceObjBid.params.app && appDeviceObjBid.params.app.id) { - appIdObj = { - appid: appIdObjBid.params.app.id - }; - } - - let debugObj = {}; - let debugObjParams = {}; - const debugBidRequest = find(bidRequests, hasDebug); - if (debugBidRequest && debugBidRequest.debug) { - debugObj = debugBidRequest.debug; - } - - if (debugObj && debugObj.enabled) { - Object.keys(debugObj) - .filter(param => includes(DEBUG_PARAMS, param)) - .forEach(param => { - debugObjParams[param] = debugObj[param]; - }); - } - - const memberIdBid = find(bidRequests, hasMemberId); - const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; - const schain = bidRequests[0].schain; - const omidSupport = find(bidRequests, hasOmidSupport); - - const payload = { - tags: [...tags], - user: userObj, - sdk: { - source: SOURCE, - version: '$prebid.version$' - }, - schain: schain - }; - - if (omidSupport) { - payload['iab_support'] = { - omidpn: 'Appnexus', - omidpv: '$prebid.version$' - } - } - - if (member > 0) { - payload.member_id = member; - } - - if (appDeviceObjBid) { - payload.device = appDeviceObj - } - if (appIdObjBid) { - payload.app = appIdObj; - } - - if (config.getConfig('adpod.brandCategoryExclusion')) { - payload.brand_category_uniqueness = true; - } - - if (debugObjParams.enabled) { - payload.debug = debugObjParams; - logInfo('Debug Auction Settings:\n\n' + JSON.stringify(debugObjParams, null, 4)); - } - - if (bidderRequest && bidderRequest.gdprConsent) { - // note - objects for impbus use underscore instead of camelCase - payload.gdpr_consent = { - consent_string: bidderRequest.gdprConsent.consentString, - consent_required: bidderRequest.gdprConsent.gdprApplies - }; - - if (bidderRequest.gdprConsent.addtlConsent && bidderRequest.gdprConsent.addtlConsent.indexOf('~') !== -1) { - let ac = bidderRequest.gdprConsent.addtlConsent; - // pull only the ids from the string (after the ~) and convert them to an array of ints - let acStr = ac.substring(ac.indexOf('~') + 1); - payload.gdpr_consent.addtl_consent = acStr.split('.').map(id => parseInt(id, 10)); - } - } - - if (bidderRequest && bidderRequest.uspConsent) { - payload.us_privacy = bidderRequest.uspConsent - } - - if (bidderRequest && bidderRequest.refererInfo) { - let refererinfo = { - rd_ref: encodeURIComponent(bidderRequest.refererInfo.referer), - rd_top: bidderRequest.refererInfo.reachedTop, - rd_ifs: bidderRequest.refererInfo.numIframes, - rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') - } - payload.referrer_detection = refererinfo; - } - - const hasAdPodBid = find(bidRequests, hasAdPod); - if (hasAdPodBid) { - bidRequests.filter(hasAdPod).forEach(adPodBid => { - const adPodTags = createAdPodRequest(tags, adPodBid); - // don't need the original adpod placement because it's in adPodTags - const nonPodTags = payload.tags.filter(tag => tag.uuid !== adPodBid.bidId); - payload.tags = [...nonPodTags, ...adPodTags]; - }); - } - - if (bidRequests[0].userId) { - let eids = []; - - addUserId(eids, deepAccess(bidRequests[0], `userId.flocId.id`), 'chrome.com', null); - addUserId(eids, deepAccess(bidRequests[0], `userId.criteoId`), 'criteo.com', null); - addUserId(eids, deepAccess(bidRequests[0], `userId.netId`), 'netid.de', null); - addUserId(eids, deepAccess(bidRequests[0], `userId.idl_env`), 'liveramp.com', null); - addUserId(eids, deepAccess(bidRequests[0], `userId.tdid`), 'adserver.org', 'TDID'); - addUserId(eids, deepAccess(bidRequests[0], `userId.uid2.id`), 'uidapi.com', 'UID2'); - - if (eids.length) { - payload.eids = eids; - } - } - - if (tags[0].publisher_id) { - payload.publisher_id = tags[0].publisher_id; - } - - const request = formatRequest(payload, bidderRequest); - // add pricing endpoint - return [{method: 'GET', url: PRICING_URL, options: {withCredentials: false}}, request]; - }, - - parseAndMapCpm: function(serverResponse) { - const responseBody = serverResponse.body; - if (Array.isArray(responseBody) && responseBody.length) { - let localData = {}; - responseBody.forEach(cpmPerSize => { - Object.keys(cpmPerSize).forEach(size => { - let obj = {}; - obj[size] = cpmPerSize[size]; - localData = Object.assign({}, localData, obj) - }) - }) - PRICE_MAPPING = localData; - return null; - } - - if (responseBody.version) { - const localPriceMapping = PRICE_MAPPING || DEFAULT_PRICE_MAPPING; - if (responseBody.tags && Array.isArray(responseBody.tags) && responseBody.tags.length) { - responseBody.tags.forEach((tag) => { - if (tag.ads && Array.isArray(tag.ads) && tag.ads.length) { - tag.ads.forEach(ad => { - if (ad.ad_type === 'banner') { - const size = `${ad.rtb.banner.width}x${ad.rtb.banner.height}`; - if (localPriceMapping[size]) { - ad.cpm = localPriceMapping[size]; - } else { - ad.cpm = localPriceMapping['0x0']; - } - } - }) - } - }); - } - } - return responseBody; - }, - - /** - * Unpack the response from the server into a list of bids. - * - * @param {*} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function (serverResponse, { bidderRequest }) { - serverResponse = this.parseAndMapCpm(serverResponse); - if (!serverResponse) return []; - const bids = []; - if (serverResponse.error) { - let errorMessage = `in response for ${bidderRequest.bidderCode} adapter : ${serverResponse.error}`; - logError(errorMessage); - return bids; - } - - if (serverResponse.tags) { - serverResponse.tags.forEach(serverBid => { - const rtbBid = getRtbBid(serverBid); - if (rtbBid) { - if (rtbBid.cpm !== 0 && includes(this.supportedMediaTypes, rtbBid.ad_type)) { - const bid = newBid(serverBid, rtbBid, bidderRequest); - bid.mediaType = parseMediaType(rtbBid); - bids.push(bid); - } - } - }); - } - - if (serverResponse.debug && serverResponse.debug.debug_info) { - let debugHeader = 'AppNexus Debug Auction for Prebid\n\n' - let debugText = debugHeader + serverResponse.debug.debug_info - debugText = debugText - .replace(/(|)/gm, '\t') // Tables - .replace(/(<\/td>|<\/th>)/gm, '\n') // Tables - .replace(/^
/gm, '') // Remove leading
- .replace(/(
\n|
)/gm, '\n') //
- .replace(/

(.*)<\/h1>/gm, '\n\n===== $1 =====\n\n') // Header H1 - .replace(/(.*)<\/h[2-6]>/gm, '\n\n*** $1 ***\n\n') // Headers - .replace(/(<([^>]+)>)/igm, ''); // Remove any other tags - logMessage(debugText); - } - - return bids; - }, - - /** - * @typedef {Object} mappingFileInfo - * @property {string} url mapping file json url - * @property {number} refreshInDays prebid stores mapping data in localstorage so you can return in how many days you want to update value stored in localstorage. - * @property {string} localStorageKey unique key to store your mapping json in localstorage - */ - - /** - * Returns mapping file info. This info will be used by bidderFactory to preload mapping file and store data in local storage - * @returns {mappingFileInfo} - */ - getMappingFileInfo: function () { - return { - url: mappingFileUrl, - refreshInDays: 2 - } - }, - - getUserSyncs: function (syncOptions, responses, gdprConsent) { - if (syncOptions.iframeEnabled && hasPurpose1Consent({gdprConsent})) { - return [{ - type: 'iframe', - url: 'https://acdn.adnxs.com/dmp/async_usersync.html' - }]; - } - }, - - transformBidParams: function (params, isOpenRtb) { - params = convertTypes({ - 'member': 'string', - 'invCode': 'string', - 'placementId': 'number', - 'keywords': transformBidderParamKeywords, - 'publisherId': 'number' - }, params); - - if (isOpenRtb) { - params.use_pmt_rule = (typeof params.usePaymentRule === 'boolean') ? params.usePaymentRule : false; - if (params.usePaymentRule) { delete params.usePaymentRule; } - - if (isPopulatedArray(params.keywords)) { - params.keywords.forEach(deleteValues); - } - - Object.keys(params).forEach(paramKey => { - let convertedKey = convertCamelToUnderscore(paramKey); - if (convertedKey !== paramKey) { - params[convertedKey] = params[paramKey]; - delete params[paramKey]; - } - }); - } - - return params; - }, - - /** - * Add element selector to javascript tracker to improve native viewability - * @param {Bid} bid - */ - onBidWon: function (bid) { - if (bid.native) { - reloadViewabilityScriptWithCorrectParameters(bid); - } - } -} - -function isPopulatedArray(arr) { - return !!(isArray(arr) && arr.length > 0); -} - -function deleteValues(keyPairObj) { - if (isPopulatedArray(keyPairObj.value) && keyPairObj.value[0] === '') { - delete keyPairObj.value; - } -} - -function reloadViewabilityScriptWithCorrectParameters(bid) { - let viewJsPayload = getAppnexusViewabilityScriptFromJsTrackers(bid.native.javascriptTrackers); - - if (viewJsPayload) { - let prebidParams = 'pbjs_adid=' + bid.adId + ';pbjs_auc=' + bid.adUnitCode; - - let jsTrackerSrc = getViewabilityScriptUrlFromPayload(viewJsPayload) - - let newJsTrackerSrc = jsTrackerSrc.replace('dom_id=%native_dom_id%', prebidParams); - - // find iframe containing script tag - let frameArray = document.getElementsByTagName('iframe'); - - // boolean var to modify only one script. That way if there are muliple scripts, - // they won't all point to the same creative. - let modifiedAScript = false; - - // first, loop on all ifames - for (let i = 0; i < frameArray.length && !modifiedAScript; i++) { - let currentFrame = frameArray[i]; - try { - // IE-compatible, see https://stackoverflow.com/a/3999191/2112089 - let nestedDoc = currentFrame.contentDocument || currentFrame.contentWindow.document; - - if (nestedDoc) { - // if the doc is present, we look for our jstracker - let scriptArray = nestedDoc.getElementsByTagName('script'); - for (let j = 0; j < scriptArray.length && !modifiedAScript; j++) { - let currentScript = scriptArray[j]; - if (currentScript.getAttribute('data-src') == jsTrackerSrc) { - currentScript.setAttribute('src', newJsTrackerSrc); - currentScript.setAttribute('data-src', ''); - if (currentScript.removeAttribute) { - currentScript.removeAttribute('data-src'); - } - modifiedAScript = true; - } - } - } - } catch (exception) { - // trying to access a cross-domain iframe raises a SecurityError - // this is expected and ignored - if (!(exception instanceof DOMException && exception.name === 'SecurityError')) { - // all other cases are raised again to be treated by the calling function - throw exception; - } - } - } - } -} - -function strIsAppnexusViewabilityScript(str) { - let regexMatchUrlStart = str.match(VIEWABILITY_URL_START); - let viewUrlStartInStr = regexMatchUrlStart != null && regexMatchUrlStart.length >= 1; - - let regexMatchFileName = str.match(VIEWABILITY_FILE_NAME); - let fileNameInStr = regexMatchFileName != null && regexMatchFileName.length >= 1; - - return str.startsWith(SCRIPT_TAG_START) && fileNameInStr && viewUrlStartInStr; -} - -function getAppnexusViewabilityScriptFromJsTrackers(jsTrackerArray) { - let viewJsPayload; - if (isStr(jsTrackerArray) && strIsAppnexusViewabilityScript(jsTrackerArray)) { - viewJsPayload = jsTrackerArray; - } else if (isArray(jsTrackerArray)) { - for (let i = 0; i < jsTrackerArray.length; i++) { - let currentJsTracker = jsTrackerArray[i]; - if (strIsAppnexusViewabilityScript(currentJsTracker)) { - viewJsPayload = currentJsTracker; - } - } - } - return viewJsPayload; -} - -function getViewabilityScriptUrlFromPayload(viewJsPayload) { - // extracting the content of the src attribute - // -> substring between src=" and " - let indexOfFirstQuote = viewJsPayload.indexOf('src="') + 5; // offset of 5: the length of 'src=' + 1 - let indexOfSecondQuote = viewJsPayload.indexOf('"', indexOfFirstQuote); - let jsTrackerSrc = viewJsPayload.substring(indexOfFirstQuote, indexOfSecondQuote); - return jsTrackerSrc; -} - -function hasPurpose1Consent(bidderRequest) { - let result = true; - if (bidderRequest && bidderRequest.gdprConsent) { - if (bidderRequest.gdprConsent.gdprApplies && bidderRequest.gdprConsent.apiVersion === 2) { - result = !!(deepAccess(bidderRequest.gdprConsent, 'vendorData.purpose.consents.1') === true); - } - } - return result; -} - -function formatRequest(payload, bidderRequest) { - let request = []; - let options = { - withCredentials: true - }; - - let endpointUrl = URL; - - if (!hasPurpose1Consent(bidderRequest)) { - endpointUrl = URL_SIMPLE; - } - - if (getParameterByName('apn_test').toUpperCase() === 'TRUE' || config.getConfig('apn_test') === true) { - options.customHeaders = { - 'X-Is-Test': 1 - } - } - - if (payload.tags.length > MAX_IMPS_PER_REQUEST) { - const clonedPayload = deepClone(payload); - - chunk(payload.tags, MAX_IMPS_PER_REQUEST).forEach(tags => { - clonedPayload.tags = tags; - const payloadString = JSON.stringify(clonedPayload); - request.push({ - method: 'POST', - url: endpointUrl, - data: payloadString, - bidderRequest, - options - }); - }); - } else { - const payloadString = JSON.stringify(payload); - request = { - method: 'POST', - url: endpointUrl, - data: payloadString, - bidderRequest, - options - }; - } - - return request; -} - -function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { - const renderer = Renderer.install({ - id: rtbBid.renderer_id, - url: rtbBid.renderer_url, - config: rendererOptions, - loaded: false, - adUnitCode - }); - - try { - renderer.setRender(outstreamRender); - } catch (err) { - logError('Prebid Error calling setRender on renderer', err); - } - - renderer.setEventHandlers({ - impression: () => logMessage('Outstream video impression event'), - loaded: () => logMessage('Outstream video loaded event'), - ended: () => { - logMessage('Outstream renderer video event'); - document.querySelector(`#${adUnitCode}`).style.display = 'none'; - } - }); - return renderer; -} - -/** - * Unpack the Server's Bid into a Prebid-compatible one. - * @param serverBid - * @param rtbBid - * @param bidderRequest - * @return Bid - */ -function newBid(serverBid, rtbBid, bidderRequest) { - const bidRequest = getBidRequest(serverBid.uuid, [bidderRequest]); - const bid = { - requestId: serverBid.uuid, - cpm: rtbBid.cpm, - creativeId: rtbBid.creative_id, - dealId: rtbBid.deal_id, - currency: 'USD', - netRevenue: true, - ttl: 300, - adUnitCode: bidRequest.adUnitCode, - appnexus: { - buyerMemberId: rtbBid.buyer_member_id, - dealPriority: rtbBid.deal_priority, - dealCode: rtbBid.deal_code - } - }; - - // WE DON'T FULLY SUPPORT THIS ATM - future spot for adomain code; creating a stub for 5.0 compliance - if (rtbBid.adomain) { - bid.meta = Object.assign({}, bid.meta, { advertiserDomains: [] }); - } - - if (rtbBid.advertiser_id) { - bid.meta = Object.assign({}, bid.meta, { advertiserId: rtbBid.advertiser_id }); - } - - if (rtbBid.rtb.video) { - // shared video properties used for all 3 contexts - Object.assign(bid, { - width: rtbBid.rtb.video.player_width, - height: rtbBid.rtb.video.player_height, - vastImpUrl: rtbBid.notify_url, - ttl: 3600 - }); - - const videoContext = deepAccess(bidRequest, 'mediaTypes.video.context'); - switch (videoContext) { - case ADPOD: - const primaryCatId = getIabSubCategory(bidRequest.bidder, rtbBid.brand_category_id); - bid.meta = Object.assign({}, bid.meta, { primaryCatId }); - const dealTier = rtbBid.deal_priority; - bid.video = { - context: ADPOD, - durationSeconds: Math.floor(rtbBid.rtb.video.duration_ms / 1000), - dealTier - }; - bid.vastUrl = rtbBid.rtb.video.asset_url; - break; - case OUTSTREAM: - bid.adResponse = serverBid; - bid.adResponse.ad = bid.adResponse.ads[0]; - bid.adResponse.ad.video = bid.adResponse.ad.rtb.video; - bid.vastXml = rtbBid.rtb.video.content; - - if (rtbBid.renderer_url) { - const videoBid = find(bidderRequest.bids, bid => bid.bidId === serverBid.uuid); - const rendererOptions = deepAccess(videoBid, 'renderer.options'); - bid.renderer = newRenderer(bid.adUnitCode, rtbBid, rendererOptions); - } - break; - case INSTREAM: - bid.vastUrl = rtbBid.notify_url + '&redir=' + encodeURIComponent(rtbBid.rtb.video.asset_url); - break; - } - } else if (rtbBid.rtb[NATIVE]) { - const nativeAd = rtbBid.rtb[NATIVE]; - - // setting up the jsTracker: - // we put it as a data-src attribute so that the tracker isn't called - // until we have the adId (see onBidWon) - let jsTrackerDisarmed = rtbBid.viewability.config.replace('src=', 'data-src='); - - let jsTrackers = nativeAd.javascript_trackers; - - if (jsTrackers == undefined) { - jsTrackers = jsTrackerDisarmed; - } else if (isStr(jsTrackers)) { - jsTrackers = [jsTrackers, jsTrackerDisarmed]; - } else { - jsTrackers.push(jsTrackerDisarmed); - } - - bid[NATIVE] = { - title: nativeAd.title, - body: nativeAd.desc, - body2: nativeAd.desc2, - cta: nativeAd.ctatext, - rating: nativeAd.rating, - sponsoredBy: nativeAd.sponsored, - privacyLink: nativeAd.privacy_link, - address: nativeAd.address, - downloads: nativeAd.downloads, - likes: nativeAd.likes, - phone: nativeAd.phone, - price: nativeAd.price, - salePrice: nativeAd.saleprice, - clickUrl: nativeAd.link.url, - displayUrl: nativeAd.displayurl, - clickTrackers: nativeAd.link.click_trackers, - impressionTrackers: nativeAd.impression_trackers, - javascriptTrackers: jsTrackers - }; - if (nativeAd.main_img) { - bid['native'].image = { - url: nativeAd.main_img.url, - height: nativeAd.main_img.height, - width: nativeAd.main_img.width, - }; - } - if (nativeAd.icon) { - bid['native'].icon = { - url: nativeAd.icon.url, - height: nativeAd.icon.height, - width: nativeAd.icon.width, - }; - } - } else { - Object.assign(bid, { - width: rtbBid.rtb.banner.width, - height: rtbBid.rtb.banner.height, - ad: rtbBid.rtb.banner.content - }); - try { - if (rtbBid.rtb.trackers) { - const url = rtbBid.rtb.trackers[0].impression_urls[0]; - const tracker = createTrackPixelHtml(url); - bid.ad += tracker; - } - } catch (error) { - logError('Error appending tracking pixel', error); - } - } - - return bid; -} - -function bidToTag(bid) { - const tag = {}; - tag.sizes = transformSizes(bid.sizes); - tag.primary_size = tag.sizes[0]; - tag.ad_types = []; - tag.uuid = bid.bidId; - if (bid.params.placementId) { - tag.id = parseInt(bid.params.placementId, 10); - } else { - tag.code = bid.params.invCode; - } - tag.allow_smaller_sizes = bid.params.allowSmallerSizes || false; - tag.use_pmt_rule = bid.params.usePaymentRule || false - tag.prebid = true; - tag.disable_psa = true; - let bidFloor = getBidFloor(bid); - if (bidFloor) { - tag.reserve = bidFloor; - } - if (bid.params.position) { - tag.position = { 'above': 1, 'below': 2 }[bid.params.position] || 0; - } - if (bid.params.trafficSourceCode) { - tag.traffic_source_code = bid.params.trafficSourceCode; - } - if (bid.params.privateSizes) { - tag.private_sizes = transformSizes(bid.params.privateSizes); - } - if (bid.params.supplyType) { - tag.supply_type = bid.params.supplyType; - } - if (bid.params.pubClick) { - tag.pubclick = bid.params.pubClick; - } - if (bid.params.extInvCode) { - tag.ext_inv_code = bid.params.extInvCode; - } - if (bid.params.publisherId) { - tag.publisher_id = parseInt(bid.params.publisherId, 10); - } - if (bid.params.externalImpId) { - tag.external_imp_id = bid.params.externalImpId; - } - if (!isEmpty(bid.params.keywords)) { - let keywords = transformBidderParamKeywords(bid.params.keywords); - - if (keywords.length > 0) { - keywords.forEach(deleteValues); - } - tag.keywords = keywords; - } - - let gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); - if (gpid) { - tag.gpid = gpid; - } - - if (bid.mediaType === NATIVE || deepAccess(bid, `mediaTypes.${NATIVE}`)) { - tag.ad_types.push(NATIVE); - if (tag.sizes.length === 0) { - tag.sizes = transformSizes([1, 1]); - } - - if (bid.nativeParams) { - const nativeRequest = buildNativeRequest(bid.nativeParams); - tag[NATIVE] = { layouts: [nativeRequest] }; - } - } - - const videoMediaType = deepAccess(bid, `mediaTypes.${VIDEO}`); - const context = deepAccess(bid, 'mediaTypes.video.context'); - - if (videoMediaType && context === 'adpod') { - tag.hb_source = 7; - } else { - tag.hb_source = 1; - } - if (bid.mediaType === VIDEO || videoMediaType) { - tag.ad_types.push(VIDEO); - } - - // instream gets vastUrl, outstream gets vastXml - if (bid.mediaType === VIDEO || (videoMediaType && context !== 'outstream')) { - tag.require_asset_url = true; - } - - if (bid.params.video) { - tag.video = {}; - // place any valid video params on the tag - Object.keys(bid.params.video) - .filter(param => includes(VIDEO_TARGETING, param)) - .forEach(param => { - switch (param) { - case 'context': - case 'playback_method': - let type = bid.params.video[param]; - type = (isArray(type)) ? type[0] : type; - tag.video[param] = VIDEO_MAPPING[param][type]; - break; - // Deprecating tags[].video.frameworks in favor of tags[].video_frameworks - case 'frameworks': - break; - default: - tag.video[param] = bid.params.video[param]; - } - }); - - if (bid.params.video.frameworks && isArray(bid.params.video.frameworks)) { - tag['video_frameworks'] = bid.params.video.frameworks; - } - } - - // use IAB ORTB values if the corresponding values weren't already set by bid.params.video - if (videoMediaType) { - tag.video = tag.video || {}; - Object.keys(videoMediaType) - .filter(param => includes(VIDEO_RTB_TARGETING, param)) - .forEach(param => { - switch (param) { - case 'minduration': - case 'maxduration': - if (typeof tag.video[param] !== 'number') tag.video[param] = videoMediaType[param]; - break; - case 'skip': - if (typeof tag.video['skippable'] !== 'boolean') tag.video['skippable'] = (videoMediaType[param] === 1); - break; - case 'skipafter': - if (typeof tag.video['skipoffset'] !== 'number') tag.video['skippoffset'] = videoMediaType[param]; - break; - case 'playbackmethod': - if (typeof tag.video['playback_method'] !== 'number') { - let type = videoMediaType[param]; - type = (isArray(type)) ? type[0] : type; - - // we only support iab's options 1-4 at this time. - if (type >= 1 && type <= 4) { - tag.video['playback_method'] = type; - } - } - break; - case 'api': - if (!tag['video_frameworks'] && isArray(videoMediaType[param])) { - // need to read thru array; remove 6 (we don't support it), swap 4 <> 5 if found (to match our adserver mapping for these specific values) - let apiTmp = videoMediaType[param].map(val => { - let v = (val === 4) ? 5 : (val === 5) ? 4 : val; - - if (v >= 1 && v <= 5) { - return v; - } - }).filter(v => v); - tag['video_frameworks'] = apiTmp; - } - break; - } - }); - } - - if (bid.renderer) { - tag.video = Object.assign({}, tag.video, { custom_renderer_present: true }); - } - - if (bid.params.frameworks && isArray(bid.params.frameworks)) { - tag['banner_frameworks'] = bid.params.frameworks; - } - - let adUnit = find(auctionManager.getAdUnits(), au => bid.transactionId === au.transactionId); - if (adUnit && adUnit.mediaTypes && adUnit.mediaTypes.banner) { - tag.ad_types.push(BANNER); - } - - if (tag.ad_types.length === 0) { - delete tag.ad_types; - } - - return tag; -} - -/* Turn bid request sizes into ut-compatible format */ -function transformSizes(requestSizes) { - let sizes = []; - let sizeObj = {}; - - if (isArray(requestSizes) && requestSizes.length === 2 && - !isArray(requestSizes[0])) { - sizeObj.width = parseInt(requestSizes[0], 10); - sizeObj.height = parseInt(requestSizes[1], 10); - sizes.push(sizeObj); - } else if (typeof requestSizes === 'object') { - for (let i = 0; i < requestSizes.length; i++) { - let size = requestSizes[i]; - sizeObj = {}; - sizeObj.width = parseInt(size[0], 10); - sizeObj.height = parseInt(size[1], 10); - sizes.push(sizeObj); - } - } - - return sizes; -} - -function hasUserInfo(bid) { - return !!bid.params.user; -} - -function hasMemberId(bid) { - return !!parseInt(bid.params.member, 10); -} - -function hasAppDeviceInfo(bid) { - if (bid.params) { - return !!bid.params.app - } -} - -function hasAppId(bid) { - if (bid.params && bid.params.app) { - return !!bid.params.app.id - } - return !!bid.params.app -} - -function hasDebug(bid) { - return !!bid.debug -} - -function hasAdPod(bid) { - return ( - bid.mediaTypes && - bid.mediaTypes.video && - bid.mediaTypes.video.context === ADPOD - ); -} - -function hasOmidSupport(bid) { - let hasOmid = false; - const bidderParams = bid.params; - const videoParams = bid.params.video; - if (bidderParams.frameworks && isArray(bidderParams.frameworks)) { - hasOmid = includes(bid.params.frameworks, 6); - } - if (!hasOmid && videoParams && videoParams.frameworks && isArray(videoParams.frameworks)) { - hasOmid = includes(bid.params.video.frameworks, 6); - } - return hasOmid; -} - -/** - * Expand an adpod placement into a set of request objects according to the - * total adpod duration and the range of duration seconds. Sets minduration/ - * maxduration video property according to requireExactDuration configuration - */ -function createAdPodRequest(tags, adPodBid) { - const { durationRangeSec, requireExactDuration } = adPodBid.mediaTypes.video; - - const numberOfPlacements = getAdPodPlacementNumber(adPodBid.mediaTypes.video); - const maxDuration = getMaxValueFromArray(durationRangeSec); - - const tagToDuplicate = tags.filter(tag => tag.uuid === adPodBid.bidId); - let request = fill(...tagToDuplicate, numberOfPlacements); - - if (requireExactDuration) { - const divider = Math.ceil(numberOfPlacements / durationRangeSec.length); - const chunked = chunk(request, divider); - - // each configured duration is set as min/maxduration for a subset of requests - durationRangeSec.forEach((duration, index) => { - chunked[index].map(tag => { - setVideoProperty(tag, 'minduration', duration); - setVideoProperty(tag, 'maxduration', duration); - }); - }); - } else { - // all maxdurations should be the same - request.map(tag => setVideoProperty(tag, 'maxduration', maxDuration)); - } - - return request; -} - -function getAdPodPlacementNumber(videoParams) { - const { adPodDurationSec, durationRangeSec, requireExactDuration } = videoParams; - const minAllowedDuration = getMinValueFromArray(durationRangeSec); - const numberOfPlacements = Math.floor(adPodDurationSec / minAllowedDuration); - - return requireExactDuration - ? Math.max(numberOfPlacements, durationRangeSec.length) - : numberOfPlacements; -} - -function setVideoProperty(tag, key, value) { - if (isEmpty(tag.video)) { tag.video = {}; } - tag.video[key] = value; -} - -function getRtbBid(tag) { - return tag && tag.ads && tag.ads.length && find(tag.ads, ad => ad.rtb); -} - -function buildNativeRequest(params) { - const request = {}; - - // map standard prebid native asset identifier to /ut parameters - // e.g., tag specifies `body` but /ut only knows `description`. - // mapping may be in form {tag: ''} or - // {tag: {serverName: '', requiredParams: {...}}} - Object.keys(params).forEach(key => { - // check if one of the forms is used, otherwise - // a mapping wasn't specified so pass the key straight through - const requestKey = - (NATIVE_MAPPING[key] && NATIVE_MAPPING[key].serverName) || - NATIVE_MAPPING[key] || - key; - - // required params are always passed on request - const requiredParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].requiredParams; - request[requestKey] = Object.assign({}, requiredParams, params[key]); - - // convert the sizes of image/icon assets to proper format (if needed) - const isImageAsset = !!(requestKey === NATIVE_MAPPING.image.serverName || requestKey === NATIVE_MAPPING.icon.serverName); - if (isImageAsset && request[requestKey].sizes) { - let sizes = request[requestKey].sizes; - if (isArrayOfNums(sizes) || (isArray(sizes) && sizes.length > 0 && sizes.every(sz => isArrayOfNums(sz)))) { - request[requestKey].sizes = transformSizes(request[requestKey].sizes); - } - } - - if (requestKey === NATIVE_MAPPING.privacyLink) { - request.privacy_supported = true; - } - }); - - return request; -} - -/** - * This function hides google div container for outstream bids to remove unwanted space on page. Appnexus renderer creates a new iframe outside of google iframe to render the outstream creative. - * @param {string} elementId element id - */ -function hidedfpContainer(elementId) { - var el = document.getElementById(elementId).querySelectorAll("div[id^='google_ads']"); - if (el[0]) { - el[0].style.setProperty('display', 'none'); - } -} - -function hideSASIframe(elementId) { - try { - // find script tag with id 'sas_script'. This ensures it only works if you're using Smart Ad Server. - const el = document.getElementById(elementId).querySelectorAll("script[id^='sas_script']"); - if (el[0].nextSibling && el[0].nextSibling.localName === 'iframe') { - el[0].nextSibling.style.setProperty('display', 'none'); - } - } catch (e) { - // element not found! - } -} - -function outstreamRender(bid) { - hidedfpContainer(bid.adUnitCode); - hideSASIframe(bid.adUnitCode); - // push to render queue because ANOutstreamVideo may not be loaded yet - bid.renderer.push(() => { - window.ANOutstreamVideo.renderAd({ - tagId: bid.adResponse.tag_id, - sizes: [bid.getSize().split('x')], - targetId: bid.adUnitCode, // target div id to render video - uuid: bid.adResponse.uuid, - adResponse: bid.adResponse, - rendererOptions: bid.renderer.getConfig() - }, handleOutstreamRendererEvents.bind(null, bid)); - }); -} - -function handleOutstreamRendererEvents(bid, id, eventName) { - bid.renderer.handleVideoEvent({ id, eventName }); -} - -function parseMediaType(rtbBid) { - const adType = rtbBid.ad_type; - if (adType === VIDEO) { - return VIDEO; - } else if (adType === NATIVE) { - return NATIVE; - } else { - return BANNER; - } -} - -function addUserId(eids, id, source, rti) { - if (id) { - if (rti) { - eids.push({ source, id, rti_partner: rti }); - } else { - eids.push({ source, id }); - } - } - return eids; -} - -function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return (bid.params.reserve) ? bid.params.reserve : null; - } - - let floor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*' - }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { - return floor.floor; - } - return null; -} - -registerBidder(spec); diff --git a/modules/goldbachBidAdapter.md b/modules/goldbachBidAdapter.md deleted file mode 100644 index f7c9479439b..00000000000 --- a/modules/goldbachBidAdapter.md +++ /dev/null @@ -1,151 +0,0 @@ -#Overview - -``` -Module Name: Goldbach Bid Adapter -Module Type: Bidder Adapter -Maintainer: dusan.veljovic@goldbach.com -``` - -# Description - -Connects to Xandr exchange for bids. - -Goldbach bid adapter supports Banner, Video (instream and outstream) and Native. - -# Test Parameters -``` -var adUnits = [ - // Banner adUnit - { - code: 'banner-div', - mediaTypes: { - banner: { - sizes: [[300, 250], [300,600]] - } - }, - bids: [{ - bidder: 'goldbach', - params: { - placementId: 13144370 - } - }] - }, - // Native adUnit - { - code: 'native-div', - sizes: [[1, 1]], - mediaTypes: { - native: { - title: { - required: true - }, - body: { - required: true - }, - image: { - required: true - }, - sponsoredBy: { - required: true - }, - icon: { - required: false - } - } - }, - bids: [{ - bidder: 'goldbach', - params: { - placementId: 13232354, - allowSmallerSizes: true - } - }] - }, - // Video instream adUnit - { - code: 'video-instream', - sizes: [[640, 480]], - mediaTypes: { - video: { - playerSize: [[640, 480]], - context: 'instream' - }, - }, - bids: [{ - goldbach: 'goldbach', - params: { - placementId: 13232361, - video: { - skippable: true, - playback_methods: ['auto_play_sound_off'] - } - } - }] - }, - // Video outstream adUnit - { - code: 'video-outstream', - sizes: [[300, 250]], - mediaTypes: { - video: { - playerSize: [[300, 250]], - context: 'outstream', - // Certain ORTB 2.5 video values can be read from the mediatypes object; below are examples of supported params. - // To note - goldbach supports additional values for our system that are not part of the ORTB spec. If you want - // to use these values, they will have to be declared in the bids[].params.video object instead using the goldbach syntax. - // Between the corresponding values of the mediaTypes.video and params.video objects, the properties in params.video will - // take precedence if declared; eg in the example below, the `skippable: true` setting will be used instead of the `skip: 0`. - minduration: 1, - maxduration: 60, - skip: 0, // 1 - true, 0 - false - skipafter: 5, - playbackmethod: [2], // note - we only support options 1-4 at this time - api: [1,2,3] // note - option 6 is not supported at this time - } - }, - bids: [ - { - bidder: 'goldbach', - params: { - placementId: 13232385, - video: { - skippable: true, - playback_method: 'auto_play_sound_off' - } - } - } - ] - }, - // Banner adUnit in a App Webview - // Only use this for situations where prebid.js is in a webview of an App - // See Prebid Mobile for displaying ads via an SDK - { - code: 'banner-div', - mediaTypes: { - banner: { - sizes: [[300, 250], [300,600]] - } - } - bids: [{ - bidder: 'goldbach', - params: { - placementId: 13144370, - app: { - id: "B1O2W3M4AN.com.prebid.webview", - geo: { - lat: 40.0964439, - lng: -75.3009142 - }, - device_id: { - idfa: "4D12078D-3246-4DA4-AD5E-7610481E7AE", // Apple advertising identifier - aaid: "38400000-8cf0-11bd-b23e-10b96e40000d", // Android advertising identifier - md5udid: "5756ae9022b2ea1e47d84fead75220c8", // MD5 hash of the ANDROID_ID - sha1udid: "4DFAA92388699AC6539885AEF1719293879985BF", // SHA1 hash of the ANDROID_ID - windowsadid: "750c6be243f1c4b5c9912b95a5742fc5" // Windows advertising identifier - } - } - } - }] - } -]; -``` diff --git a/modules/googleAnalyticsAdapter.js b/modules/googleAnalyticsAdapter.js index b4c4c8c7009..a8fc83ae62e 100644 --- a/modules/googleAnalyticsAdapter.js +++ b/modules/googleAnalyticsAdapter.js @@ -2,8 +2,8 @@ * ga.js - analytics adapter for google analytics */ -import { _each, logMessage } from '../src/utils.js'; var events = require('../src/events.js'); +var utils = require('../src/utils.js'); var CONSTANTS = require('../src/constants.json'); var adapterManager = require('../src/adapterManager.js').default; @@ -22,7 +22,6 @@ var _enableDistribution = false; var _cpmDistribution = null; var _trackerSend = null; var _sampled = true; -var _sendFloors = false; let adapter = {}; @@ -47,9 +46,6 @@ adapter.enableAnalytics = function ({ provider, options }) { if (options && typeof options.cpmDistribution === 'function') { _cpmDistribution = options.cpmDistribution; } - if (options && typeof options.sendFloors !== 'undefined') { - _sendFloors = options.sendFloors; - } var bid = null; @@ -58,7 +54,7 @@ adapter.enableAnalytics = function ({ provider, options }) { var existingEvents = events.getEvents(); - _each(existingEvents, function (eventObj) { + utils._each(existingEvents, function (eventObj) { if (typeof eventObj !== 'object') { return; } @@ -102,12 +98,12 @@ adapter.enableAnalytics = function ({ provider, options }) { sendBidWonToGa(bid); }); } else { - logMessage('Prebid.js google analytics disabled by sampling'); + utils.logMessage('Prebid.js google analytics disabled by sampling'); } // finally set this function to return log message, prevents multiple adapter listeners this.enableAnalytics = function _enable() { - return logMessage(`Analytics adapter already enabled, unnecessary call to \`enableAnalytics\`.`); + return utils.logMessage(`Analytics adapter already enabled, unnecessary call to \`enableAnalytics\`.`); }; }; @@ -133,7 +129,7 @@ function checkAnalytics() { _enableCheck = false; } - logMessage('event count sent to GA: ' + _eventCount); + utils.logMessage('event count sent to GA: ' + _eventCount); } function convertToCents(dollars) { @@ -207,17 +203,7 @@ function sendBidRequestToGa(bid) { if (bid && bid.bidderCode) { _analyticsQueue.push(function () { _eventCount++; - if (_sendFloors) { - var floor = 'No Floor'; - if (bid.floorData) { - floor = bid.floorData.floorValue; - } else if (bid.bids.length) { - floor = bid.bids[0].getFloor().floor; - } - window[_gaGlobal](_trackerSend, 'event', _category, 'Requests by Floor=' + floor, bid.bidderCode, 1, _disableInteraction); - } else { - window[_gaGlobal](_trackerSend, 'event', _category, 'Requests', bid.bidderCode, 1, _disableInteraction); - } + window[_gaGlobal](_trackerSend, 'event', _category, 'Requests', bid.bidderCode, 1, _disableInteraction); }); } @@ -243,12 +229,8 @@ function sendBidResponseToGa(bid) { _eventCount++; window[_gaGlobal](_trackerSend, 'event', 'Prebid.js CPM Distribution', cpmDis, bidder, 1, _disableInteraction); } - if (_sendFloors) { - var floor = (bid.floorData) ? bid.floorData.floorValue : 'No Floor'; - window[_gaGlobal](_trackerSend, 'event', _category, 'Bids by Floor=' + floor, 'Size=' + bid.size + ',' + bidder, cpmCents, _disableInteraction); - } else { - window[_gaGlobal](_trackerSend, 'event', _category, 'Bids', bidder, cpmCents, _disableInteraction); - } + + window[_gaGlobal](_trackerSend, 'event', _category, 'Bids', bidder, cpmCents, _disableInteraction); window[_gaGlobal](_trackerSend, 'event', _category, 'Bid Load Time', bidder, bid.timeToRespond, _disableInteraction); } }); @@ -260,7 +242,7 @@ function sendBidResponseToGa(bid) { function sendBidTimeouts(timedOutBidders) { _analyticsQueue.push(function () { - _each(timedOutBidders, function (bidderCode) { + utils._each(timedOutBidders, function (bidderCode) { _eventCount++; var bidderName = bidderCode.bidder; window[_gaGlobal](_trackerSend, 'event', _category, 'Timeouts', bidderName, _disableInteraction); @@ -274,12 +256,7 @@ function sendBidWonToGa(bid) { var cpmCents = convertToCents(bid.cpm); _analyticsQueue.push(function () { _eventCount++; - if (_sendFloors) { - var floor = (bid.floorData) ? bid.floorData.floorValue : 'No Floor'; - window[_gaGlobal](_trackerSend, 'event', _category, 'Wins by Floor=' + floor, 'Size=' + bid.size + ',' + bid.bidderCode, cpmCents, _disableInteraction); - } else { - window[_gaGlobal](_trackerSend, 'event', _category, 'Wins', bid.bidderCode, cpmCents, _disableInteraction); - } + window[_gaGlobal](_trackerSend, 'event', _category, 'Wins', bid.bidderCode, cpmCents, _disableInteraction); }); checkAnalytics(); diff --git a/modules/googleAnalyticsAdapter.md b/modules/googleAnalyticsAdapter.md index 8c31b07b811..08423a1d492 100644 --- a/modules/googleAnalyticsAdapter.md +++ b/modules/googleAnalyticsAdapter.md @@ -30,7 +30,6 @@ Here is a full list of settings available - `enableDistribution` (boolean) - enables additional events that track load time and cpm distribution by creating buckets for load time and cpm - `cpmDistribution` (cpm: number => string) - customize the cpm buckets for the cpm distribution -- `sendFloors` (boolean) - if set, will include floor data in the eventCategory field and include ad unit code in eventAction field ## Additional resources diff --git a/modules/gothamadsBidAdapter.js b/modules/gothamadsBidAdapter.js index 1993f0c9b64..ff6fa5221f3 100644 --- a/modules/gothamadsBidAdapter.js +++ b/modules/gothamadsBidAdapter.js @@ -1,6 +1,6 @@ -import { logMessage, deepSetValue, deepAccess, _map, logWarn } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; const BIDDER_CODE = 'gothamads'; @@ -79,7 +79,7 @@ export const spec = { winTop = window.top; } catch (e) { location = winTop.location; - logMessage(e); + utils.logMessage(e); }; let bids = []; @@ -110,12 +110,12 @@ export const spec = { }; if (bidRequest.gdprConsent && bidRequest.gdprConsent.gdprApplies) { - deepSetValue(data, 'regs.ext.gdpr', bidRequest.gdprConsent.gdprApplies ? 1 : 0); - deepSetValue(data, 'user.ext.consent', bidRequest.gdprConsent.consentString); + utils.deepSetValue(data, 'regs.ext.gdpr', bidRequest.gdprConsent.gdprApplies ? 1 : 0); + utils.deepSetValue(data, 'user.ext.consent', bidRequest.gdprConsent.consentString); } if (bidRequest.uspConsent !== undefined) { - deepSetValue(data, 'regs.ext.us_privacy', bidRequest.uspConsent); + utils.deepSetValue(data, 'regs.ext.us_privacy', bidRequest.uspConsent); } bids.push(data) @@ -186,7 +186,7 @@ export const spec = { * @returns {boolean} */ const checkRequestType = (bidRequest, type) => { - return (typeof deepAccess(bidRequest, `mediaTypes.${type}`) !== 'undefined'); + return (typeof utils.deepAccess(bidRequest, `mediaTypes.${type}`) !== 'undefined'); } const parseNative = admObject => { @@ -246,7 +246,7 @@ const addNativeParameters = bidRequest => { ver: NATIVE_VERSION, }; - const assets = _map(bidRequest.mediaTypes.native, (bidParams, key) => { + const assets = utils._map(bidRequest.mediaTypes.native, (bidParams, key) => { const props = NATIVE_PARAMS[key]; const asset = { required: bidParams.required & 1, @@ -300,7 +300,7 @@ const parseSizes = (bid, mediaType) => { mediaTypes.video.w, mediaTypes.video.h ]; - } else if (Array.isArray(deepAccess(bid, 'mediaTypes.video.playerSize')) && bid.mediaTypes.video.playerSize.length === 1) { + } else if (Array.isArray(utils.deepAccess(bid, 'mediaTypes.video.playerSize')) && bid.mediaTypes.video.playerSize.length === 1) { size = bid.mediaTypes.video.playerSize[0]; } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0 && Array.isArray(bid.sizes[0]) && bid.sizes[0].length > 1) { size = bid.sizes[0]; @@ -313,7 +313,7 @@ const parseSizes = (bid, mediaType) => { } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) { sizes = bid.sizes } else { - logWarn('no sizes are setup or found'); + utils.logWarn('no sizes are setup or found'); } return sizes diff --git a/modules/gptPreAuction.js b/modules/gptPreAuction.js index 71884235b38..c351a5181a9 100644 --- a/modules/gptPreAuction.js +++ b/modules/gptPreAuction.js @@ -1,7 +1,7 @@ -import {deepAccess, isAdUnitCodeMatchingSlot, isGptPubadsDefined, logInfo, pick} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {getHook} from '../src/hook.js'; -import {find} from '../src/polyfill.js'; +import { config } from '../src/config.js'; +import * as utils from '../src/utils.js'; +import { getHook } from '../src/hook.js'; +import find from 'core-js-pure/features/array/find.js'; const MODULE_NAME = 'GPT Pre-Auction'; export let _currentConfig = {}; @@ -10,7 +10,7 @@ let hooksAdded = false; export const appendGptSlots = adUnits => { const { customGptSlotMatching } = _currentConfig; - if (!isGptPubadsDefined()) { + if (!utils.isGptPubadsDefined()) { return; } @@ -22,7 +22,7 @@ export const appendGptSlots = adUnits => { window.googletag.pubads().getSlots().forEach(slot => { const matchingAdUnitCode = find(Object.keys(adUnitMap), customGptSlotMatching ? customGptSlotMatching(slot) - : isAdUnitCodeMatchingSlot(slot)); + : utils.isAdUnitCodeMatchingSlot(slot)); if (matchingAdUnitCode) { const adUnit = adUnitMap[matchingAdUnitCode]; @@ -48,48 +48,22 @@ const sanitizeSlotPath = (path) => { return path; } -const defaultPreAuction = (adUnit, adServerAdSlot) => { - const context = adUnit.ortb2Imp.ext.data; - - // use pbadslot if supplied - if (context.pbadslot) { - return context.pbadslot; - } - - // confirm that GPT is set up - if (!isGptPubadsDefined()) { - return; - } - - // find all GPT slots with this name - var gptSlots = window.googletag.pubads().getSlots().filter(slot => slot.getAdUnitPath() === adServerAdSlot); - - if (gptSlots.length === 0) { - return; // should never happen - } - - if (gptSlots.length === 1) { - return adServerAdSlot; - } - - // else the adunit code must be div id. append it. - return `${adServerAdSlot}#${adUnit.code}`; -} - export const appendPbAdSlot = adUnit => { + adUnit.ortb2Imp = adUnit.ortb2Imp || {}; + adUnit.ortb2Imp.ext = adUnit.ortb2Imp.ext || {}; + adUnit.ortb2Imp.ext.data = adUnit.ortb2Imp.ext.data || {}; const context = adUnit.ortb2Imp.ext.data; const { customPbAdSlot } = _currentConfig; - // use context.pbAdSlot if set (if someone set it already, it will take precedence over others) - if (context.pbadslot) { + if (customPbAdSlot) { + context.pbadslot = customPbAdSlot(adUnit.code, utils.deepAccess(context, 'adserver.adslot')); return; } - if (customPbAdSlot) { - context.pbadslot = customPbAdSlot(adUnit.code, deepAccess(context, 'adserver.adslot')); + // use context.pbAdSlot if set + if (context.pbadslot) { return; } - // use data attribute 'data-adslotid' if set try { const adUnitCodeDiv = document.getElementById(adUnit.code); @@ -99,55 +73,27 @@ export const appendPbAdSlot = adUnit => { } } catch (e) {} // banner adUnit, use GPT adunit if defined - if (deepAccess(context, 'adserver.adslot')) { + if (utils.deepAccess(context, 'adserver.adslot')) { context.pbadslot = context.adserver.adslot; return; } context.pbadslot = adUnit.code; - return true; }; export const makeBidRequestsHook = (fn, adUnits, ...args) => { appendGptSlots(adUnits); - const { useDefaultPreAuction, customPreAuction } = _currentConfig; adUnits.forEach(adUnit => { - // init the ortb2Imp if not done yet - adUnit.ortb2Imp = adUnit.ortb2Imp || {}; - adUnit.ortb2Imp.ext = adUnit.ortb2Imp.ext || {}; - adUnit.ortb2Imp.ext.data = adUnit.ortb2Imp.ext.data || {}; - const context = adUnit.ortb2Imp.ext; - - // if neither new confs set do old stuff - if (!customPreAuction && !useDefaultPreAuction) { - const usedAdUnitCode = appendPbAdSlot(adUnit); - // gpid should be set to itself if already set, or to what pbadslot was (as long as it was not adUnit code) - if (!context.gpid && !usedAdUnitCode) { - context.gpid = context.data.pbadslot; - } - } else { - let adserverSlot = deepAccess(context, 'data.adserver.adslot'); - let result; - if (customPreAuction) { - result = customPreAuction(adUnit, adserverSlot); - } else if (useDefaultPreAuction) { - result = defaultPreAuction(adUnit, adserverSlot); - } - if (result) { - context.gpid = context.data.pbadslot = result; - } - } + appendPbAdSlot(adUnit); }); return fn.call(this, adUnits, ...args); }; const handleSetGptConfig = moduleConfig => { - _currentConfig = pick(moduleConfig, [ + _currentConfig = utils.pick(moduleConfig, [ 'enabled', enabled => enabled !== false, 'customGptSlotMatching', customGptSlotMatching => typeof customGptSlotMatching === 'function' && customGptSlotMatching, 'customPbAdSlot', customPbAdSlot => typeof customPbAdSlot === 'function' && customPbAdSlot, - 'customPreAuction', customPreAuction => typeof customPreAuction === 'function' && customPreAuction, - 'useDefaultPreAuction', useDefaultPreAuction => useDefaultPreAuction === true, ]); if (_currentConfig.enabled) { @@ -156,7 +102,7 @@ const handleSetGptConfig = moduleConfig => { hooksAdded = true; } } else { - logInfo(`${MODULE_NAME}: Turning off module`); + utils.logInfo(`${MODULE_NAME}: Turning off module`); _currentConfig = {}; getHook('makeBidRequests').getHooks({hook: makeBidRequestsHook}).remove(); hooksAdded = false; diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index e1090732071..0da15499e0c 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -1,18 +1,17 @@ -import { isEmpty, deepAccess, logError, parseGPTSingleSizeArrayToRtbSize, generateUUID, mergeDeep, logWarn } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { Renderer } from '../src/Renderer.js'; import { VIDEO, BANNER } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; -import { getStorageManager } from '../src/storageManager.js'; const BIDDER_CODE = 'grid'; const ENDPOINT_URL = 'https://grid.bidswitch.net/hbjson'; const SYNC_URL = 'https://x.bidswitch.net/sync?ssp=themediagrid'; const TIME_TO_LIVE = 360; -const USER_ID_KEY = 'tmguid'; -const GVLID = 686; const RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; -export const storage = getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE}); + +let hasSynced = false; + const LOG_ERROR_MESS = { noAuid: 'Bid from response has no auid parameter - ', noAdm: 'Bid from response has no adm parameter - ', @@ -24,12 +23,8 @@ const LOG_ERROR_MESS = { hasEmptySeatbidArray: 'Response has empty seatbid array', hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' }; - -let hasSynced = false; - export const spec = { code: BIDDER_CODE, - aliases: ['playwire', 'adlivetech'], supportedMediaTypes: [ BANNER, VIDEO ], /** * Determines whether or not the given bid request is valid. @@ -55,6 +50,7 @@ export const spec = { let jwpseg = null; let content = null; let schain = null; + let userId = null; let userIdAsEids = null; let user = null; let userExt = null; @@ -74,6 +70,9 @@ export const spec = { if (!schain) { schain = bid.schain; } + if (!userId) { + userId = bid.userId; + } if (!userIdAsEids) { userIdAsEids = bid.userIdAsEids; } @@ -90,26 +89,19 @@ export const spec = { } } let impObj = { - id: bidId.toString(), + id: bidId, tagid: uid.toString(), ext: { - divid: adUnitCode.toString() + divid: adUnitCode } }; - if (ortb2Imp) { - if (ortb2Imp.instl) { - impObj.instl = ortb2Imp.instl; - } - if (ortb2Imp.ext && ortb2Imp.ext.data) { - impObj.ext.data = ortb2Imp.ext.data; - if (impObj.ext.data.adserver && impObj.ext.data.adserver.adslot) { - impObj.ext.gpid = impObj.ext.data.adserver.adslot.toString(); - } else { - impObj.ext.gpid = ortb2Imp.ext.data.pbadslot && ortb2Imp.ext.data.pbadslot.toString(); - } + if (ortb2Imp && ortb2Imp.ext && ortb2Imp.ext.data) { + impObj.ext.data = ortb2Imp.ext.data; + if (impObj.ext.data.adserver && impObj.ext.data.adserver.adslot) { + impObj.ext.gpid = impObj.ext.data.adserver.adslot; } } - if (!isEmpty(keywords)) { + if (!utils.isEmpty(keywords)) { if (!pageKeywords) { pageKeywords = keywords; } @@ -139,7 +131,7 @@ export const spec = { }); const source = { - tid: auctionId && auctionId.toString(), + tid: auctionId, ext: { wrapper: 'Prebid_js', wrapper_version: '$prebid.version$' @@ -154,7 +146,7 @@ export const spec = { const tmax = timeout ? Math.min(bidderTimeout, timeout) : bidderTimeout; let request = { - id: bidderRequestId && bidderRequestId.toString(), + id: bidderRequestId, site: { page: referer }, @@ -171,31 +163,17 @@ export const spec = { user = { data: [{ name: 'iow_labs_pub_data', - segment: segmentProcessing(jwpseg, 'jwpseg'), + segment: jwpseg.map((seg) => { + return {name: 'jwpseg', value: seg}; + }) }] }; } - const ortb2UserData = config.getConfig('ortb2.user.data'); - if (ortb2UserData && ortb2UserData.length) { - if (!user) { - user = { data: [] }; - } - user = mergeDeep(user, { - data: [...ortb2UserData] - }); - } - if (gdprConsent && gdprConsent.consentString) { userExt = {consent: gdprConsent.consentString}; } - const ortb2UserExtDevice = config.getConfig('ortb2.user.ext.device'); - if (ortb2UserExtDevice) { - userExt = userExt || {}; - userExt.device = { ...ortb2UserExtDevice }; - } - if (userIdAsEids && userIdAsEids.length) { userExt = userExt || {}; userExt.eids = [...userIdAsEids]; @@ -206,19 +184,12 @@ export const spec = { user.ext = userExt; } - const fpdUserId = getUserIdFromFPDStorage(); - - if (fpdUserId) { - user = user || {}; - user.id = fpdUserId.toString(); - } - if (user) { request.user = user; } - const userKeywords = deepAccess(config.getConfig('ortb2.user'), 'keywords') || null; - const siteKeywords = deepAccess(config.getConfig('ortb2.site'), 'keywords') || null; + const userKeywords = utils.deepAccess(config.getConfig('ortb2.user'), 'keywords') || null; + const siteKeywords = utils.deepAccess(config.getConfig('ortb2.site'), 'keywords') || null; if (userKeywords) { pageKeywords = pageKeywords || {}; @@ -272,20 +243,6 @@ export const spec = { request.regs.coppa = 1; } - const site = config.getConfig('ortb2.site'); - if (site) { - const pageCategory = [...(site.cat || []), ...(site.pagecat || [])].filter((category) => { - return category && typeof category === 'string' - }); - if (pageCategory.length) { - request.site.cat = pageCategory; - } - const genre = deepAccess(site, 'content.genre'); - if (genre && typeof genre === 'string') { - request.site.content = {...request.site.content, genre}; - } - } - return { method: 'POST', url: ENDPOINT_URL, @@ -317,18 +274,17 @@ export const spec = { _addBidResponse(_getBidFromResponse(respItem), bidRequest, bidResponses); }); } - if (errorMessage) logError(errorMessage); + if (errorMessage) utils.logError(errorMessage); return bidResponses; }, getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent) { if (!hasSynced && syncOptions.pixelEnabled) { let params = ''; - if (gdprConsent) { + if (gdprConsent && typeof gdprConsent.consentString === 'string') { if (typeof gdprConsent.gdprApplies === 'boolean') { - params += `&gdpr=${Number(gdprConsent.gdprApplies)}`; - } - if (typeof gdprConsent.consentString === 'string') { + params += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { params += `&gdpr_consent=${gdprConsent.consentString}`; } } @@ -374,11 +330,11 @@ function _getFloor (mediaTypes, bid) { function _getBidFromResponse(respItem) { if (!respItem) { - logError(LOG_ERROR_MESS.emptySeatbid); + utils.logError(LOG_ERROR_MESS.emptySeatbid); } else if (!respItem.bid) { - logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); } else if (!respItem.bid[0]) { - logError(LOG_ERROR_MESS.noBid); + utils.logError(LOG_ERROR_MESS.noBid); } return respItem && respItem.bid && respItem.bid[0]; } @@ -387,7 +343,7 @@ function _addBidResponse(serverBid, bidRequest, bidResponses) { if (!serverBid) return; let errorMessage; if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); - if (!errorMessage && !serverBid.adm && !serverBid.nurl) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); else { const bid = bidRequest.bidsMap[serverBid.impid]; if (bid) { @@ -412,15 +368,11 @@ function _addBidResponse(serverBid, bidRequest, bidResponses) { } if (serverBid.content_type === 'video') { - if (serverBid.adm) { - bidResponse.vastXml = serverBid.adm; - bidResponse.adResponse = { - content: bidResponse.vastXml - }; - } else if (serverBid.nurl) { - bidResponse.vastUrl = serverBid.nurl; - } + bidResponse.vastXml = serverBid.adm; bidResponse.mediaType = VIDEO; + bidResponse.adResponse = { + content: bidResponse.vastXml + }; if (!bid.renderer && (!bid.mediaTypes || !bid.mediaTypes.video || bid.mediaTypes.video.context === 'outstream')) { bidResponse.renderer = createRenderer(bidResponse, { id: bid.bidId, @@ -435,7 +387,7 @@ function _addBidResponse(serverBid, bidRequest, bidResponses) { } } if (errorMessage) { - logError(errorMessage); + utils.logError(errorMessage); } } @@ -444,7 +396,7 @@ function createVideoRequest(bid, mediaType) { const size = (playerSize || bid.sizes || [])[0]; if (!size) return; - let result = parseGPTSingleSizeArrayToRtbSize(size); + let result = utils.parseGPTSingleSizeArrayToRtbSize(size); if (mimes) { result.mimes = mimes; @@ -466,8 +418,8 @@ function createBannerRequest(bid, mediaType) { const sizes = mediaType.sizes || bid.sizes; if (!sizes || !sizes.length) return; - let format = sizes.map((size) => parseGPTSingleSizeArrayToRtbSize(size)); - let result = parseGPTSingleSizeArrayToRtbSize(sizes[0]); + let format = sizes.map((size) => utils.parseGPTSingleSizeArrayToRtbSize(size)); + let result = utils.parseGPTSingleSizeArrayToRtbSize(sizes[0]); if (format.length) { result.format = format @@ -475,36 +427,6 @@ function createBannerRequest(bid, mediaType) { return result; } -function makeNewUserIdInFPDStorage() { - if (config.getConfig('localStorageWriteAllowed')) { - const value = generateUUID().replace(/-/g, ''); - - storage.setDataInLocalStorage(USER_ID_KEY, value); - return value; - } - return null; -} - -function getUserIdFromFPDStorage() { - return storage.getDataFromLocalStorage(USER_ID_KEY) || makeNewUserIdInFPDStorage(); -} - -function segmentProcessing(segment, forceSegName) { - return segment - .map((seg) => { - const value = seg && (seg.value || seg.id || seg); - if (typeof value === 'string' || typeof value === 'number') { - return { - value: value.toString(), - ...(forceSegName && { name: forceSegName }), - ...(seg.name && { name: seg.name }), - }; - } - return null; - }) - .filter((seg) => !!seg); -} - function reformatKeywords(pageKeywords) { const formatedPageKeywords = {}; Object.keys(pageKeywords).forEach((name) => { @@ -569,7 +491,7 @@ function createRenderer (bid, rendererParams) { try { renderer.setRender(outstreamRender); } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); + utils.logWarn('Prebid Error calling setRender on renderer', err); } return renderer; diff --git a/modules/gridBidAdapter.md b/modules/gridBidAdapter.md index d5ec747aae2..6a7075ccb00 100644 --- a/modules/gridBidAdapter.md +++ b/modules/gridBidAdapter.md @@ -9,27 +9,12 @@ Maintainer: grid-tech@themediagrid.com Module that connects to Grid demand source to fetch bids. Grid bid adapter supports Banner and Video (instream and outstream). -#Bidder Config -You can allow writing in localStorage `pbjs.setBidderConfig` for the bidder `grid` -``` -pbjs.setBidderConfig({ - bidders: ["grid"], - config: { - localStorageWriteAllowed: true - } -}) -``` - # Test Parameters ``` var adUnits = [ { code: 'test-div', - mediaTypes: { - banner: { - sizes: [[300, 250], [300,600]], - } - }, + sizes: [[300, 250]], bids: [ { bidder: "grid", @@ -41,19 +26,15 @@ pbjs.setBidderConfig({ ] },{ code: 'test-div', + sizes: [[728, 90]], bids: [ { bidder: "grid", params: { uid: 2, keywords: { - site: { - publisher: [{ - name: 'someKeywordsName', - brandsafety: ['disaster'], - topic: ['stress', 'fear'] - }] - } + brandsafety: ['disaster'], + topic: ['stress', 'fear'] } } } @@ -62,12 +43,7 @@ pbjs.setBidderConfig({ { code: 'test-div', sizes: [[728, 90]], - mediaTypes: { - video: { - playerSize: [1280, 720], - context: 'instream' - } - }, + mediaTypes: { video: {} }, bids: [ { bidder: "grid", diff --git a/modules/gridNMBidAdapter.js b/modules/gridNMBidAdapter.js index 3c46b25b8e1..4ab8464b115 100644 --- a/modules/gridNMBidAdapter.js +++ b/modules/gridNMBidAdapter.js @@ -1,11 +1,10 @@ -import { isStr, deepAccess, isArray, isNumber, logError, logWarn, parseGPTSingleSizeArrayToRtbSize } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; import { Renderer } from '../src/Renderer.js'; import { VIDEO } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; const BIDDER_CODE = 'gridNM'; -const ENDPOINT_URL = 'https://grid.bidswitch.net/hbjson'; +const ENDPOINT_URL = 'https://grid.bidswitch.net/hbnm'; const SYNC_URL = 'https://x.bidswitch.net/sync?ssp=themediagrid'; const TIME_TO_LIVE = 360; const RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; @@ -38,19 +37,19 @@ export const spec = { */ isBidRequestValid: function(bid) { let invalid = - !bid.params.source || !isStr(bid.params.source) || - !bid.params.secid || !isStr(bid.params.secid) || - !bid.params.pubid || !isStr(bid.params.pubid); + !bid.params.source || !utils.isStr(bid.params.source) || + !bid.params.secid || !utils.isStr(bid.params.secid) || + !bid.params.pubid || !utils.isStr(bid.params.pubid); - const video = deepAccess(bid, 'mediaTypes.video') || {}; - const { protocols = video.protocols, mimes = video.mimes } = deepAccess(bid, 'params.video') || {}; + const video = utils.deepAccess(bid, 'mediaTypes.video') || {}; + const { protocols = video.protocols, mimes = video.mimes } = utils.deepAccess(bid, 'params.video') || {}; if (!invalid) { invalid = !protocols || !mimes; } if (!invalid) { - invalid = !isArray(mimes) || !mimes.length || mimes.filter((it) => !(it && isStr(it))).length; + invalid = !utils.isArray(mimes) || !mimes.length || mimes.filter((it) => !(it && utils.isStr(it))).length; if (!invalid) { - invalid = !isArray(protocols) || !protocols.length || protocols.filter((it) => !(isNumber(it) && it > 0 && !(it % 1))).length; + invalid = !utils.isArray(protocols) || !protocols.length || protocols.filter((it) => !(utils.isNumber(it) && it > 0 && !(it % 1))).length; } } return !invalid; @@ -65,146 +64,62 @@ export const spec = { buildRequests: function(validBidRequests, bidderRequest) { const bids = validBidRequests || []; const requests = []; - let { bidderRequestId, auctionId, gdprConsent, uspConsent, timeout, refererInfo } = bidderRequest || {}; - - const referer = refererInfo ? encodeURIComponent(refererInfo.referer) : ''; bids.forEach(bid => { - let user; - let userExt; - - const schain = bid.schain; - const userIdAsEids = bid.userIdAsEids; - - if (!bidderRequestId) { - bidderRequestId = bid.bidderRequestId; - } - if (!auctionId) { - auctionId = bid.auctionId; - } - const { - params: { floorcpm, pubdata, source, secid, pubid, content, video }, - mediaTypes, bidId, adUnitCode, rtd, ortb2Imp, sizes - } = bid; - - const bidFloor = _getFloor(mediaTypes || {}, bid, isNumber(floorcpm) && floorcpm); - const jwTargeting = rtd && rtd.jwplayer && rtd.jwplayer.targeting; - const jwpseg = (pubdata && pubdata.jwpseg) || (jwTargeting && jwTargeting.segments); - - const siteContent = content || (jwTargeting && jwTargeting.content); - - const impObj = { - id: bidId.toString(), - tagid: secid.toString(), - video: createVideoForImp(video, sizes, mediaTypes && mediaTypes.video), - ext: { - divid: adUnitCode.toString() - } + const { params, bidderRequestId, sizes } = bid; + const payload = { + sizes: utils.parseSizesInput(sizes).join(','), + r: bidderRequestId, + wrapperType: 'Prebid_js', + wrapperVersion: '$prebid.version$' }; - if (ortb2Imp && ortb2Imp.ext && ortb2Imp.ext.data) { - impObj.ext.data = ortb2Imp.ext.data; - if (impObj.ext.data.adserver && impObj.ext.data.adserver.adslot) { - impObj.ext.gpid = impObj.ext.data.adserver.adslot.toString(); - } else { - impObj.ext.gpid = ortb2Imp.ext.data.pbadslot && ortb2Imp.ext.data.pbadslot.toString(); + if (bidderRequest) { + if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + payload.u = bidderRequest.refererInfo.referer; } - } - - if (bidFloor) { - impObj.bidfloor = bidFloor; - } - - const imp = [impObj]; - - const reqSource = { - tid: auctionId && auctionId.toString(), - ext: { - wrapper: 'Prebid_js', - wrapper_version: '$prebid.version$' + if (bidderRequest.timeout) { + payload.wtimeout = bidderRequest.timeout; } - }; - - if (schain) { - reqSource.ext.schain = schain; - } - - const bidderTimeout = config.getConfig('bidderTimeout') || timeout; - const tmax = timeout ? Math.min(bidderTimeout, timeout) : bidderTimeout; - - const request = { - id: bidderRequestId && bidderRequestId.toString(), - site: { - page: referer, - publisher: { - id: pubid, - }, - }, - source: reqSource, - tmax, - imp, - }; - - if (siteContent) { - request.site.content = siteContent; - } - - if (jwpseg && jwpseg.length) { - user = { - data: [{ - name: 'iow_labs_pub_data', - segment: jwpseg.map((seg) => { - return {name: 'jwpseg', value: seg}; - }) - }] - }; - } - - if (gdprConsent && gdprConsent.consentString) { - userExt = { consent: gdprConsent.consentString }; - } - - if (userIdAsEids && userIdAsEids.length) { - userExt = userExt || {}; - userExt.eids = [...userIdAsEids]; - } - - if (userExt && Object.keys(userExt).length) { - user = user || {}; - user.ext = userExt; - } - - if (user) { - request.user = user; - } - - if (gdprConsent && gdprConsent.gdprApplies) { - request.regs = { - ext: { - gdpr: gdprConsent.gdprApplies ? 1 : 0 + if (bidderRequest.gdprConsent) { + if (bidderRequest.gdprConsent.consentString) { + payload.gdpr_consent = bidderRequest.gdprConsent.consentString; } + payload.gdpr_applies = + (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') + ? Number(bidderRequest.gdprConsent.gdprApplies) : 1; + } + if (bidderRequest.uspConsent) { + payload.us_privacy = bidderRequest.uspConsent; } } - if (uspConsent) { - if (!request.regs) { - request.regs = { ext: {} }; + const video = utils.deepAccess(bid, 'mediaTypes.video') || {}; + const paramsVideo = Object.assign({}, params.video); + VIDEO_KEYS.forEach((key) => { + if (!(key in paramsVideo) && key in video) { + paramsVideo[key] = video[key]; } - request.regs.ext.us_privacy = uspConsent; + }); + + if (!paramsVideo.size && video.playerSize && video.playerSize.length === 2) { + paramsVideo.size = video.playerSize.join('x'); } - if (config.getConfig('coppa') === true) { - if (!request.regs) { - request.regs = {}; - } - request.regs.coppa = 1; + if (!('mind' in paramsVideo) && 'minduration' in video) { + paramsVideo.mind = video.minduration; } + if (!('maxd' in paramsVideo) && 'maxduration' in video) { + paramsVideo.maxd = video.maxduration; + } + + const paramsToSend = Object.assign({}, params, {video: paramsVideo}); requests.push({ method: 'POST', - url: ENDPOINT_URL + '?no_mapping=1&sp=' + source, + url: ENDPOINT_URL + '?' + utils.parseQueryStringParameters(payload).replace(/\&$/, ''), bid: bid, - data: request + data: paramsToSend // content }); }); @@ -231,11 +146,16 @@ export const spec = { if (!errorMessage && serverResponse.seatbid) { const serverBid = _getBidFromResponse(serverResponse.seatbid[0]); if (serverBid) { - if (!serverBid.adm && !serverBid.nurl) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); else if (!serverBid.price) errorMessage = LOG_ERROR_MESS.noPrice + JSON.stringify(serverBid); else if (serverBid.content_type !== 'video') errorMessage = LOG_ERROR_MESS.wrongContentType + serverBid.content_type; if (!errorMessage) { const bid = bidRequest.bid; + if (!serverBid.w || !serverBid.h) { + const size = utils.parseSizesInput(bid.sizes)[0].split('x'); + serverBid.w = size[0]; + serverBid.h = size[1]; + } const bidResponse = { requestId: bid.bidId, cpm: serverBid.price, @@ -246,21 +166,16 @@ export const spec = { netRevenue: true, ttl: TIME_TO_LIVE, dealId: serverBid.dealid, + vastXml: serverBid.adm, mediaType: VIDEO, meta: { advertiserDomains: serverBid.adomain ? serverBid.adomain : [] + }, + adResponse: { + content: serverBid.adm } }; - if (serverBid.adm) { - bidResponse.vastXml = serverBid.adm; - bidResponse.adResponse = { - content: bidResponse.vastXml - }; - } else if (serverBid.nurl) { - bidResponse.vastUrl = serverBid.nurl; - } - if (!bid.renderer && (!bid.mediaTypes || !bid.mediaTypes.video || bid.mediaTypes.video.context === 'outstream')) { bidResponse.renderer = createRenderer(bidResponse, { id: bid.bidId, @@ -271,7 +186,7 @@ export const spec = { } } } - if (errorMessage) logError(errorMessage); + if (errorMessage) utils.logError(errorMessage); return bidResponses; }, getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent) { @@ -298,40 +213,13 @@ export const spec = { } }; -/** - * Gets bidfloor - * @param {Object} mediaTypes - * @param {Object} bid - * @param {Number} floor - * @returns {Number} floor - */ -function _getFloor (mediaTypes, bid, floor) { - const curMediaType = mediaTypes.video ? 'video' : 'banner'; - - if (typeof bid.getFloor === 'function') { - const floorInfo = bid.getFloor({ - currency: 'USD', - mediaType: curMediaType, - size: bid.sizes.map(([w, h]) => ({w, h})) - }); - - if (typeof floorInfo === 'object' && - floorInfo.currency === 'USD' && - !isNaN(parseFloat(floorInfo.floor))) { - floor = Math.max(floor, parseFloat(floorInfo.floor)); - } - } - - return floor; -} - function _getBidFromResponse(respItem) { if (!respItem) { - logError(LOG_ERROR_MESS.emptySeatbid); + utils.logError(LOG_ERROR_MESS.emptySeatbid); } else if (!respItem.bid) { - logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); } else if (!respItem.bid[0]) { - logError(LOG_ERROR_MESS.noBid); + utils.logError(LOG_ERROR_MESS.noBid); } return respItem && respItem.bid && respItem.bid[0]; } @@ -355,51 +243,12 @@ function createRenderer (bid, rendererParams) { try { renderer.setRender(outstreamRender); } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); + utils.logWarn('Prebid Error calling setRender on renderer', err); } return renderer; } -function createVideoForImp({ mind, maxd, size, ...paramsVideo }, bidSizes, bidVideo = {}) { - VIDEO_KEYS.forEach((key) => { - if (!(key in paramsVideo) && key in bidVideo) { - paramsVideo[key] = bidVideo[key]; - } - }); - - if (size && isStr(size)) { - const sizeArray = size.split('x'); - if (sizeArray.length === 2 && parseInt(sizeArray[0]) && parseInt(sizeArray[1])) { - paramsVideo.w = parseInt(sizeArray[0]); - paramsVideo.h = parseInt(sizeArray[1]); - } - } - - if (!paramsVideo.w || !paramsVideo.h) { - const playerSizes = bidVideo.playerSize && bidVideo.playerSize.length === 2 ? bidVideo.playerSize : bidSizes; - if (playerSizes) { - const playerSize = playerSizes[0]; - if (playerSize) { - Object.assign(paramsVideo, parseGPTSingleSizeArrayToRtbSize(playerSize)); - } - } - } - - const durationRangeSec = bidVideo.durationRangeSec || []; - const minDur = mind || durationRangeSec[0] || bidVideo.minduration; - const maxDur = maxd || durationRangeSec[1] || bidVideo.maxduration; - - if (minDur) { - paramsVideo.minduration = minDur; - } - if (maxDur) { - paramsVideo.maxduration = maxDur; - } - - return paramsVideo; -} - export function resetUserSync() { hasSynced = false; } diff --git a/modules/growadvertisingBidAdapter.js b/modules/growadvertisingBidAdapter.js index 286d27607c5..0626b137a1b 100644 --- a/modules/growadvertisingBidAdapter.js +++ b/modules/growadvertisingBidAdapter.js @@ -1,8 +1,9 @@ 'use strict'; -import { getBidIdParameter, deepAccess, _each, triggerPixel } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE} from '../src/mediaTypes.js'; +import {triggerPixel} from '../src/utils.js'; const BIDDER_CODE = 'growads'; @@ -22,8 +23,8 @@ export const spec = { const zoneCounters = {}; return validBidRequests.map(bidRequest => { - zoneId = getBidIdParameter('zoneId', bidRequest.params); - domain = getBidIdParameter('domain', bidRequest.params); + zoneId = utils.getBidIdParameter('zoneId', bidRequest.params); + domain = utils.getBidIdParameter('domain', bidRequest.params); if (!(zoneId in zoneCounters)) { zoneCounters[zoneId] = 0; @@ -76,8 +77,8 @@ export const spec = { width = parseInt(response.width); height = parseInt(response.height); - minCPM = getBidIdParameter('minCPM', request.params); - maxCPM = getBidIdParameter('maxCPM', request.params); + minCPM = utils.getBidIdParameter('minCPM', request.params); + maxCPM = utils.getBidIdParameter('maxCPM', request.params); width = parseInt(response.width); height = parseInt(response.height); @@ -101,7 +102,7 @@ export const spec = { netRevenue: true, ttl: response.ttl, adUnitCode: request.adUnitCode, - referrer: deepAccess(request, 'refererInfo.referer') + referrer: utils.deepAccess(request, 'refererInfo.referer') }; if (response.hasOwnProperty(NATIVE)) { @@ -136,7 +137,7 @@ export const spec = { bid.ad = response.ad; bid.mediaType = BANNER; // Ensure that response ad matches one of the placement sizes. - _each(deepAccess(request, 'mediaTypes.banner.sizes', []), function (size) { + utils._each(utils.deepAccess(request, 'mediaTypes.banner.sizes', []), function (size) { if (width === size[0] && height === size[1]) { isCorrectSize = true; } diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index f7662f54fae..3a0862b9aec 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -1,13 +1,15 @@ -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {_each, deepAccess, logError, logWarn, parseSizesInput} from '../src/utils.js'; +import * as utils from '../src/utils.js' -import {config} from '../src/config.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {includes} from '../src/polyfill.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; + +import { config } from '../src/config.js' +import { getStorageManager } from '../src/storageManager.js'; +import includes from 'core-js-pure/features/array/includes'; +import { registerBidder } from '../src/adapters/bidderFactory.js' + +const storage = getStorageManager(); const BIDDER_CODE = 'gumgum' -const storage = getStorageManager({bidderCode: BIDDER_CODE}); const ALIAS_BIDDER_CODE = ['gg'] const BID_ENDPOINT = `https://g2.gumgum.com/hbid/imp` const JCSI = { t: 0, rq: 8, pbv: '$prebid.version$' } @@ -16,48 +18,32 @@ const TIME_TO_LIVE = 60 const DELAY_REQUEST_TIME = 1800000; // setting to 30 mins let invalidRequestIds = {}; +let browserParams = {}; let pageViewId = null; // TODO: potential 0 values for browserParams sent to ad server function _getBrowserParams(topWindowUrl) { - const paramRegex = paramName => new RegExp(`[?#&](${paramName}=(.*?))($|&)`, 'i'); - - let browserParams = {}; - let topWindow; - let topScreen; - let topUrl; - let ggad; - let ggdeal; - let ns; - - function getNetworkSpeed () { - const connection = window.navigator && (window.navigator.connection || window.navigator.mozConnection || window.navigator.webkitConnection); - const Mbps = connection && (connection.downlink || connection.bandwidth); - return Mbps ? Math.round(Mbps * 1024) : null; + let topWindow + let topScreen + let topUrl + let ggad + let ns + function getNetworkSpeed() { + const connection = window.navigator && (window.navigator.connection || window.navigator.mozConnection || window.navigator.webkitConnection) + const Mbps = connection && (connection.downlink || connection.bandwidth) + return Mbps ? Math.round(Mbps * 1024) : null } - - function getOgURL () { - let ogURL = ''; - const ogURLSelector = "meta[property='og:url']"; - const head = document && document.getElementsByTagName('head')[0]; - const ogURLElement = head.querySelector(ogURLSelector); - ogURL = ogURLElement ? ogURLElement.content : null; - return ogURL; + function getOgURL() { + let ogURL = '' + const ogURLSelector = "meta[property='og:url']" + const head = document && document.getElementsByTagName('head')[0] + const ogURLElement = head.querySelector(ogURLSelector) + ogURL = ogURLElement ? ogURLElement.content : null + return ogURL } - - function stripGGParams (url) { - const params = [ - 'ggad', - 'ggdeal' - ]; - - return params.reduce((result, param) => { - const matches = url.match(paramRegex(param)); - if (!matches) return result; - matches[1] && (result = result.replace(matches[1], '')); - matches[3] && (result = result.replace(matches[3], '')); - return result; - }, url); + if (browserParams.vw) { + // we've already initialized browserParams, just return it. + return browserParams } try { @@ -65,8 +51,8 @@ function _getBrowserParams(topWindowUrl) { topScreen = topWindow.screen; topUrl = topWindowUrl || ''; } catch (error) { - logError(error); - return browserParams; + utils.logError(error); + return browserParams } browserParams = { @@ -74,25 +60,23 @@ function _getBrowserParams(topWindowUrl) { vh: topWindow.innerHeight, sw: topScreen.width, sh: topScreen.height, - pu: stripGGParams(topUrl), + pu: topUrl, ce: storage.cookiesAreEnabled(), dpr: topWindow.devicePixelRatio || 1, jcsi: JSON.stringify(JCSI), ogu: getOgURL() - }; + } - ns = getNetworkSpeed(); + ns = getNetworkSpeed() if (ns) { - browserParams.ns = ns; + browserParams.ns = ns } - ggad = (topUrl.match(paramRegex('ggad')) || [0, 0, 0])[2]; - if (ggad) browserParams[isNaN(ggad) ? 'eAdBuyId' : 'adBuyId'] = ggad; - - ggdeal = (topUrl.match(paramRegex('ggdeal')) || [0, 0, 0])[2]; - if (ggdeal) browserParams.ggdeal = ggdeal; - - return browserParams; + ggad = (topUrl.match(/#ggad=(\w+)$/) || [0, 0])[1] + if (ggad) { + browserParams[isNaN(ggad) ? 'eAdBuyId' : 'adBuyId'] = ggad + } + return browserParams } function getWrapperCode(wrapper, data) { @@ -147,7 +131,7 @@ function isBidRequestValid(bid) { const id = legacyParamID || params.slot || params.native || params.zone || params.pubID; if (invalidRequestIds[id]) { - logWarn(`[GumGum] Please check the implementation for ${id} for the placement ${adUnitCode}`); + utils.logWarn(`[GumGum] Please check the implementation for ${id} for the placement ${adUnitCode}`); return false; } @@ -162,12 +146,12 @@ function isBidRequestValid(bid) { case !!(params.inVideo): break; case !!(params.videoPubID): break; default: - logWarn(`[GumGum] No product selected for the placement ${adUnitCode}, please check your implementation.`); + utils.logWarn(`[GumGum] No product selected for the placement ${adUnitCode}, please check your implementation.`); return false; } if (params.bidfloor && !(typeof params.bidfloor === 'number' && isFinite(params.bidfloor))) { - logWarn('[GumGum] bidfloor must be a Number'); + utils.logWarn('[GumGum] bidfloor must be a Number'); return false; } @@ -189,7 +173,7 @@ function _getVidParams(attributes) { protocols = [], playerSize = [] } = attributes; - const sizes = parseSizesInput(playerSize); + const sizes = utils.parseSizesInput(playerSize); const [viw, vih] = sizes[0] && sizes[0].split('x'); let pr = ''; @@ -295,7 +279,7 @@ function buildRequests(validBidRequests, bidderRequest) { const uspConsent = bidderRequest && bidderRequest.uspConsent; const timeout = config.getConfig('bidderTimeout'); const topWindowUrl = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; - _each(validBidRequests, bidRequest => { + utils._each(validBidRequests, bidRequest => { const { bidId, mediaTypes = {}, @@ -303,31 +287,21 @@ function buildRequests(validBidRequests, bidderRequest) { schain, transactionId, userId = {}, - ortb2Imp, - adUnitCode = '' + ortb2Imp } = bidRequest; const { currency, floor } = _getFloor(mediaTypes, params.bidfloor, bidRequest); const eids = getEids(userId); - const gpid = deepAccess(ortb2Imp, 'ext.data.pbadslot') || deepAccess(ortb2Imp, 'ext.data.adserver.adslot'); let sizes = [1, 1]; let data = {}; - - const date = new Date(); - const lt = date.getTime(); - const to = date.getTimezoneOffset(); - - // ADTS-174 Removed unnecessary checks to fix failing test - data.lt = lt; - data.to = to; - - // ADTS-169 add adUnitCode to requests - if (adUnitCode) data.aun = adUnitCode + let gpid = ''; // ADTS-134 Retrieve ID envelopes for (const eid in eids) data[eid] = eids[eid]; - // ADJS-1024 & ADSS-1297 & ADTS-175 - gpid && (data.gpid = gpid); + // ADJS-1024 + if (utils.deepAccess(ortb2Imp, 'ext.data.adserver.name')) { + gpid = ortb2Imp.ext.data.adserver.adslot + } if (mediaTypes.banner) { sizes = mediaTypes.banner.sizes; @@ -362,11 +336,11 @@ function buildRequests(validBidRequests, bidderRequest) { const [maxw, maxh] = getGreatestDimensions(sizes); data.maxw = maxw; data.maxh = maxh; - data.si = params.slot; + data.si = parseInt(params.slot, 10); data.pi = 3; data.bf = sizes.reduce((acc, curSlotDim) => `${acc}${acc && ','}${curSlotDim[0]}x${curSlotDim[1]}`, ''); } else if (params.native) { - data.ni = params.native; + data.ni = parseInt(params.native, 10); data.pi = 5; } else if (mediaTypes.video) { data.pi = mediaTypes.video.linearity === 2 ? 6 : 7; // invideo : video @@ -397,7 +371,7 @@ function buildRequests(validBidRequests, bidderRequest) { sizes, url: BID_ENDPOINT, method: 'GET', - data: Object.assign(data, _getBrowserParams(topWindowUrl), _getDigiTrustQueryParams(userId)) + data: Object.assign(data, _getBrowserParams(topWindowUrl), _getDigiTrustQueryParams(userId), { gpid }) }) }); return bids; @@ -417,12 +391,12 @@ function handleLegacyParams(params, sizes) { const [maxw, maxh] = getGreatestDimensions(sizes); data.maxw = maxw; data.maxh = maxh; - data.si = params.inSlot; + data.si = parseInt(params.inSlot, 10); data.pi = 3; data.bf = sizes.reduce((acc, curSlotDim) => `${acc}${acc && ','}${curSlotDim[0]}x${curSlotDim[1]}`, ''); } if (params.ICV) { - data.ni = params.ICV; + data.ni = parseInt(params.ICV, 10); data.pi = 5; } if (params.videoPubID) { @@ -459,7 +433,7 @@ function interpretResponse(serverResponse, bidRequest) { setTimeout(() => { !!invalidRequestIds[id] && delete invalidRequestIds[id]; }, delayTime); - logWarn(`[GumGum] Please check the implementation for ${id}`); + utils.logWarn(`[GumGum] Please check the implementation for ${id}`); } const defaultResponse = { @@ -507,19 +481,14 @@ function interpretResponse(serverResponse, bidRequest) { advertiserDomains: advertiserDomains || [], mediaType: type || mediaType }; - let sizes = parseSizesInput(bidRequest.sizes); + let sizes = utils.parseSizesInput(bidRequest.sizes); if (maxw && maxh) { sizes = [`${maxw}x${maxh}`]; } else if (product === 5 && includes(sizes, '1x1')) { sizes = ['1x1']; } else if (product === 2 && includes(sizes, '1x1')) { - const requestSizesThatMatchResponse = (bidRequest.sizes && bidRequest.sizes.reduce((result, current) => { - const [ width, height ] = current; - if (responseWidth === width || responseHeight === height) result.push(current.join('x')); - return result - }, [])) || []; - sizes = requestSizesThatMatchResponse.length ? requestSizesThatMatchResponse : parseSizesInput(bidRequest.sizes) + sizes = responseWidth && responseHeight ? [`${responseWidth}x${responseHeight}`] : utils.parseSizesInput(bidRequest.sizes) } let [width, height] = sizes[0].split('x'); diff --git a/modules/h12mediaBidAdapter.js b/modules/h12mediaBidAdapter.js index 9a6244a9e82..7b736780226 100644 --- a/modules/h12mediaBidAdapter.js +++ b/modules/h12mediaBidAdapter.js @@ -1,4 +1,4 @@ -import { inIframe, logError, logMessage, deepAccess } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'h12media'; const DEFAULT_URL = 'https://bidder.h12-media.com/prebid/'; @@ -15,7 +15,7 @@ export const spec = { }, buildRequests: function(validBidRequests, bidderRequest) { - const isiframe = inIframe(); + const isiframe = utils.inIframe(); const screenSize = getClientDimensions(); const docSize = getDocumentDimensions(); @@ -24,7 +24,7 @@ export const spec = { const requestUrl = bidderParams.endpointdom || DEFAULT_URL; let pubsubid = bidderParams.pubsubid || ''; if (pubsubid && pubsubid.length > 32) { - logError('Bidder param \'pubsubid\' should be not more than 32 chars.'); + utils.logError('Bidder param \'pubsubid\' should be not more than 32 chars.'); pubsubid = ''; } const pubcontainerid = bidderParams.pubcontainerid; @@ -57,7 +57,7 @@ export const spec = { try { windowTop = window.top; } catch (e) { - logMessage(e); + utils.logMessage(e); windowTop = window; } @@ -66,11 +66,11 @@ export const spec = { url: requestUrl, options: {withCredentials: true}, data: { - gdpr: !!deepAccess(bidderRequest, 'gdprConsent.gdprApplies', false), - gdpr_cs: deepAccess(bidderRequest, 'gdprConsent.consentString', ''), - usp: !!deepAccess(bidderRequest, 'uspConsent', false), - usp_cs: deepAccess(bidderRequest, 'uspConsent', ''), - topLevelUrl: deepAccess(bidderRequest, 'refererInfo.referer', ''), + gdpr: !!utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies', false), + gdpr_cs: utils.deepAccess(bidderRequest, 'gdprConsent.consentString', ''), + usp: !!utils.deepAccess(bidderRequest, 'uspConsent', false), + usp_cs: utils.deepAccess(bidderRequest, 'uspConsent', ''), + topLevelUrl: utils.deepAccess(bidderRequest, 'refererInfo.referer', ''), refererUrl: windowTop.document.referrer, isiframe, version: '$prebid.version$', @@ -122,14 +122,14 @@ export const spec = { } return bidResponses; } catch (err) { - logError(err); + utils.logError(err); } }, getUserSyncs: function(syncOptions, serverResponses, gdprConsent, usPrivacy) { const syncs = []; - const uspApplies = !!deepAccess(usPrivacy, 'uspConsent', false); - const uspString = deepAccess(usPrivacy, 'uspConsent', ''); + const uspApplies = !!utils.deepAccess(usPrivacy, 'uspConsent', false); + const uspString = utils.deepAccess(usPrivacy, 'uspConsent', ''); gdprConsent = gdprConsent || { gdprApplies: false, consentString: '', }; diff --git a/modules/hadronIdSystem.js b/modules/hadronIdSystem.js deleted file mode 100644 index db2620d2422..00000000000 --- a/modules/hadronIdSystem.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * This module adds HadronID to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/hadronIdSystem - * @requires module:modules/userId - */ - -import {ajax} from '../src/ajax.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {submodule} from '../src/hook.js'; -import { isFn, isStr, isPlainObject, logError } from '../src/utils.js'; - -const MODULE_NAME = 'hadronId'; -const AU_GVLID = 561; - -export const storage = getStorageManager({gvlid: AU_GVLID, moduleName: 'hadron'}); - -/** - * Param or default. - * @param {String} param - * @param {String} defaultVal - */ -function paramOrDefault(param, defaultVal, arg) { - if (isFn(param)) { - return param(arg); - } else if (isStr(param)) { - return param; - } - return defaultVal; -} - -/** @type {Submodule} */ -export const hadronIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - /** - * decode the stored id value for passing to bid requests - * @function - * @param {{value:string}} value - * @returns {{hadronId:Object}} - */ - decode(value) { - let hadronId = storage.getDataFromLocalStorage('auHadronId'); - if (isStr(hadronId)) { - return {hadronId: hadronId}; - } - return (value && typeof value['hadronId'] === 'string') ? { 'hadronId': value['hadronId'] } : undefined; - }, - /** - * performs action to obtain id and return a value in the callback's response argument - * @function - * @param {SubmoduleConfig} [config] - * @returns {IdResponse|undefined} - */ - getId(config) { - if (!isPlainObject(config.params)) { - config.params = {}; - } - const url = paramOrDefault(config.params.url, - `https://id.hadron.ad.gt/api/v1/pbhid`, - config.params.urlArg); - - const resp = function (callback) { - let hadronId = storage.getDataFromLocalStorage('auHadronId'); - if (isStr(hadronId)) { - const responseObj = {hadronId: hadronId}; - callback(responseObj); - } else { - const callbacks = { - success: response => { - let responseObj; - if (response) { - try { - responseObj = JSON.parse(response); - } catch (error) { - logError(error); - } - } - callback(responseObj); - }, - error: error => { - logError(`${MODULE_NAME}: ID fetch encountered an error`, error); - callback(); - } - }; - ajax(url, callbacks, undefined, {method: 'GET'}); - } - }; - return {callback: resp}; - } -}; - -submodule('userId', hadronIdSubmodule); diff --git a/modules/hadronIdSystem.md b/modules/hadronIdSystem.md deleted file mode 100644 index 26539676e17..00000000000 --- a/modules/hadronIdSystem.md +++ /dev/null @@ -1,35 +0,0 @@ -## Audigent Hadron User ID Submodule - -Audigent Hadron ID Module. For assistance setting up your module please contact us at [prebid@audigent.com](prebid@audigent.com). - -### Prebid Params - -Individual params may be set for the Audigent Hadron ID Submodule. At least one identifier must be set in the params. - -``` -pbjs.setConfig({ - usersync: { - userIds: [{ - name: 'hadronId', - storage: { - name: 'hadronId', - type: 'html5' - } - }] - } -}); -``` -## Parameter Descriptions for the `usersync` Configuration Section -The below parameters apply only to the HadronID User ID Module integration. - -| Param under usersync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | ID value for the HadronID module - `"hadronId"` | `"hadronId"` | -| storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | | -| storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` | -| storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"hadronid"` | -| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. | `365` | -| value | Optional | Object | Used only if the page has a separate mechanism for storing the Hadron ID. The value is an object containing the values to be sent to the adapters. In this scenario, no URL is called and nothing is added to local storage | `{"hadronId": "eb33b0cb-8d35-4722-b9c0-1a31d4064888"}` | -| params | Optional | Object | Used to store params for the id system | -| params.url | Optional | String | Set an alternate GET url for HadronId with this parameter | -| params.urlArg | Optional | Object | Optional url parameter for params.url | diff --git a/modules/hadronRtdProvider.js b/modules/hadronRtdProvider.js deleted file mode 100644 index 0b1081f174a..00000000000 --- a/modules/hadronRtdProvider.js +++ /dev/null @@ -1,254 +0,0 @@ -/** - * This module adds the Audigent Hadron provider to the real time data module - * The {@link module:modules/realTimeData} module is required - * The module will fetch real-time data from Audigent - * @module modules/hadronRtdProvider - * @requires module:modules/realTimeData - */ -import {ajax} from '../src/ajax.js'; -import {config} from '../src/config.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {submodule} from '../src/hook.js'; -import {isFn, isStr, isArray, deepEqual, isPlainObject, logError} from '../src/utils.js'; - -const MODULE_NAME = 'realTimeData'; -const SUBMODULE_NAME = 'hadron'; -const AU_GVLID = 561; - -export const HALOID_LOCAL_NAME = 'auHadronId'; -export const RTD_LOCAL_NAME = 'auHadronRtd'; -export const storage = getStorageManager({gvlid: AU_GVLID, moduleName: SUBMODULE_NAME}); - -/** - * Deep set an object unless value present. - * @param {Object} obj - * @param {String} path - * @param {Object} val - */ -function set(obj, path, val) { - const keys = path.split('.'); - const lastKey = keys.pop(); - const lastObj = keys.reduce((obj, key) => obj[key] = obj[key] || {}, obj); - lastObj[lastKey] = lastObj[lastKey] || val; -} - -/** - * Deep object merging with array deduplication. - * @param {Object} target - * @param {Object} sources - */ -function mergeDeep(target, ...sources) { - if (!sources.length) return target; - const source = sources.shift(); - - if (isPlainObject(target) && isPlainObject(source)) { - for (const key in source) { - if (isPlainObject(source[key])) { - if (!target[key]) Object.assign(target, { [key]: {} }); - mergeDeep(target[key], source[key]); - } else if (isArray(source[key])) { - if (!target[key]) { - Object.assign(target, { [key]: source[key] }); - } else if (isArray(target[key])) { - source[key].forEach(obj => { - let e = 1; - for (let i = 0; i < target[key].length; i++) { - if (deepEqual(target[key][i], obj)) { - e = 0; - break; - } - } - if (e) { - target[key].push(obj); - } - }); - } - } else { - Object.assign(target, { [key]: source[key] }); - } - } - } - - return mergeDeep(target, ...sources); -} - -/** - * Lazy merge objects. - * @param {Object} target - * @param {Object} source - */ -function mergeLazy(target, source) { - if (!isPlainObject(target)) { - target = {}; - } - - if (!isPlainObject(source)) { - source = {}; - } - - return mergeDeep(target, source); -} - -/** - * Param or default. - * @param {String} param - * @param {String} defaultVal - */ -function paramOrDefault(param, defaultVal, arg) { - if (isFn(param)) { - return param(arg); - } else if (isStr(param)) { - return param; - } - return defaultVal; -} - -/** - * Add real-time data & merge segments. - * @param {Object} bidConfig - * @param {Object} rtd - * @param {Object} rtdConfig - */ -export function addRealTimeData(bidConfig, rtd, rtdConfig) { - if (rtdConfig.params && rtdConfig.params.handleRtd) { - rtdConfig.params.handleRtd(bidConfig, rtd, rtdConfig, config); - } else { - if (isPlainObject(rtd.ortb2)) { - let ortb2 = config.getConfig('ortb2') || {}; - config.setConfig({ortb2: mergeLazy(ortb2, rtd.ortb2)}); - } - - if (isPlainObject(rtd.ortb2b)) { - let bidderConfig = config.getBidderConfig(); - - Object.keys(rtd.ortb2b).forEach(bidder => { - let rtdOptions = rtd.ortb2b[bidder] || {}; - - let bidderOptions = {}; - if (isPlainObject(bidderConfig[bidder])) { - bidderOptions = bidderConfig[bidder]; - } - - config.setBidderConfig({ - bidders: [bidder], - config: mergeLazy(bidderOptions, rtdOptions) - }); - }); - } - } -} - -/** - * Real-time data retrieval from Audigent - * @param {Object} reqBidsConfigObj - * @param {function} onDone - * @param {Object} rtdConfig - * @param {Object} userConsent - */ -export function getRealTimeData(bidConfig, onDone, rtdConfig, userConsent) { - if (rtdConfig && isPlainObject(rtdConfig.params) && rtdConfig.params.segmentCache) { - let jsonData = storage.getDataFromLocalStorage(RTD_LOCAL_NAME); - - if (jsonData) { - let data = JSON.parse(jsonData); - - if (data.rtd) { - addRealTimeData(bidConfig, data.rtd, rtdConfig); - onDone(); - return; - } - } - } - - const userIds = (getGlobal()).getUserIds(); - - let hadronId = storage.getDataFromLocalStorage(HALOID_LOCAL_NAME); - if (isStr(hadronId)) { - (getGlobal()).refreshUserIds({submoduleNames: 'hadronId'}); - userIds.hadronId = hadronId; - getRealTimeDataAsync(bidConfig, onDone, rtdConfig, userConsent, userIds); - } else { - var script = document.createElement('script'); - script.type = 'text/javascript'; - - window.pubHadronCb = (hadronId) => { - userIds.hadronId = hadronId; - getRealTimeDataAsync(bidConfig, onDone, rtdConfig, userConsent, userIds); - } - - const hadronIdUrl = rtdConfig.params && rtdConfig.params.hadronIdUrl; - script.src = paramOrDefault(hadronIdUrl, 'https://id.hadron.ad.gt/api/v1/hadronid', userIds); - document.getElementsByTagName('head')[0].appendChild(script); - } -} - -/** - * Async rtd retrieval from Audigent - * @param {function} onDone - * @param {Object} rtdConfig - * @param {Object} userConsent - * @param {Object} userIds - */ -export function getRealTimeDataAsync(bidConfig, onDone, rtdConfig, userConsent, userIds) { - let reqParams = {}; - - if (isPlainObject(rtdConfig)) { - set(rtdConfig, 'params.requestParams.ortb2', config.getConfig('ortb2')); - reqParams = rtdConfig.params.requestParams; - } - - if (isPlainObject(window.pubHadronPm)) { - reqParams.pubHadronPm = window.pubHadronPm; - } - - const url = `https://seg.hadron.ad.gt/api/v1/rtd`; - ajax(url, { - success: function (response, req) { - if (req.status === 200) { - try { - const data = JSON.parse(response); - if (data && data.rtd) { - addRealTimeData(bidConfig, data.rtd, rtdConfig); - onDone(); - storage.setDataInLocalStorage(RTD_LOCAL_NAME, JSON.stringify(data)); - } else { - onDone(); - } - } catch (err) { - logError('unable to parse audigent segment data'); - onDone(); - } - } else if (req.status === 204) { - // unrecognized partner config - onDone(); - } - }, - error: function () { - onDone(); - logError('unable to get audigent segment data'); - } - }, - JSON.stringify({'userIds': userIds, 'config': reqParams}), - {contentType: 'application/json'} - ); -} - -/** - * Module init - * @param {Object} provider - * @param {Objkect} userConsent - * @return {boolean} - */ -function init(provider, userConsent) { - return true; -} - -/** @type {RtdSubmodule} */ -export const hadronSubmodule = { - name: SUBMODULE_NAME, - getBidRequestData: getRealTimeData, - init: init -}; - -submodule(MODULE_NAME, hadronSubmodule); diff --git a/modules/hadronRtdProvider.md b/modules/hadronRtdProvider.md deleted file mode 100644 index 0dbe9666230..00000000000 --- a/modules/hadronRtdProvider.md +++ /dev/null @@ -1,126 +0,0 @@ -## Audigent Hadron Real-time Data Submodule - -Audigent is a next-generation, 1st party data management platform and the -world’s first "data agency", powering the programmatic landscape and DTC -eCommerce with actionable 1st party audience and contextual data from the -world’s most influential retailers, lifestyle publishers, content creators, -athletes and artists. - -The Hadron real-time data module in Prebid has been built so that publishers -can maximize the power of their first-party audiences and contextual data. -This module provides both an integrated cookieless Hadron identity with real-time -contextual and audience segmentation solution that seamlessly and easily -integrates into your existing Prebid deployment. - -Users, devices, content, cohorts and other features are identified and utilized -to augment every bid request with targeted, 1st party data-derived segments -before being submitted to supply-side platforms. Enriching the bid request with -robust 1st party audience and contextual data, Audigent's Hadron RTD module -optimizes targeting, increases the number of bids, increases bid value, -and drives additional incremental revenue for publishers. - -### Publisher Usage - -Compile the Hadron RTD module into your Prebid build: - -`gulp build --modules=userId,unifiedIdSystem,rtdModule,hadronRtdProvider,appnexusBidAdapter` - -Add the Hadron RTD provider to your Prebid config. In this example we will configure -publisher 1234 to retrieve segments from Audigent. See the -"Parameter Descriptions" below for more detailed information of the -configuration parameters. Please work with your Audigent Prebid support team -(prebid@audigent.com) on which version of Prebid.js supports different bidder -and segment configurations. - -``` -pbjs.setConfig( - ... - realTimeData: { - auctionDelay: 5000, - dataProviders: [ - { - name: "hadron", - waitForIt: true, - params: { - segmentCache: false, - requestParams: { - publisherId: 1234 - } - } - } - ] - } - ... -} -``` - -### Parameter Descriptions for the Hadron Configuration Section - -| Name |Type | Description | Notes | -| :------------ | :------------ | :------------ |:------------ | -| name | String | Real time data module name | Always 'hadron' | -| waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false | -| params | Object | | | -| params.handleRtd | Function | A passable RTD handler that allows custom adunit and ortb2 logic to be configured. The function signature is (bidConfig, rtd, rtdConfig, pbConfig) => {}. | Optional | -| params.segmentCache | Boolean | This parameter tells the Hadron RTD module to attempt reading segments from a local storage cache instead of always requesting them from the Audigent server. | Optional. Defaults to false. | -| params.requestParams | Object | Publisher partner specific configuration options, such as optional publisher id and other segment query related metadata to be submitted to Audigent's backend with each request. Contact prebid@audigent.com for more information. | Optional | -| params.hadronIdUrl | String | Parameter to specify alternate hadronid endpoint url. | Optional | - -### Publisher Customized RTD Handling -As indicated above, it is possible to provide your own bid augmentation -functions rather than simply merging supplied data. This is useful if you -want to perform custom bid augmentation and logic with Hadron real-time data -prior to the bid request being sent. Simply add your custom logic to the -optional handleRtd parameter and provide your custom RTD handling logic there. - -Please see the following example, which provides a function to modify bids for -a bid adapter called adBuzz and perform custom logic on bidder parameters. - -``` -pbjs.setConfig( - ... - realTimeData: { - auctionDelay: auctionDelay, - dataProviders: [ - { - name: "hadron", - waitForIt: true, - params: { - handleRtd: function(bidConfig, rtd, rtdConfig, pbConfig) { - var adUnits = bidConfig.adUnits; - for (var i = 0; i < adUnits.length; i++) { - var adUnit = adUnits[i]; - for (var j = 0; j < adUnit.bids.length; j++) { - var bid = adUnit.bids[j]; - if (bid.bidder == 'adBuzz' && rtd['adBuzz'][0].value != 'excludeSeg') { - bid.params.adBuzzCustomSegments.push(rtd['adBuzz'][0].id); - } - } - } - }, - segmentCache: false, - requestParams: { - publisherId: 1234 - } - } - } - ] - } - ... -} -``` - -The handleRtd function can also be used to configure custom ortb2 data -processing. Please see the examples available in the hadronRtdProvider_spec.js -tests and work with your Audigent Prebid integration team (prebid@audigent.com) -on how to best configure your own Hadron RTD & Open RTB data handlers. - -### Testing - -To view an example of available segments returned by Audigent's backends: - -`gulp serve --modules=userId,unifiedIdSystem,rtdModule,hadronRtdProvider,appnexusBidAdapter` - -and then point your browser at: - -`http://localhost:9999/integrationExamples/gpt/hadronRtdProvider_example.html` diff --git a/modules/haloIdSystem.js b/modules/haloIdSystem.js index 2ce18e1e740..3011569a17d 100644 --- a/modules/haloIdSystem.js +++ b/modules/haloIdSystem.js @@ -8,12 +8,12 @@ import {ajax} from '../src/ajax.js'; import {getStorageManager} from '../src/storageManager.js'; import {submodule} from '../src/hook.js'; -import { isFn, isStr, isPlainObject, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; const MODULE_NAME = 'haloId'; const AU_GVLID = 561; -export const storage = getStorageManager({gvlid: AU_GVLID, moduleName: 'halo'}); +export const storage = getStorageManager(AU_GVLID, 'halo'); /** * Param or default. @@ -21,9 +21,9 @@ export const storage = getStorageManager({gvlid: AU_GVLID, moduleName: 'halo'}); * @param {String} defaultVal */ function paramOrDefault(param, defaultVal, arg) { - if (isFn(param)) { + if (utils.isFn(param)) { return param(arg); - } else if (isStr(param)) { + } else if (utils.isStr(param)) { return param; } return defaultVal; @@ -44,7 +44,7 @@ export const haloIdSubmodule = { */ decode(value) { let haloId = storage.getDataFromLocalStorage('auHaloId'); - if (isStr(haloId)) { + if (utils.isStr(haloId)) { return {haloId: haloId}; } return (value && typeof value['haloId'] === 'string') ? { 'haloId': value['haloId'] } : undefined; @@ -56,7 +56,7 @@ export const haloIdSubmodule = { * @returns {IdResponse|undefined} */ getId(config) { - if (!isPlainObject(config.params)) { + if (!utils.isPlainObject(config.params)) { config.params = {}; } const url = paramOrDefault(config.params.url, @@ -65,7 +65,7 @@ export const haloIdSubmodule = { const resp = function (callback) { let haloId = storage.getDataFromLocalStorage('auHaloId'); - if (isStr(haloId)) { + if (utils.isStr(haloId)) { const responseObj = {haloId: haloId}; callback(responseObj); } else { @@ -76,13 +76,13 @@ export const haloIdSubmodule = { try { responseObj = JSON.parse(response); } catch (error) { - logError(error); + utils.logError(error); } } callback(responseObj); }, error: error => { - logError(`${MODULE_NAME}: ID fetch encountered an error`, error); + utils.logError(`${MODULE_NAME}: ID fetch encountered an error`, error); callback(); } }; diff --git a/modules/haloIdSystem.md b/modules/haloIdSystem.md index 7c58aea3ec6..f740ae58048 100644 --- a/modules/haloIdSystem.md +++ b/modules/haloIdSystem.md @@ -1,4 +1,35 @@ -## Audigent Halo has been rebranded as Hadron -## Use the Hadron Id Submodule -## The Halo modules will be removed from Prebid 7 -## Contact prebid@audigent.com for more info. +## Audigent Halo User ID Submodule + +Audigent Halo ID Module. For assistance setting up your module please contact us at [prebid@audigent.com](prebid@audigent.com). + +### Prebid Params + +Individual params may be set for the Audigent Halo ID Submodule. At least one identifier must be set in the params. + +``` +pbjs.setConfig({ + usersync: { + userIds: [{ + name: 'haloId', + storage: { + name: 'haloId', + type: 'html5' + } + }] + } +}); +``` +## Parameter Descriptions for the `usersync` Configuration Section +The below parameters apply only to the HaloID User ID Module integration. + +| Param under usersync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | ID value for the HaloID module - `"haloId"` | `"haloId"` | +| storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | | +| storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` | +| storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"haloid"` | +| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. | `365` | +| value | Optional | Object | Used only if the page has a separate mechanism for storing the Halo ID. The value is an object containing the values to be sent to the adapters. In this scenario, no URL is called and nothing is added to local storage | `{"haloId": "eb33b0cb-8d35-4722-b9c0-1a31d4064888"}` | +| params | Optional | Object | Used to store params for the id system | +| params.url | Optional | String | Set an alternate GET url for HaloId with this parameter | +| params.urlArg | Optional | Object | Optional url parameter for params.url | diff --git a/modules/haloRtdProvider.js b/modules/haloRtdProvider.js index 1810bfb6f63..d889310a7c2 100644 --- a/modules/haloRtdProvider.js +++ b/modules/haloRtdProvider.js @@ -18,7 +18,7 @@ const AU_GVLID = 561; export const HALOID_LOCAL_NAME = 'auHaloId'; export const RTD_LOCAL_NAME = 'auHaloRtd'; -export const storage = getStorageManager({gvlid: AU_GVLID, moduleName: SUBMODULE_NAME}); +export const storage = getStorageManager(AU_GVLID, SUBMODULE_NAME); /** * Deep set an object unless value present. diff --git a/modules/haloRtdProvider.md b/modules/haloRtdProvider.md index 6ae5a3f75fa..4a264af9e2e 100644 --- a/modules/haloRtdProvider.md +++ b/modules/haloRtdProvider.md @@ -1,3 +1,126 @@ -## Audigent Halo has been rebranded as Hadron -## Use the Hadron Rtd Submodule -## The Halo modules will be removed from Prebid 7 \ No newline at end of file +## Audigent Halo Real-time Data Submodule + +Audigent is a next-generation, 1st party data management platform and the +world’s first "data agency", powering the programmatic landscape and DTC +eCommerce with actionable 1st party audience and contextual data from the +world’s most influential retailers, lifestyle publishers, content creators, +athletes and artists. + +The Halo real-time data module in Prebid has been built so that publishers +can maximize the power of their first-party audiences and contextual data. +This module provides both an integrated cookieless Halo identity with real-time +contextual and audience segmentation solution that seamlessly and easily +integrates into your existing Prebid deployment. + +Users, devices, content, cohorts and other features are identified and utilized +to augment every bid request with targeted, 1st party data-derived segments +before being submitted to supply-side platforms. Enriching the bid request with +robust 1st party audience and contextual data, Audigent's Halo RTD module +optimizes targeting, increases the number of bids, increases bid value, +and drives additional incremental revenue for publishers. + +### Publisher Usage + +Compile the Halo RTD module into your Prebid build: + +`gulp build --modules=userId,unifiedIdSystem,rtdModule,haloRtdProvider,appnexusBidAdapter` + +Add the Halo RTD provider to your Prebid config. In this example we will configure +publisher 1234 to retrieve segments from Audigent. See the +"Parameter Descriptions" below for more detailed information of the +configuration parameters. Please work with your Audigent Prebid support team +(prebid@audigent.com) on which version of Prebid.js supports different bidder +and segment configurations. + +``` +pbjs.setConfig( + ... + realTimeData: { + auctionDelay: 5000, + dataProviders: [ + { + name: "halo", + waitForIt: true, + params: { + segmentCache: false, + requestParams: { + publisherId: 1234 + } + } + } + ] + } + ... +} +``` + +### Parameter Descriptions for the Halo Configuration Section + +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| name | String | Real time data module name | Always 'halo' | +| waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false | +| params | Object | | | +| params.handleRtd | Function | A passable RTD handler that allows custom adunit and ortb2 logic to be configured. The function signature is (bidConfig, rtd, rtdConfig, pbConfig) => {}. | Optional | +| params.segmentCache | Boolean | This parameter tells the Halo RTD module to attempt reading segments from a local storage cache instead of always requesting them from the Audigent server. | Optional. Defaults to false. | +| params.requestParams | Object | Publisher partner specific configuration options, such as optional publisher id and other segment query related metadata to be submitted to Audigent's backend with each request. Contact prebid@audigent.com for more information. | Optional | +| params.haloIdUrl | String | Parameter to specify alternate haloid endpoint url. | Optional | + +### Publisher Customized RTD Handling +As indicated above, it is possible to provide your own bid augmentation +functions rather than simply merging supplied data. This is useful if you +want to perform custom bid augmentation and logic with Halo real-time data +prior to the bid request being sent. Simply add your custom logic to the +optional handleRtd parameter and provide your custom RTD handling logic there. + +Please see the following example, which provides a function to modify bids for +a bid adapter called adBuzz and perform custom logic on bidder parameters. + +``` +pbjs.setConfig( + ... + realTimeData: { + auctionDelay: auctionDelay, + dataProviders: [ + { + name: "halo", + waitForIt: true, + params: { + handleRtd: function(bidConfig, rtd, rtdConfig, pbConfig) { + var adUnits = bidConfig.adUnits; + for (var i = 0; i < adUnits.length; i++) { + var adUnit = adUnits[i]; + for (var j = 0; j < adUnit.bids.length; j++) { + var bid = adUnit.bids[j]; + if (bid.bidder == 'adBuzz' && rtd['adBuzz'][0].value != 'excludeSeg') { + bid.params.adBuzzCustomSegments.push(rtd['adBuzz'][0].id); + } + } + } + }, + segmentCache: false, + requestParams: { + publisherId: 1234 + } + } + } + ] + } + ... +} +``` + +The handleRtd function can also be used to configure custom ortb2 data +processing. Please see the examples available in the haloRtdProvider_spec.js +tests and work with your Audigent Prebid integration team (prebid@audigent.com) +on how to best configure your own Halo RTD & Open RTB data handlers. + +### Testing + +To view an example of available segments returned by Audigent's backends: + +`gulp serve --modules=userId,unifiedIdSystem,rtdModule,haloRtdProvider,appnexusBidAdapter` + +and then point your browser at: + +`http://localhost:9999/integrationExamples/gpt/haloRtdProvider_example.html` diff --git a/modules/hybridBidAdapter.js b/modules/hybridBidAdapter.js index 98fecf04d8d..15f8acd824f 100644 --- a/modules/hybridBidAdapter.js +++ b/modules/hybridBidAdapter.js @@ -1,9 +1,9 @@ -import {_map, deepAccess, isArray, logWarn} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {auctionManager} from '../src/auctionManager.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js' +import { registerBidder } from '../src/adapters/bidderFactory.js' +import { auctionManager } from '../src/auctionManager.js' +import { BANNER, VIDEO } from '../src/mediaTypes.js' import {Renderer} from '../src/Renderer.js'; -import {find} from '../src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; const BIDDER_CODE = 'hybrid'; const DSP_ENDPOINT = 'https://hbe198.hybrid.ai/prebidhb'; @@ -21,7 +21,7 @@ const placementTypes = { }; function buildBidRequests(validBidRequests) { - return _map(validBidRequests, function(validBidRequest) { + return utils._map(validBidRequests, function(validBidRequest) { const params = validBidRequest.params; const bidRequest = { bidId: validBidRequest.bidId, @@ -63,7 +63,7 @@ const createRenderer = (bid) => { try { renderer.setRender(outstreamRender); } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); + utils.logWarn('Prebid Error calling setRender on renderer', err); } return renderer; @@ -143,8 +143,8 @@ function hasVideoMandatoryParams(mediaTypes) { const isHasVideoContext = !!mediaTypes.video && (mediaTypes.video.context === 'instream' || mediaTypes.video.context === 'outstream'); const isPlayerSize = - !!deepAccess(mediaTypes, 'video.playerSize') && - isArray(deepAccess(mediaTypes, 'video.playerSize')); + !!utils.deepAccess(mediaTypes, 'video.playerSize') && + utils.isArray(utils.deepAccess(mediaTypes, 'video.playerSize')); return isHasVideoContext && isPlayerSize; } @@ -237,8 +237,8 @@ export const spec = { let bidRequests = JSON.parse(bidRequest.data).bidRequests; const serverBody = serverResponse.body; - if (serverBody && serverBody.bids && isArray(serverBody.bids)) { - return _map(serverBody.bids, function(bid) { + if (serverBody && serverBody.bids && utils.isArray(serverBody.bids)) { + return utils._map(serverBody.bids, function(bid) { let rawBid = find(bidRequests, function (item) { return item.bidId === bid.bidId; }); diff --git a/modules/iasRtdProvider.js b/modules/iasRtdProvider.js index 58899d7a8c0..bbd2529bf86 100644 --- a/modules/iasRtdProvider.js +++ b/modules/iasRtdProvider.js @@ -1,40 +1,11 @@ import { submodule } from '../src/hook.js'; -import * as utils from '../src/utils.js'; -import { ajax } from '../src/ajax.js'; import { getGlobal } from '../src/prebidGlobal.js'; +import * as utils from '../src/utils.js'; +import { ajaxBuilder } from '../src/ajax.js'; /** @type {string} */ const MODULE_NAME = 'realTimeData'; const SUBMODULE_NAME = 'ias'; -const IAS_HOST = 'https://pixel.adsafeprotected.com/services/pub'; -export let iasTargeting = {}; -const BRAND_SAFETY_OBJECT_FIELD_NAME = 'brandSafety'; -const FRAUD_FIELD_NAME = 'fr'; -const SLOTS_OBJECT_FIELD_NAME = 'slots'; -const CUSTOM_FIELD_NAME = 'custom'; -const IAS_KW = 'ias-kw'; -const IAS_KEY_MAPPINGS = { - adt: 'adt', - alc: 'alc', - dlm: 'dlm', - hat: 'hat', - off: 'off', - vio: 'vio', - drg: 'drg', - 'ias-kw': 'ias-kw', - fr: 'fr', - vw: 'vw', - grm: 'grm', - pub: 'pub', - vw05: 'vw05', - vw10: 'vw10', - vw15: 'vw15', - vw30: 'vw30', - vw_vv: 'vw_vv', - grm_vv: 'grm_vv', - pub_vv: 'pub_vv', - id: 'id' -}; /** * Module init @@ -43,19 +14,6 @@ const IAS_KEY_MAPPINGS = { * @return {boolean} */ export function init(config, userConsent) { - const params = config.params; - if (!params || !params.pubId) { - utils.logError('missing pubId param for IAS provider'); - return false; - } - if (params.hasOwnProperty('keyMappings')) { - const keyMappings = params.keyMappings; - for (let prop in keyMappings) { - if (IAS_KEY_MAPPINGS.hasOwnProperty(prop)) { - IAS_KEY_MAPPINGS[prop] = keyMappings[prop] - } - } - } return true; } @@ -72,11 +30,9 @@ function stringifySlotSizes(sizes) { } function stringifySlot(bidRequest) { - const sizes = utils.getAdUnitSizes(bidRequest); const id = bidRequest.code; - const ss = stringifySlotSizes(sizes); - const adSlot = utils.getGptSlotInfoForAdUnitCode(bidRequest.code); - const p = utils.isEmpty(adSlot) ? bidRequest.code : adSlot.gptSlot; + const ss = stringifySlotSizes(bidRequest.sizes); + const p = bidRequest.bids[0].params.adUnitPath; const slot = { id, ss, p }; const keyValues = utils.getKeys(slot).map(function (key) { return [key, slot[key]].join(':'); @@ -92,34 +48,31 @@ function stringifyScreenSize() { return [(window.screen && window.screen.width) || -1, (window.screen && window.screen.height) || -1].join('.'); } -function renameKeyValues(source) { +function getPageLevelKeywords(response) { let result = {}; - for (let prop in IAS_KEY_MAPPINGS) { - if (source.hasOwnProperty(prop)) { - result[IAS_KEY_MAPPINGS[prop]] = source[prop]; - } + if (response.brandSafety) { + shallowMerge(result, response.brandSafety); } + result.fr = response.fr; + result.custom = response.custom; return result; } -function formatTargetingData(adUnit) { - let result = {}; - if (iasTargeting[BRAND_SAFETY_OBJECT_FIELD_NAME]) { - utils.mergeDeep(result, iasTargeting[BRAND_SAFETY_OBJECT_FIELD_NAME]); - } - if (iasTargeting[FRAUD_FIELD_NAME]) { - result[FRAUD_FIELD_NAME] = iasTargeting[FRAUD_FIELD_NAME]; - } - if (iasTargeting[CUSTOM_FIELD_NAME] && IAS_KW in iasTargeting[CUSTOM_FIELD_NAME]) { - result[IAS_KW] = iasTargeting[CUSTOM_FIELD_NAME][IAS_KW]; - } - if (iasTargeting[SLOTS_OBJECT_FIELD_NAME] && adUnit in iasTargeting[SLOTS_OBJECT_FIELD_NAME]) { - utils.mergeDeep(result, iasTargeting[SLOTS_OBJECT_FIELD_NAME][adUnit]); - } - return renameKeyValues(result); +function shallowMerge(dest, src) { + utils.getKeys(src).reduce((dest, srcKey) => { + dest[srcKey] = src[srcKey]; + return dest; + }, dest); } -function constructQueryString(anId, adUnits) { +function getBidRequestData(reqBidsConfigObj, callback, config) { + const adUnits = reqBidsConfigObj.adUnits || getGlobal().adUnits; + + let isFinish = false; + + const IAS_HOST = 'https://pixel.adsafeprotected.com/services/pub'; + const { pubId } = config.params; + const anId = pubId; let queries = []; queries.push(['anId', anId]); @@ -132,69 +85,39 @@ function constructQueryString(anId, adUnits) { queries.push(['sr', stringifyScreenSize()]); queries.push(['url', encodeURIComponent(window.location.href)]); - return encodeURI(queries.map(qs => qs.join('=')).join('&')); -} - -function parseResponse(result) { - let iasResponse = {}; - try { - iasResponse = JSON.parse(result); - } catch (err) { - utils.logError('error', err); - } - iasTargeting = iasResponse; -} - -function getTargetingData(adUnits, config, userConsent) { - const targeting = {}; - try { - if (!utils.isEmpty(iasTargeting)) { - adUnits.forEach(function (adUnit) { - targeting[adUnit] = formatTargetingData(adUnit); - }); - } - } catch (err) { - utils.logError('error', err); - } - utils.logInfo('IAS targeting', targeting); - return targeting; -} - -export function getApiCallback() { - return { - success: function (response, req) { - if (req.status === 200) { - try { - parseResponse(response); - } catch (e) { - utils.logError('Unable to parse IAS response.', e); + const queryString = encodeURI(queries.map(qs => qs.join('=')).join('&')); + + const ajax = ajaxBuilder(); + + ajax(`${IAS_HOST}?${queryString}`, { + success: function (response, request) { + if (!isFinish) { + if (request.status === 200) { + const iasResponse = JSON.parse(response); + adUnits.forEach(adUnit => { + adUnit.bids.forEach(bid => { + const rtd = bid.rtd || {}; + const iasRtd = {}; + iasRtd[SUBMODULE_NAME] = Object.assign({}, rtd[SUBMODULE_NAME], getPageLevelKeywords(iasResponse)); + bid.rtd = Object.assign({}, rtd, iasRtd); + }); + }); } + isFinish = true; } + callback(); }, error: function () { - utils.logError('failed to retrieve IAS data'); + utils.logError('failed to retrieve targeting information'); + callback(); } - } -} - -function getBidRequestData(reqBidsConfigObj, callback, config, userConsent) { - const adUnits = reqBidsConfigObj.adUnits || getGlobal().adUnits; - const { pubId } = config.params; - const queryString = constructQueryString(pubId, adUnits); - ajax( - `${IAS_HOST}?${queryString}`, - getApiCallback(), - undefined, - { method: 'GET' } - ); - callback() + }); } /** @type {RtdSubmodule} */ export const iasSubModule = { name: SUBMODULE_NAME, init: init, - getTargetingData: getTargetingData, getBidRequestData: getBidRequestData }; diff --git a/modules/id5AnalyticsAdapter.js b/modules/id5AnalyticsAdapter.js index 69e303b520a..d2803aa3102 100644 --- a/modules/id5AnalyticsAdapter.js +++ b/modules/id5AnalyticsAdapter.js @@ -3,7 +3,7 @@ import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; import { ajax } from '../src/ajax.js'; import { logInfo, logError } from '../src/utils.js'; -import * as events from '../src/events.js'; +import events from '../src/events.js'; const { EVENTS: { diff --git a/modules/id5IdSystem.js b/modules/id5IdSystem.js index f2143c1cced..d2d64f52738 100644 --- a/modules/id5IdSystem.js +++ b/modules/id5IdSystem.js @@ -5,7 +5,7 @@ * @requires module:modules/userId */ -import { deepAccess, logInfo, deepSetValue, logError, isEmpty, isEmptyStr, logWarn } from '../src/utils.js'; +import * as utils from '../src/utils.js' import { ajax } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; import { getRefererInfo } from '../src/refererDetection.js'; @@ -24,7 +24,7 @@ const LOG_PREFIX = 'User ID - ID5 submodule: '; // cookie in the array is the most preferred to use const LEGACY_COOKIE_NAMES = [ 'pbjs-id5id', 'id5id.1st', 'id5id' ]; -const storage = getStorageManager({gvlid: GVLID, moduleName: MODULE_NAME}); +const storage = getStorageManager(GVLID, MODULE_NAME); /** @type {Submodule} */ export const id5IdSubmodule = { @@ -67,25 +67,25 @@ export const id5IdSubmodule = { } }; - const abTestingResult = deepAccess(value, 'ab_testing.result'); + const abTestingResult = utils.deepAccess(value, 'ab_testing.result'); switch (abTestingResult) { case 'control': // A/B Testing is enabled and user is in the Control Group - logInfo(LOG_PREFIX + 'A/B Testing - user is in the Control Group: ID5 ID is NOT exposed'); - deepSetValue(responseObj, 'id5id.ext.abTestingControlGroup', true); + utils.logInfo(LOG_PREFIX + 'A/B Testing - user is in the Control Group: ID5 ID is NOT exposed'); + utils.deepSetValue(responseObj, 'id5id.ext.abTestingControlGroup', true); break; case 'error': // A/B Testing is enabled, but configured improperly, so skip A/B testing - logError(LOG_PREFIX + 'A/B Testing ERROR! controlGroupPct must be a number >= 0 and <= 1'); + utils.logError(LOG_PREFIX + 'A/B Testing ERROR! controlGroupPct must be a number >= 0 and <= 1'); break; case 'normal': // A/B Testing is enabled but user is not in the Control Group, so ID5 ID is shared - logInfo(LOG_PREFIX + 'A/B Testing - user is NOT in the Control Group'); - deepSetValue(responseObj, 'id5id.ext.abTestingControlGroup', false); + utils.logInfo(LOG_PREFIX + 'A/B Testing - user is NOT in the Control Group'); + utils.deepSetValue(responseObj, 'id5id.ext.abTestingControlGroup', false); break; } - logInfo(LOG_PREFIX + 'Decoded ID', responseObj); + utils.logInfo(LOG_PREFIX + 'Decoded ID', responseObj); return responseObj; }, @@ -120,19 +120,19 @@ export const id5IdSubmodule = { }; // pass in optional data, but only if populated - if (hasGdpr && typeof consentData.consentString !== 'undefined' && !isEmpty(consentData.consentString) && !isEmptyStr(consentData.consentString)) { + if (hasGdpr && typeof consentData.consentString !== 'undefined' && !utils.isEmpty(consentData.consentString) && !utils.isEmptyStr(consentData.consentString)) { data.gdpr_consent = consentData.consentString; } - if (typeof usp !== 'undefined' && !isEmpty(usp) && !isEmptyStr(usp)) { + if (typeof usp !== 'undefined' && !utils.isEmpty(usp) && !utils.isEmptyStr(usp)) { data.us_privacy = usp; } - if (typeof signature !== 'undefined' && !isEmptyStr(signature)) { + if (typeof signature !== 'undefined' && !utils.isEmptyStr(signature)) { data.s = signature; } - if (typeof config.params.pd !== 'undefined' && !isEmptyStr(config.params.pd)) { + if (typeof config.params.pd !== 'undefined' && !utils.isEmptyStr(config.params.pd)) { data.pd = config.params.pd; } - if (typeof config.params.provider !== 'undefined' && !isEmptyStr(config.params.provider)) { + if (typeof config.params.provider !== 'undefined' && !utils.isEmptyStr(config.params.provider)) { data.provider = config.params.provider; } @@ -151,7 +151,7 @@ export const id5IdSubmodule = { if (response) { try { responseObj = JSON.parse(response); - logInfo(LOG_PREFIX + 'response received from the server', responseObj); + utils.logInfo(LOG_PREFIX + 'response received from the server', responseObj); resetNb(config.params.partner); @@ -165,17 +165,17 @@ export const id5IdSubmodule = { removeLegacyCookies(config.params.partner); } } catch (error) { - logError(LOG_PREFIX + error); + utils.logError(LOG_PREFIX + error); } } callback(responseObj); }, error: error => { - logError(LOG_PREFIX + 'getId fetch encountered an error', error); + utils.logError(LOG_PREFIX + 'getId fetch encountered an error', error); callback(); } }; - logInfo(LOG_PREFIX + 'requesting an ID from the server', data); + utils.logInfo(LOG_PREFIX + 'requesting an ID from the server', data); ajax(url, callbacks, JSON.stringify(data), { method: 'POST', withCredentials: true }); }; return { callback: resp }; @@ -198,29 +198,29 @@ export const id5IdSubmodule = { const partnerId = (config && config.params && config.params.partner) || 0; incrementNb(partnerId); - logInfo(LOG_PREFIX + 'using cached ID', cacheIdObj); + utils.logInfo(LOG_PREFIX + 'using cached ID', cacheIdObj); return cacheIdObj; } }; function hasRequiredConfig(config) { if (!config || !config.params || !config.params.partner || typeof config.params.partner !== 'number') { - logError(LOG_PREFIX + 'partner required to be defined as a number'); + utils.logError(LOG_PREFIX + 'partner required to be defined as a number'); return false; } if (!config.storage || !config.storage.type || !config.storage.name) { - logError(LOG_PREFIX + 'storage required to be set'); + utils.logError(LOG_PREFIX + 'storage required to be set'); return false; } // in a future release, we may return false if storage type or name are not set as required if (config.storage.type !== LOCAL_STORAGE) { - logWarn(LOG_PREFIX + `storage type recommended to be '${LOCAL_STORAGE}'. In a future release this may become a strict requirement`); + utils.logWarn(LOG_PREFIX + `storage type recommended to be '${LOCAL_STORAGE}'. In a future release this may become a strict requirement`); } // in a future release, we may return false if storage type or name are not set as required if (config.storage.name !== ID5_STORAGE_NAME) { - logWarn(LOG_PREFIX + `storage name recommended to be '${ID5_STORAGE_NAME}'. In a future release this may become a strict requirement`); + utils.logWarn(LOG_PREFIX + `storage name recommended to be '${ID5_STORAGE_NAME}'. In a future release this may become a strict requirement`); } return true; @@ -265,7 +265,7 @@ function getLegacyCookieSignature() { * @param {integer} partnerId */ function removeLegacyCookies(partnerId) { - logInfo(LOG_PREFIX + 'removing legacy cookies'); + utils.logInfo(LOG_PREFIX + 'removing legacy cookies'); LEGACY_COOKIE_NAMES.forEach(function(cookie) { storage.setCookie(`${cookie}`, ' ', expDaysStr(-1)); storage.setCookie(`${cookie}_nb`, ' ', expDaysStr(-1)); @@ -313,7 +313,7 @@ export function storeInLocalStorage(key, value, expDays) { * @returns {Object} an object which always contains at least the property "enabled" */ function getAbTestingConfig(config) { - return deepAccess(config, 'params.abTesting', { enabled: false }); + return utils.deepAccess(config, 'params.abTesting', { enabled: false }); } submodule('userId', id5IdSubmodule); diff --git a/modules/id5IdSystem.md b/modules/id5IdSystem.md index 11f8ffc5609..8ffe29e091f 100644 --- a/modules/id5IdSystem.md +++ b/modules/id5IdSystem.md @@ -1,14 +1,14 @@ # ID5 Universal ID -The ID5 ID is a shared, neutral identifier that publishers and ad tech platforms can use to recognise users even in environments where 3rd party cookies are not available. The ID5 ID is designed to respect users' privacy choices and publishers’ preferences throughout the advertising value chain. For more information about the ID5 ID and detailed integration docs, please visit [our documentation](https://support.id5.io/portal/en/kb/articles/prebid-js-user-id-module). +The ID5 Universal ID is a shared, neutral identifier that publishers and ad tech platforms can use to recognise users even in environments where 3rd party cookies are not available. The ID5 Universal ID is designed to respect users' privacy choices and publishers’ preferences throughout the advertising value chain. For more information about the ID5 Universal ID and detailed integration docs, please visit [our documentation](https://support.id5.io/portal/en/kb/articles/prebid-js-user-id-module). We also recommend that you sign up for our [release notes](https://id5.io/universal-id/release-notes) to stay up-to-date with any changes to the implementation of the ID5 Universal ID in Prebid. -## ID5 ID Registration +## ID5 Universal ID Registration -The ID5 ID is free to use, but requires a simple registration with ID5. Please visit [our website](https://id5.io/solutions/#publishers) to sign up and request your ID5 Partner Number to get started. +The ID5 Universal ID is free to use, but requires a simple registration with ID5. Please visit [id5.io/universal-id](https://id5.io/universal-id) to sign up and request your ID5 Partner Number to get started. -The ID5 privacy policy is at [https://id5.io/platform-privacy-policy](https://id5.io/platform-privacy-policy). +The ID5 privacy policy is at [https://www.id5.io/platform-privacy-policy](https://www.id5.io/platform-privacy-policy). -## ID5 ID Configuration +## ID5 Universal ID Configuration First, make sure to add the ID5 submodule to your Prebid.js package with: @@ -46,7 +46,7 @@ pbjs.setConfig({ | Param under userSync.userIds[] | Scope | Type | Description | Example | | --- | --- | --- | --- | --- | | name | Required | String | The name of this module: `"id5Id"` | `"id5Id"` | -| params | Required | Object | Details for the ID5 ID. | | +| params | Required | Object | Details for the ID5 Universal ID. | | | params.partner | Required | Number | This is the ID5 Partner Number obtained from registering with ID5. | `173` | | params.pd | Optional | String | Partner-supplied data used for linking ID5 IDs across domains. See [our documentation](https://support.id5.io/portal/en/kb/articles/passing-partner-data-to-id5) for details on generating the string. Omit the parameter or leave as an empty string if no data to supply | `"MT1iNTBjY..."` | | params.provider | Optional | String | An identifier provided by ID5 to technology partners who manage Prebid setups on behalf of publishers. Reach out to [ID5](mailto:prebid@id5.io) if you have questions about this parameter | `pubmatic-identity-hub` | diff --git a/modules/idImportLibrary.js b/modules/idImportLibrary.js index e1847edfce4..2a3a86cf270 100644 --- a/modules/idImportLibrary.js +++ b/modules/idImportLibrary.js @@ -1,7 +1,7 @@ -import { logInfo, logError } from '../src/utils.js'; import {getGlobal} from '../src/prebidGlobal.js'; import {ajax} from '../src/ajax.js'; import {config} from '../src/config.js'; +import * as utils from '../src/utils.js'; import MD5 from 'crypto-js/md5.js'; let email; @@ -9,7 +9,6 @@ let conf; const LOG_PRE_FIX = 'ID-Library: '; const CONF_DEFAULT_OBSERVER_DEBOUNCE_MS = 250; const CONF_DEFAULT_FULL_BODY_SCAN = false; -const CONF_DEFAULT_INPUT_SCAN = false; const OBSERVER_CONFIG = { subtree: true, attributes: true, @@ -19,18 +18,18 @@ const OBSERVER_CONFIG = { characterData: true, characterDataOldValue: false }; -const _logInfo = createLogInfo(LOG_PRE_FIX); -const _logError = createLogError(LOG_PRE_FIX); +const logInfo = createLogInfo(LOG_PRE_FIX); +const logError = createLogError(LOG_PRE_FIX); function createLogInfo(prefix) { return function (...strings) { - logInfo(prefix + ' ', ...strings); + utils.logInfo(prefix + ' ', ...strings); } } function createLogError(prefix) { return function (...strings) { - logError(prefix + ' ', ...strings); + utils.logError(prefix + ' ', ...strings); } } @@ -39,39 +38,39 @@ function getEmail(value) { if (!matched) { return null; } - _logInfo('Email found: ' + matched[0]); + logInfo('Email found: ' + matched[0]); return matched[0]; } function bodyAction(mutations, observer) { - _logInfo('BODY observer on debounce called'); + logInfo('BODY observer on debounce called'); // If the email is found in the input element, disconnect the observer if (email) { observer.disconnect(); - _logInfo('Email is found, body observer disconnected'); + logInfo('Email is found, body observer disconnected'); return; } const body = document.body.innerHTML; email = getEmail(body); if (email !== null) { - _logInfo(`Email obtained from the body ${email}`); + logInfo(`Email obtained from the body ${email}`); observer.disconnect(); - _logInfo('Post data on email found in body'); + logInfo('Post data on email found in body'); postData(); } } function targetAction(mutations, observer) { - _logInfo('Target observer called'); + logInfo('Target observer called'); for (const mutation of mutations) { for (const node of mutation.addedNodes) { email = node.textContent; if (email) { - _logInfo('Email obtained from the target ' + email); + logInfo('Email obtained from the target ' + email); observer.disconnect(); - _logInfo('Post data on email found in target'); + logInfo('Post data on email found in target'); postData(); return; } @@ -79,38 +78,19 @@ function targetAction(mutations, observer) { } } -function addInputElementsElementListner() { - if (doesInputElementsHaveEmail()) { - _logInfo('Email found in input elements ' + email); - _logInfo('Post data on email found in target without'); - postData(); - return; - } - _logInfo('Adding input element listeners'); +function addInputElementsElementListner(conf) { + logInfo('Adding input element listeners'); const inputs = document.querySelectorAll('input[type=text], input[type=email]'); for (var i = 0; i < inputs.length; i++) { - _logInfo(`Original Value in Input = ${inputs[i].value}`); + logInfo(`Original Value in Input = ${inputs[i].value}`); inputs[i].addEventListener('change', event => processInputChange(event)); inputs[i].addEventListener('blur', event => processInputChange(event)); } } -function addFormInputElementsElementListner(id) { - _logInfo('Adding input element listeners'); - if (doesFormInputElementsHaveEmail(id)) { - _logInfo('Email found in input elements ' + email); - postData(); - return; - } - _logInfo('Adding input element listeners'); - const input = document.getElementById(id); - input.addEventListener('change', event => processInputChange(event)); - input.addEventListener('blur', event => processInputChange(event)); -} - function removeInputElementsElementListner() { - _logInfo('Removing input element listeners'); + logInfo('Removing input element listeners'); const inputs = document.querySelectorAll('input[type=text], input[type=email]'); for (var i = 0; i < inputs.length; i++) { @@ -121,10 +101,10 @@ function removeInputElementsElementListner() { function processInputChange(event) { const value = event.target.value; - _logInfo(`Modified Value of input ${event.target.value}`); + logInfo(`Modified Value of input ${event.target.value}`); email = getEmail(value); if (email !== null) { - _logInfo('Email found in input ' + email); + logInfo('Email found in input ' + email); postData(); removeInputElementsElementListner(); } @@ -144,7 +124,7 @@ function debounce(func, wait, immediate) { if (callNow) { func.apply(context, args); } else { - _logInfo('Debounce wait time ' + wait); + logInfo('Debounce wait time ' + wait); timeout = setTimeout(later, wait); } }; @@ -158,25 +138,31 @@ function handleTargetElement() { email = targetElement.innerText; if (!email) { - _logInfo('Finding the email with observer'); + logInfo('Finding the email with observer'); targetObserver.observe(targetElement, OBSERVER_CONFIG); } else { - _logInfo('Target found with target ' + email); - _logInfo('Post data on email found in target with target'); + logInfo('Target found with target ' + email); + logInfo('Post data on email found in target with target'); postData(); } } } function handleBodyElements() { + if (doesInputElementsHaveEmail()) { + logInfo('Email found in input elements ' + email); + logInfo('Post data on email found in target without'); + postData(); + return; + } email = getEmail(document.body.innerHTML); if (email !== null) { - _logInfo('Email found in body ' + email); - _logInfo('Post data on email found in the body without observer'); + logInfo('Email found in body ' + email); + logInfo('Post data on email found in the body without observer'); postData(); return; } - + addInputElementsElementListner(); if (conf.fullscan === true) { const bodyObserver = new MutationObserver(debounce(bodyAction, conf.debounce, false)); bodyObserver.observe(document.body, OBSERVER_CONFIG); @@ -196,24 +182,13 @@ function doesInputElementsHaveEmail() { return false; } -function doesFormInputElementsHaveEmail(formElementId) { - const input = document.getElementById(formElementId); - if (input) { - email = getEmail(input.value); - if (email !== null) { - return true; - } - } - return false; -} - function syncCallback() { return { success: function () { - _logInfo('Data synced successfully.'); + logInfo('Data synced successfully.'); }, error: function () { - _logInfo('Data sync failed.'); + logInfo('Data sync failed.'); } } } @@ -222,15 +197,15 @@ function postData() { (getGlobal()).refreshUserIds(); const userIds = (getGlobal()).getUserIds(); if (Object.keys(userIds).length === 0) { - _logInfo('No user ids'); + logInfo('No user ids'); return; } - _logInfo('Users' + userIds); + logInfo('Users' + userIds); const syncPayload = {}; syncPayload.hid = MD5(email).toString(); syncPayload.uids = userIds; const payloadString = JSON.stringify(syncPayload); - _logInfo(payloadString); + logInfo(payloadString); ajax(conf.url, syncCallback(), payloadString, {method: 'POST', withCredentials: true}); } @@ -238,10 +213,6 @@ function associateIds() { if (window.MutationObserver || window.WebKitMutationObserver) { if (conf.target) { handleTargetElement(); - } else if (conf.formElementId) { - addFormInputElementsElementListner(conf.formElementId); - } else if (conf.inputscan) { - addInputElementsElementListner(); } else { handleBodyElements(); } @@ -250,28 +221,20 @@ function associateIds() { export function setConfig(config) { if (!config) { - _logError('Required confirguration not provided'); + logError('Required confirguration not provided'); return; } if (!config.url) { - _logError('The required url is not configured'); + logError('The required url is not configured'); return; } if (typeof config.debounce !== 'number') { config.debounce = CONF_DEFAULT_OBSERVER_DEBOUNCE_MS; - _logInfo('Set default observer debounce to ' + CONF_DEFAULT_OBSERVER_DEBOUNCE_MS); + logInfo('Set default observer debounce to ' + CONF_DEFAULT_OBSERVER_DEBOUNCE_MS); } if (typeof config.fullscan !== 'boolean') { config.fullscan = CONF_DEFAULT_FULL_BODY_SCAN; - _logInfo('Set default fullscan ' + CONF_DEFAULT_FULL_BODY_SCAN); - } - if (typeof config.inputscan !== 'boolean') { - config.inputscan = CONF_DEFAULT_INPUT_SCAN; - _logInfo('Set default input scan ' + CONF_DEFAULT_INPUT_SCAN); - } - - if (typeof config.formElementId == 'string') { - _logInfo('Looking for formElementId ' + config.formElementId); + logInfo('Set default fullscan ' + CONF_DEFAULT_FULL_BODY_SCAN); } conf = config; associateIds(); diff --git a/modules/idImportLibrary.md b/modules/idImportLibrary.md index f91ca984bb3..3dd78ee25d8 100644 --- a/modules/idImportLibrary.md +++ b/modules/idImportLibrary.md @@ -8,8 +8,6 @@ | `url` | Yes | String | N/A | URL endpoint used to post the hashed email and user IDs. | | `debounce` | No | Number | 250 | Time in milliseconds before the email and IDs are fetched. | | `fullscan` | No | Boolean | false | Enable/disable a full page body scan to get email. | -| `formElementId` | No | String | N/A | ID attribute of the input (type=text/email) from which the email can be read. | -| `inputscan` | No | Boolean | N/A | Enable/disable a input element (type=text/email) scan to get email. | ## Example @@ -20,7 +18,5 @@ pbjs.setConfig({ url: 'https://example.com', debounce: 250, fullscan: false, - inputscan: false, - formElementId: "userid" }, }); diff --git a/modules/idWardRtdProvider.js b/modules/idWardRtdProvider.js deleted file mode 100644 index a130d3cc8d2..00000000000 --- a/modules/idWardRtdProvider.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * This module adds the ID Ward RTD provider to the real time data module - * The {@link module:modules/realTimeData} module is required - * The module will poulate real-time data from ID Ward - * @module modules/idWardRtdProvider - * @requires module:modules/realTimeData - */ -import {config} from '../src/config.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {submodule} from '../src/hook.js'; -import {isPlainObject, mergeDeep, logMessage, logError} from '../src/utils.js'; - -const MODULE_NAME = 'realTimeData'; -const SUBMODULE_NAME = 'idWard'; - -export const storage = getStorageManager({moduleName: SUBMODULE_NAME}); -/** - * Add real-time data & merge segments. - * @param {Object} rtd - */ -function addRealTimeData(rtd) { - if (isPlainObject(rtd.ortb2)) { - const ortb2 = config.getConfig('ortb2') || {}; - logMessage('idWardRtdProvider: merging original: ', ortb2); - logMessage('idWardRtdProvider: merging in: ', rtd.ortb2); - config.setConfig({ortb2: mergeDeep(ortb2, rtd.ortb2)}); - } -} - -/** - * Try parsing stringified array of segment IDs. - * @param {String} data - */ -function tryParse(data) { - try { - return JSON.parse(data); - } catch (err) { - logError(`idWardRtdProvider: failed to parse json:`, data); - return null; - } -} - -/** - * Real-time data retrieval from ID Ward - * @param {Object} reqBidsConfigObj - * @param {function} onDone - * @param {Object} rtdConfig - * @param {Object} userConsent - */ -export function getRealTimeData(reqBidsConfigObj, onDone, rtdConfig, userConsent) { - if (rtdConfig && isPlainObject(rtdConfig.params)) { - const jsonData = storage.getDataFromLocalStorage(rtdConfig.params.cohortStorageKey) - - if (!jsonData) { - return; - } - - const segments = tryParse(jsonData); - - if (segments) { - const udSegment = { - name: 'id-ward.com', - ext: { - segtax: rtdConfig.params.segtax - }, - segment: segments.map(x => ({id: x})) - } - - logMessage('idWardRtdProvider: user.data.segment: ', udSegment); - const data = { - rtd: { - ortb2: { - user: { - data: [ - udSegment - ] - } - } - } - }; - addRealTimeData(data.rtd); - onDone(); - } - } -} - -/** - * Module init - * @param {Object} provider - * @param {Object} userConsent - * @return {boolean} - */ -function init(provider, userConsent) { - return true; -} - -/** @type {RtdSubmodule} */ -export const idWardRtdSubmodule = { - name: SUBMODULE_NAME, - getBidRequestData: getRealTimeData, - init: init -}; - -submodule(MODULE_NAME, idWardRtdSubmodule); diff --git a/modules/idWardRtdProvider.md b/modules/idWardRtdProvider.md deleted file mode 100644 index 5a44bfa49f3..00000000000 --- a/modules/idWardRtdProvider.md +++ /dev/null @@ -1,44 +0,0 @@ -### Overview - -ID Ward is a data anonymization technology for privacy-preserving advertising. Publishers and advertisers are able to target and retarget custom audience segments covering 100% of consented audiences. -ID Ward’s Real-time Data Provider automatically obtains segment IDs from the ID Ward on-domain script (via localStorage) and passes them to the bid-stream. - -### Integration - - 1) Build the idWardRtd module into the Prebid.js package with: - - ``` - gulp build --modules=idWardRtdProvider,... - ``` - - 2) Use `setConfig` to instruct Prebid.js to initilaize the idWardRtdProvider module, as specified below. - -### Configuration - -``` - pbjs.setConfig({ - realTimeData: { - dataProviders: [ - { - name: "idWard", - waitForIt: true, - params: { - cohortStorageKey: "cohort_ids", - segtax: , - } - } - ] - } - }); - ``` - -Please note that idWardRtdProvider should be integrated into the publisher website along with the [ID Ward Pixel](https://publishers-web.id-ward.com/pixel-integration). -Please reach out to Id Ward representative(support@id-ward.com) if you have any questions or need further help to integrate Prebid, idWardRtdProvider, and Id Ward Pixel - -### Testing -To view an example of available segments returned by Id Ward: -``` -‘gulp serve --modules=rtdModule,idWardRtdProvider,pubmaticBidAdapter -``` -and then point your browser at: -"http://localhost:9999/integrationExamples/gpt/idward_segments_example.html" diff --git a/modules/idxIdSystem.js b/modules/idxIdSystem.js index 908edad4c04..00e8a8bc5e5 100644 --- a/modules/idxIdSystem.js +++ b/modules/idxIdSystem.js @@ -4,7 +4,7 @@ * @module modules/idxIdSystem * @requires module:modules/userId */ -import { isStr, isPlainObject, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js' import { submodule } from '../src/hook.js'; import { getStorageManager } from '../src/storageManager.js'; @@ -34,7 +34,7 @@ export const idxIdSubmodule = { * @return { Object | string | undefined } */ decode(value) { - const idxVal = value ? isStr(value) ? value : isPlainObject(value) ? value.id : undefined : undefined; + const idxVal = value ? utils.isStr(value) ? value : utils.isPlainObject(value) ? value.id : undefined : undefined; return idxVal ? { 'idx': idxVal } : undefined; @@ -52,7 +52,7 @@ export const idxIdSubmodule = { const idxObj = JSON.parse(idxString); return idxObj && idxObj.idx ? { id: idxObj.idx } : undefined; } catch (error) { - logError(error); + utils.logError(error); } } return undefined; diff --git a/modules/imRtdProvider.js b/modules/imRtdProvider.js deleted file mode 100644 index 6c582df3df3..00000000000 --- a/modules/imRtdProvider.js +++ /dev/null @@ -1,238 +0,0 @@ -/** - * The {@link module:modules/realTimeData} module is required - * The module will fetch real-time data from Intimate Merger - * @module modules/imRtdProvider - * @requires module:modules/realTimeData - */ -import {ajax} from '../src/ajax.js'; -import {config} from '../src/config.js'; -import {getGlobal} from '../src/prebidGlobal.js' -import {getStorageManager} from '../src/storageManager.js'; -import { - deepSetValue, - deepAccess, - timestamp, - mergeDeep, - logError, - logInfo, - isFn -} from '../src/utils.js' -import {submodule} from '../src/hook.js'; - -export const imUidLocalName = '__im_uid'; -export const imVidCookieName = '_im_vid'; -export const imRtdLocalName = '__im_sids'; -export const storage = getStorageManager(); -const submoduleName = 'im'; -const segmentsMaxAge = 3600000; // 1 hour (30 * 60 * 1000) -const uidMaxAge = 1800000; // 30 minites (30 * 60 * 1000) -const vidMaxAge = 97200000000; // 37 months ((365 * 3 + 30) * 24 * 60 * 60 * 1000) - -function setImDataInCookie(value) { - storage.setCookie( - imVidCookieName, - value, - new Date(timestamp() + vidMaxAge).toUTCString(), - 'none' - ); -} - -/** -* @param {string} bidderName -*/ -export function getBidderFunction(bidderName) { - const biddersFunction = { - ix: function (bid, data) { - if (data.im_segments && data.im_segments.length) { - config.setConfig({ - ix: {firstPartyData: {im_segments: data.im_segments}}, - }); - } - return bid - }, - pubmatic: function (bid, data) { - if (data.im_segments && data.im_segments.length) { - const dctr = deepAccess(bid, 'params.dctr'); - deepSetValue( - bid, - 'params.dctr', - `${dctr ? dctr + '|' : ''}im_segments=${data.im_segments.join(',')}` - ); - } - return bid - }, - fluct: function (bid, data) { - if (data.im_segments && data.im_segments.length) { - deepSetValue( - bid, - 'params.kv.imsids', - data.im_segments - ); - } - return bid - } - } - return biddersFunction[bidderName] || null; -} - -export function getCustomBidderFunction(config, bidder) { - const overwriteFn = deepAccess(config, `params.overwrites.${bidder}`) - - if (overwriteFn && isFn(overwriteFn)) { - return overwriteFn - } else { - return null - } -} - -/** - * Add real-time data. - * @param {Object} bidConfig - * @param {Object} moduleConfig - * @param {Object} data - */ -export function setRealTimeData(bidConfig, moduleConfig, data) { - const adUnits = bidConfig.adUnits || getGlobal().adUnits; - const utils = {deepSetValue, deepAccess, logInfo, logError, mergeDeep}; - - if (data.im_segments) { - const ortb2 = config.getConfig('ortb2') || {}; - deepSetValue(ortb2, 'user.ext.data.im_segments', data.im_segments); - config.setConfig({ortb2: ortb2}); - - if (moduleConfig.params.setGptKeyValues || !moduleConfig.params.hasOwnProperty('setGptKeyValues')) { - window.googletag = window.googletag || {cmd: []}; - window.googletag.cmd = window.googletag.cmd || []; - window.googletag.cmd.push(() => { - window.googletag.pubads().setTargeting('im_segments', data.im_segments); - }); - } - } - - adUnits.forEach(adUnit => { - adUnit.bids.forEach(bid => { - const bidderFunction = getBidderFunction(bid.bidder); - const overwriteFunction = getCustomBidderFunction(moduleConfig, bid.bidder); - if (overwriteFunction) { - overwriteFunction(bid, data, utils, config); - } else if (bidderFunction) { - bidderFunction(bid, data); - } - }) - }); -} - -/** - * Real-time data retrieval from Intimate Merger - * @param {Object} reqBidsConfigObj - * @param {function} onDone - * @param {Object} moduleConfig - */ -export function getRealTimeData(reqBidsConfigObj, onDone, moduleConfig) { - const cid = deepAccess(moduleConfig, 'params.cid'); - if (!cid) { - logError('imRtdProvider requires a valid cid to be defined'); - onDone(); - return; - } - const sids = storage.getDataFromLocalStorage(imRtdLocalName); - const parsedSids = sids ? sids.split(',') : []; - const mt = storage.getDataFromLocalStorage(`${imRtdLocalName}_mt`); - const localVid = storage.getCookie(imVidCookieName); - let apiUrl = `https://sync6.im-apps.net/${cid}/rtd`; - let expired = true; - let alreadyDone = false; - - if (localVid) { - apiUrl += `?vid=${localVid}`; - setImDataInCookie(localVid); - } - - if (Date.parse(mt) && Date.now() - (new Date(mt)).getTime() < segmentsMaxAge) { - expired = false; - } - - if (sids !== null) { - setRealTimeData(reqBidsConfigObj, moduleConfig, {im_segments: parsedSids}); - onDone(); - alreadyDone = true; - } - - if (expired) { - ajax( - apiUrl, - getApiCallback(reqBidsConfigObj, alreadyDone ? undefined : onDone, moduleConfig), - undefined, - {method: 'GET', withCredentials: true} - ); - } -} - -/** - * Api callback from Intimate Merger - * @param {Object} reqBidsConfigObj - * @param {function} onDone - * @param {Object} moduleConfig - */ -export function getApiCallback(reqBidsConfigObj, onDone, moduleConfig) { - return { - success: function (response, req) { - let parsedResponse = {}; - if (req.status === 200) { - try { - parsedResponse = JSON.parse(response); - } catch (e) { - logError('unable to get Intimate Merger segment data'); - } - - if (parsedResponse.uid) { - const imuid = storage.getDataFromLocalStorage(imUidLocalName); - const imuidMt = storage.getDataFromLocalStorage(`${imUidLocalName}_mt`); - const imuidExpired = Date.parse(imuidMt) && Date.now() - (new Date(imuidMt)).getTime() < uidMaxAge; - if (!imuid || imuidExpired) { - storage.setDataInLocalStorage(imUidLocalName, parsedResponse.uid); - storage.setDataInLocalStorage(`${imUidLocalName}_mt`, new Date(timestamp()).toUTCString()); - } - } - - if (parsedResponse.vid) { - setImDataInCookie(parsedResponse.vid); - } - - if (parsedResponse.segments) { - setRealTimeData(reqBidsConfigObj, moduleConfig, {im_segments: parsedResponse.segments}); - storage.setDataInLocalStorage(imRtdLocalName, parsedResponse.segments); - storage.setDataInLocalStorage(`${imRtdLocalName}_mt`, new Date(timestamp()).toUTCString()); - } - } - if (onDone) { - onDone(); - } - }, - error: function () { - if (onDone) { - onDone(); - } - logError('unable to get Intimate Merger segment data'); - } - } -} - -/** - * Module init - * @param {Object} provider - * @param {Object} userConsent - * @return {boolean} - */ -function init(provider, userConsent) { - return true; -} - -/** @type {RtdSubmodule} */ -export const imRtdSubmodule = { - name: submoduleName, - getBidRequestData: getRealTimeData, - init: init -}; - -submodule('realTimeData', imRtdSubmodule); diff --git a/modules/imRtdProvider.md b/modules/imRtdProvider.md deleted file mode 100644 index 7ece2b996b4..00000000000 --- a/modules/imRtdProvider.md +++ /dev/null @@ -1,41 +0,0 @@ -## Intimate Merger Real-time Data Submodule - -provided by Intimate Merger. - -## Building Prebid with Real-time Data Support - -First, make sure to add the Intimate Merger submodule to your Prebid.js package with: - -`gulp build --modules=rtdModule,imRtdProvider` - -The following configuration parameters are available: - -``` -pbjs.setConfig( - ... - realTimeData: { - auctionDelay: 5000, - dataProviders: [ - { - name: "im", - waitForIt: true, - params: { - cid: 5126, // Set your Intimate Merger Customer ID here for production - setGptKeyValues: true - } - } - ] - } - ... -} -``` - -### Parameter Descriptions for the im Configuration Section - -| Param under dataProviders | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `"im"` | -| waitForIt | Optional | Boolean | Required to ensure that the auction is delayed until prefetch is complete. Defaults to false but recommended to true | `true` | -| params | Required | Object | Details of module params. | | -| params.cid | Required | Number | This is the Customer ID value obtained via Intimate Merger. | `5126` | -| params.setGptKeyValues | Optional | Boolean | This is set targeting for GPT/GAM. Default setting is true. | `true` | diff --git a/modules/impactifyBidAdapter.js b/modules/impactifyBidAdapter.js index b204e81f22c..7e52669d33e 100644 --- a/modules/impactifyBidAdapter.js +++ b/modules/impactifyBidAdapter.js @@ -1,14 +1,13 @@ -import { deepAccess, deepSetValue, generateUUID } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import {ajax} from '../src/ajax.js'; -import { createEidsArray } from './userId/eids.js'; const BIDDER_CODE = 'impactify'; const BIDDER_ALIAS = ['imp']; const DEFAULT_CURRENCY = 'USD'; const DEFAULT_VIDEO_WIDTH = 640; -const DEFAULT_VIDEO_HEIGHT = 360; +const DEFAULT_VIDEO_HEIGHT = 480; const ORIGIN = 'https://sonic.impactify.media'; const LOGGER_URI = 'https://logger.impactify.media'; const AUCTIONURI = '/bidder'; @@ -33,24 +32,12 @@ const createOpenRtbRequest = (validBidRequests, bidderRequest) => { id: bidderRequest.auctionId, validBidRequests, cur: [DEFAULT_CURRENCY], - imp: [], - source: {tid: bidderRequest.auctionId} + imp: [] }; // Force impactify debugging parameter - if (window.localStorage.getItem('_im_db_bidder') != null) { - request.test = Number(window.localStorage.getItem('_im_db_bidder')); - } - - // Set Schain in request - let schain = deepAccess(validBidRequests, '0.schain'); - if (schain) request.source.ext = { schain: schain }; - - // Set eids - let bidUserId = deepAccess(validBidRequests, '0.userId'); - let eids = createEidsArray(bidUserId); - if (eids.length) { - deepSetValue(request, 'user.ext.eids', eids); + if (window.localStorage.getItem('_im_db_bidder') == 3) { + request.test = 3; } // Set device/user/site @@ -71,23 +58,23 @@ const createOpenRtbRequest = (validBidRequests, bidderRequest) => { let gdprApplies = 0; if (bidderRequest.gdprConsent) { if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') gdprApplies = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; - deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString); } - deepSetValue(request, 'regs.ext.gdpr', gdprApplies); + utils.deepSetValue(request, 'regs.ext.gdpr', gdprApplies); if (bidderRequest.uspConsent) { - deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent); this.syncStore.uspConsent = bidderRequest.uspConsent; } - if (GETCONFIG('coppa') == true) deepSetValue(request, 'regs.coppa', 1); + if (GETCONFIG('coppa') == true) utils.deepSetValue(request, 'regs.coppa', 1); if (bidderRequest.uspConsent) { - deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent); } // Set buyer uid - deepSetValue(request, 'user.buyeruid', generateUUID()); + utils.deepSetValue(request, 'user.buyeruid', utils.generateUUID()); // Create imps with bids validBidRequests.forEach((bid) => { @@ -119,7 +106,7 @@ const createOpenRtbRequest = (validBidRequests, bidderRequest) => { export const spec = { code: BIDDER_CODE, gvlid: GVLID, - supportedMediaTypes: ['video', 'banner'], + supportedMediaTypes: ['video'], aliases: BIDDER_ALIAS, /** diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index 9de2e2b2d32..e73df68b625 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -1,58 +1,17 @@ -import { - cleanObj, deepAccess, deepClone, deepSetValue, getBidIdParameter, getBidRequest, getDNT, - getUniqueIdentifierStr, isFn, isPlainObject, logWarn, mergeDeep, parseUrl -} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {config} from '../src/config.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import {Renderer} from '../src/Renderer.js'; -import {createEidsArray} from './userId/eids.js'; +import { createEidsArray } from './userId/eids.js'; +import includes from 'core-js-pure/features/array/includes.js'; const BIDDER_CODE = 'improvedigital'; -const REQUEST_URL = 'https://ad.360yield.com/pb'; -const CREATIVE_TTL = 300; - -const VIDEO_PARAMS = { - DEFAULT_MIMES: ['video/mp4'], - SUPPORTED_PROPERTIES: ['mimes', 'minduration', 'maxduration', 'protocols', 'w', 'h', 'startdelay', 'placement', 'linearity', 'skip', 'skipmin', - 'skipafter', 'sequence', 'battr', 'maxextended', 'minbitrate', 'maxbitrate', 'boxingallowed', 'playbackmethod', 'playbackend', 'delivery', 'pos', 'companionad', - 'api', 'companiontype', 'ext'], - PLACEMENT_TYPE: { - INSTREAM: 1, - OUTSTREAM: 3, - } -}; - -const NATIVE_DATA = { - VERSION: '1.2', - ASSET_TYPES: { - TITLE: 'title', - IMG: 'img', - DATA: 'data', - }, - ASSETS: { - title: {id: 0, name: 'title', assetType: 'title', default: {len: 140}}, - sponsoredBy: {id: 1, name: 'sponsoredBy', assetType: 'data', type: 1}, - icon: {id: 2, name: 'icon', assetType: 'img', type: 2}, - body: {id: 3, name: 'body', assetType: 'data', type: 2}, - image: {id: 4, name: 'image', assetType: 'img', type: 3}, - rating: {id: 5, name: 'rating', assetType: 'data', type: 3}, - likes: {id: 6, name: 'likes', assetType: 'data', type: 4}, - downloads: {id: 7, name: 'downloads', assetType: 'data', type: 5}, - price: {id: 8, name: 'price', assetType: 'data', type: 6}, - salePrice: {id: 9, name: 'salePrice', assetType: 'data', type: 7}, - phone: {id: 10, name: 'phone', assetType: 'data', type: 8}, - address: {id: 11, name: 'address', assetType: 'data', type: 9}, - body2: {id: 12, name: 'body2', assetType: 'data', type: 10}, - displayUrl: {id: 13, name: 'displayUrl', assetType: 'data', type: 11}, - cta: {id: 14, name: 'cta', assetType: 'data', type: 12}, - }, - getAssetById(id) { - return Object.values(this.ASSETS).find(asset => id === asset.id); - } -}; +const RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; +const VIDEO_TARGETING = ['skip', 'skipmin', 'skipafter']; export const spec = { + version: '7.4.0', code: BIDDER_CODE, gvlid: 253, aliases: ['id'], @@ -64,7 +23,7 @@ export const spec = { * @param {object} bid The bid to validate. * @return boolean True if this is a valid bid, and false otherwise. */ - isBidRequestValid(bid) { + isBidRequestValid: function (bid) { return !!(bid && bid.params && (bid.params.placementId || (bid.params.placementKey && bid.params.publisherId))); }, @@ -72,134 +31,141 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. - * @param bidderRequest * @return ServerRequest Info describing the request to the server. */ - buildRequests(bidRequests, bidderRequest) { - const request = { - id: getUniqueIdentifierStr(), - cur: [config.getConfig('currency.adServerCurrency') || 'USD'], - ext: { - improvedigital: { - sdk: { - name: 'pbjs', - version: '$prebid.version$', - } - } - } + buildRequests: function (bidRequests, bidderRequest) { + let normalizedBids = bidRequests.map((bidRequest) => { + return getNormalizedBidRequest(bidRequest); + }); + + let idClient = new ImproveDigitalAdServerJSClient('hb'); + let requestParameters = { + singleRequestMode: (config.getConfig('improvedigital.singleRequest') === true), + returnObjType: idClient.CONSTANTS.RETURN_OBJ_TYPE.URL_PARAMS_SPLIT, + libVersion: this.version }; - // Device - request.device = (typeof config.getConfig('device') === 'object') ? config.getConfig('device') : {}; - request.device.w = request.device.w || window.innerWidth; - request.device.h = request.device.h || window.innerHeight; - if (getDNT()) { - request.device.dnt = 1; + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString) { + requestParameters.gdpr = bidderRequest.gdprConsent.consentString; } - // Coppa - const coppa = config.getConfig('coppa'); - if (typeof coppa === 'boolean') { - deepSetValue(request, 'regs.coppa', ID_UTIL.toBit(coppa)); + if (bidderRequest && bidderRequest.uspConsent) { + requestParameters.usPrivacy = bidderRequest.uspConsent; } - if (bidderRequest) { - // GDPR - const gdprConsent = deepAccess(bidderRequest, 'gdprConsent') - if (gdprConsent) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - deepSetValue(request, 'regs.ext.gdpr', ID_UTIL.toBit(gdprConsent.gdprApplies)); - } - deepSetValue(request, 'user.ext.consent', gdprConsent.consentString); - - // Additional Consent String - const additionalConsent = deepAccess(gdprConsent, 'addtlConsent'); - if (additionalConsent && additionalConsent.indexOf('~') !== -1) { - // Google Ad Tech Provider IDs - const atpIds = additionalConsent.substring(additionalConsent.indexOf('~') + 1); - if (atpIds) { - deepSetValue( - request, - 'user.ext.consented_providers_settings.consented_providers', - atpIds.split('.').map(id => parseInt(id, 10)) - ); - } - } - } - - // Timeout - if (bidderRequest.timeout) { - request.tmax = parseInt(bidderRequest.timeout); - } - // US Privacy - if (typeof bidderRequest.uspConsent !== typeof undefined) { - deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent); - } + if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + requestParameters.referrer = bidderRequest.refererInfo.referer; } - ID_REQUEST.buildSiteOrApp(request, bidderRequest); + requestParameters.schain = bidRequests[0].schain; - const bidRequest0 = bidRequests[0]; + if (bidRequests[0].userId) { + const eids = createEidsArray(bidRequests[0].userId); + if (eids.length) { + utils.deepSetValue(requestParameters, 'user.ext.eids', eids); + } + } - deepSetValue(request, 'source.ext.schain', bidRequest0.schain); - deepSetValue(request, 'source.tid', bidRequest0.transactionId); + let requestObj = idClient.createRequest( + normalizedBids, // requestObject + requestParameters + ); - if (bidRequest0.userId) { - const eids = createEidsArray(bidRequest0.userId); - deepSetValue(request, 'user.ext.eids', eids.length ? eids : undefined); + if (requestObj.errors && requestObj.errors.length > 0) { + utils.logError('ID WARNING 0x01'); } - - return ID_REQUEST.buildServerRequests(request, bidRequests, bidderRequest); + requestObj.requests.forEach(request => request.bidderRequest = bidderRequest); + return requestObj.requests; }, /** * Unpack the response from the server into a list of bids. * * @param {*} serverResponse A successful response from the server. - * @param bidderRequest * @return {Bid[]} An array of bids which were nested inside the server. */ - interpretResponse(serverResponse, { bidderRequest }) { - if (!Array.isArray(deepAccess(serverResponse, 'body.seatbid'))) { - return []; - } - + interpretResponse: function (serverResponse, {bidderRequest}) { const bids = []; - - serverResponse.body.seatbid.forEach(seatbid => { - if (!Array.isArray(seatbid.bid)) return; - - seatbid.bid.forEach(bidObject => { - if (!bidObject.adm || !bidObject.price || bidObject.hasOwnProperty('errorCode')) { - return; + utils._each(serverResponse.body.bid, function (bidObject) { + if (!bidObject.price || bidObject.price === null || + bidObject.hasOwnProperty('errorCode') || + (!bidObject.adm && !bidObject.native)) { + return; + } + const bidRequest = utils.getBidRequest(bidObject.id, [bidderRequest]); + const bid = {}; + + if (bidObject.native) { + // Native + bid.native = getNormalizedNativeAd(bidObject.native); + // Expose raw oRTB response to the client to allow parsing assets not directly supported by Prebid + bid.ortbNative = bidObject.native; + if (bidObject.nurl) { + bid.native.impressionTrackers.unshift(bidObject.nurl); } - const bidRequest = getBidRequest(bidObject.impid, [bidderRequest]); - const idExt = deepAccess(bidObject, `ext.${BIDDER_CODE}`); - - const bid = { - requestId: bidObject.impid, - cpm: bidObject.price, - creativeId: bidObject.crid, - currency: serverResponse.body.cur.toUpperCase() || 'USD', - dealId: (typeof idExt.buying_type === 'string' && idExt.buying_type !== 'rtb') ? idExt.line_item_id : undefined, - meta: { - advertiserDomains: bidObject.adomain ? bidObject.adomain : [] - }, - netRevenue: idExt.is_net || false, - ttl: CREATIVE_TTL + bid.mediaType = NATIVE; + } else if (bidObject.ad_type && bidObject.ad_type === 'video') { + bid.vastXml = bidObject.adm; + bid.mediaType = VIDEO; + if (isOutstreamVideo(bidRequest)) { + bid.adResponse = { + content: bid.vastXml, + height: bidObject.h, + width: bidObject.w + }; + bid.renderer = createRenderer(bidRequest); } + } else { + // Banner + let nurl = ''; + if (bidObject.nurl && bidObject.nurl.length > 0) { + nurl = ``; + } + bid.ad = `${nurl}`; + bid.mediaType = BANNER; + } - ID_RESPONSE.buildAd(bid, bidRequest, bidObject); - - ID_RAZR.addBidData({ - bidRequest, - bid + // Common properties + bid.cpm = parseFloat(bidObject.price); + bid.creativeId = bidObject.crid; + bid.currency = bidObject.currency ? bidObject.currency.toUpperCase() : 'USD'; + + // Deal ID. Composite ads can have multiple line items and the ID of the first + // dealID line item will be used. + if (utils.isNumber(bidObject.lid) && bidObject.buying_type && bidObject.buying_type !== 'rtb') { + bid.dealId = bidObject.lid; + } else if (Array.isArray(bidObject.lid) && + Array.isArray(bidObject.buying_type) && + bidObject.lid.length === bidObject.buying_type.length) { + let isDeal = false; + bidObject.buying_type.forEach((bt, i) => { + if (isDeal) return; + if (bt && bt !== 'rtb') { + isDeal = true; + bid.dealId = bidObject.lid[i]; + } }); + } - bids.push(bid); - }); - }); + bid.height = bidObject.h; + bid.netRevenue = bidObject.isNet ? bidObject.isNet : false; + bid.requestId = bidObject.id; + bid.ttl = 300; + bid.width = bidObject.w; + + if (!bid.width || !bid.height) { + bid.width = 1; + bid.height = 1; + } + + if (bidObject.adomain) { + bid.meta = { + advertiserDomains: bidObject.adomain + }; + } + bids.push(bid); + }); return bids; }, @@ -210,14 +176,17 @@ export const spec = { * @param {ServerResponse[]} serverResponses List of server's responses. * @return {UserSync[]} The user syncs which should be dropped. */ - getUserSyncs(syncOptions, serverResponses) { + getUserSyncs: function(syncOptions, serverResponses) { if (syncOptions.pixelEnabled) { const syncs = []; serverResponses.forEach(response => { - const syncArr = deepAccess(response, `body.ext.${BIDDER_CODE}.sync`, []); - syncArr.forEach(syncElement => { - if (syncs.indexOf(syncElement) === -1) { - syncs.push(syncElement); + response.body.bid.forEach(bidObject => { + if (utils.isArray(bidObject.sync)) { + bidObject.sync.forEach(syncElement => { + if (syncs.indexOf(syncElement) === -1) { + syncs.push(syncElement); + } + }); } }); }); @@ -227,384 +196,519 @@ export const spec = { } }; -registerBidder(spec); +function isInstreamVideo(bid) { + const mediaTypes = Object.keys(utils.deepAccess(bid, 'mediaTypes', {})); + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + return bid.mediaType === 'video' || (mediaTypes.length === 1 && videoMediaType && context !== 'outstream'); +} + +function isOutstreamVideo(bid) { + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + return videoMediaType && context === 'outstream'; +} + +function getVideoTargetingParams(bid) { + const result = {}; + Object.keys(Object(bid.mediaTypes.video)) + .filter(key => includes(VIDEO_TARGETING, key)) + .forEach(key => { + result[ key ] = bid.mediaTypes.video[ key ]; + }); + Object.keys(Object(bid.params.video)) + .filter(key => includes(VIDEO_TARGETING, key)) + .forEach(key => { + result[ key ] = bid.params.video[ key ]; + }); + return result; +} -const ID_REQUEST = { - buildServerRequests(requestObject, bidRequests, bidderRequest) { - const requests = []; - if (config.getConfig('improvedigital.singleRequest') === true) { - requestObject.imp = bidRequests.map((bidRequest) => this.buildImp(bidRequest)); - requests[0] = this.formatRequest(requestObject, bidderRequest); - } else { - bidRequests.map((bidRequest) => { - const request = deepClone(requestObject); - request.id = bidRequest.bidId || getUniqueIdentifierStr(); - request.imp = [this.buildImp(bidRequest)]; - deepSetValue(request, 'source.tid', bidRequest.transactionId); - requests.push(this.formatRequest(request, bidderRequest)); - }); +function getBidFloor(bid) { + if (!utils.isFn(bid.getFloor)) { + return null; + } + const floor = bid.getFloor({ + currency: 'USD', + mediaType: '*', + size: '*' + }); + if (utils.isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { + return floor.floor; + } + return null; +} + +function outstreamRender(bid) { + bid.renderer.push(() => { + window.ANOutstreamVideo.renderAd({ + sizes: [bid.width, bid.height], + targetId: bid.adUnitCode, + adResponse: bid.adResponse, + rendererOptions: bid.renderer.getConfig() + }, handleOutstreamRendererEvents.bind(null, bid)); + }); +} + +function handleOutstreamRendererEvents(bid, id, eventName) { + bid.renderer.handleVideoEvent({ id, eventName }); +} + +function createRenderer(bidRequest) { + const renderer = Renderer.install({ + id: bidRequest.adUnitCode, + url: RENDERER_URL, + loaded: false, + config: utils.deepAccess(bidRequest, 'renderer.options'), + adUnitCode: bidRequest.adUnitCode + }); + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + return renderer; +} + +function getNormalizedBidRequest(bid) { + let adUnitId = utils.getBidIdParameter('adUnitCode', bid) || null; + let placementId = utils.getBidIdParameter('placementId', bid.params) || null; + let publisherId = null; + let placementKey = null; + + if (placementId === null) { + publisherId = utils.getBidIdParameter('publisherId', bid.params) || null; + placementKey = utils.getBidIdParameter('placementKey', bid.params) || null; + } + const keyValues = utils.getBidIdParameter('keyValues', bid.params) || null; + const singleSizeFilter = utils.getBidIdParameter('size', bid.params) || null; + const bidId = utils.getBidIdParameter('bidId', bid); + const transactionId = utils.getBidIdParameter('transactionId', bid); + const currency = config.getConfig('currency.adServerCurrency'); + + let normalizedBidRequest = {}; + if (isInstreamVideo(bid)) { + normalizedBidRequest.adTypes = [ VIDEO ]; + } + if (isInstreamVideo(bid) || isOutstreamVideo(bid)) { + normalizedBidRequest.video = getVideoTargetingParams(bid); + } + if (placementId) { + normalizedBidRequest.placementId = placementId; + } else { + if (publisherId) { + normalizedBidRequest.publisherId = publisherId; + } + if (placementKey) { + normalizedBidRequest.placementKey = placementKey; } + } - return requests; - }, + if (keyValues) { + normalizedBidRequest.keyValues = keyValues; + } - formatRequest(request, bidderRequest) { - return { - method: 'POST', - url: REQUEST_URL, - data: JSON.stringify(request), - bidderRequest - } - }, + if (config.getConfig('improvedigital.usePrebidSizes') === true && !isInstreamVideo(bid) && !isOutstreamVideo(bid) && bid.sizes && bid.sizes.length > 0) { + normalizedBidRequest.format = bid.sizes; + } else if (singleSizeFilter && singleSizeFilter.w && singleSizeFilter.h) { + normalizedBidRequest.size = {}; + normalizedBidRequest.size.h = singleSizeFilter.h; + normalizedBidRequest.size.w = singleSizeFilter.w; + } - buildImp(bidRequest) { - const imp = { - id: getBidIdParameter('bidId', bidRequest) || getUniqueIdentifierStr(), - secure: ID_UTIL.toBit(window.location.protocol === 'https:'), - }; + if (bidId) { + normalizedBidRequest.id = bidId; + } + if (adUnitId) { + normalizedBidRequest.adUnitId = adUnitId; + } + if (transactionId) { + normalizedBidRequest.transactionId = transactionId; + } + if (currency) { + normalizedBidRequest.currency = currency; + } + // Floor + let bidFloor = getBidFloor(bid); + let bidFloorCur = null; + if (!bidFloor) { + bidFloor = utils.getBidIdParameter('bidFloor', bid.params); + bidFloorCur = utils.getBidIdParameter('bidFloorCur', bid.params); + } + if (bidFloor) { + normalizedBidRequest.bidFloor = bidFloor; + normalizedBidRequest.bidFloorCur = bidFloorCur ? bidFloorCur.toUpperCase() : 'USD'; + } + return normalizedBidRequest; +} - // Floor - const bidFloor = this.getBidFloor(bidRequest) || getBidIdParameter('bidFloor', bidRequest.params); - if (bidFloor) { - const bidFloorCur = getBidIdParameter('bidFloorCur', bidRequest.params) || 'USD'; - deepSetValue(imp, 'bidfloor', bidFloor); - deepSetValue(imp, 'bidfloorcur', bidFloorCur ? bidFloorCur.toUpperCase() : undefined); +function getNormalizedNativeAd(rawNative) { + const native = {}; + if (!rawNative || !utils.isArray(rawNative.assets)) { + return null; + } + // Assets + rawNative.assets.forEach(asset => { + if (asset.title) { + native.title = asset.title.text; + } else if (asset.data) { + switch (asset.data.type) { + case 1: + native.sponsoredBy = asset.data.value; + break; + case 2: + native.body = asset.data.value; + break; + case 3: + native.rating = asset.data.value; + break; + case 4: + native.likes = asset.data.value; + break; + case 5: + native.downloads = asset.data.value; + break; + case 6: + native.price = asset.data.value; + break; + case 7: + native.salePrice = asset.data.value; + break; + case 8: + native.phone = asset.data.value; + break; + case 9: + native.address = asset.data.value; + break; + case 10: + native.body2 = asset.data.value; + break; + case 11: + native.displayUrl = asset.data.value; + break; + case 12: + native.cta = asset.data.value; + break; + } + } else if (asset.img) { + switch (asset.img.type) { + case 2: + native.icon = { + url: asset.img.url, + width: asset.img.w, + height: asset.img.h + }; + break; + case 3: + native.image = { + url: asset.img.url, + width: asset.img.w, + height: asset.img.h + }; + break; + } } + }); + // Trackers + if (rawNative.eventtrackers) { + native.impressionTrackers = []; + rawNative.eventtrackers.forEach(tracker => { + // Only handle impression event. Viewability events are not supported yet. + if (tracker.event !== 1) return; + switch (tracker.method) { + case 1: // img + native.impressionTrackers.push(tracker.url); + break; + case 2: // js + // javascriptTrackers is a string. If there's more than one JS tracker in bid response, the last script will be used. + native.javascriptTrackers = ``; + break; + } + }); + } else { + native.impressionTrackers = rawNative.imptrackers || []; + native.javascriptTrackers = rawNative.jstracker; + } + if (rawNative.link) { + native.clickUrl = rawNative.link.url; + native.clickTrackers = rawNative.link.clicktrackers; + } + if (rawNative.privacy) { + native.privacyLink = rawNative.privacy; + } + return native; +} +registerBidder(spec); - const placementId = getBidIdParameter('placementId', bidRequest.params); - if (placementId) { - deepSetValue(imp, 'ext.bidder.placementId', placementId); - } else { - deepSetValue(imp, 'ext.bidder.publisherId', getBidIdParameter('publisherId', bidRequest.params)); - deepSetValue(imp, 'ext.bidder.placementKey', getBidIdParameter('placementKey', bidRequest.params)); +export function ImproveDigitalAdServerJSClient(endPoint) { + this.CONSTANTS = { + AD_SERVER_BASE_URL: 'ice.360yield.com', + END_POINT: endPoint || 'hb', + AD_SERVER_URL_PARAM: 'jsonp=', + CLIENT_VERSION: 'JS-6.4.0', + MAX_URL_LENGTH: 2083, + ERROR_CODES: { + MISSING_PLACEMENT_PARAMS: 2, + LIB_VERSION_MISSING: 3 + }, + RETURN_OBJ_TYPE: { + DEFAULT: 0, + URL_PARAMS_SPLIT: 1 } + }; - deepSetValue(imp, 'ext.bidder.keyValues', getBidIdParameter('keyValues', bidRequest.params) || undefined); + this.getErrorReturn = function(errorCode) { + return { + idMappings: {}, + requests: {}, + 'errorCode': errorCode + }; + }; - // Adding GPID - const gpid = deepAccess(bidRequest, 'ortb2Imp.ext.gpid') || - deepAccess(bidRequest, 'ortb2Imp.ext.data.pbadslot') || - deepAccess(bidRequest, 'ortb2Imp.ext.data.adserver.adslot'); + this.createRequest = function(requestObject, requestParameters, extraRequestParameters) { + if (!requestParameters.libVersion) { + return this.getErrorReturn(this.CONSTANTS.ERROR_CODES.LIB_VERSION_MISSING); + } - deepSetValue(imp, 'ext.gpid', gpid); + requestParameters.returnObjType = requestParameters.returnObjType || this.CONSTANTS.RETURN_OBJ_TYPE.DEFAULT; + requestParameters.adServerBaseUrl = 'https://' + (requestParameters.adServerBaseUrl || this.CONSTANTS.AD_SERVER_BASE_URL); - // Adding Interstitial Signal - if (deepAccess(bidRequest, 'ortb2Imp.instl')) { - imp.instl = 1; + let impressionObjects = []; + let impressionObject; + if (utils.isArray(requestObject)) { + for (let counter = 0; counter < requestObject.length; counter++) { + impressionObject = this.createImpressionObject(requestObject[counter]); + impressionObjects.push(impressionObject); + } + } else { + impressionObject = this.createImpressionObject(requestObject); + impressionObjects.push(impressionObject); } - const videoParams = deepAccess(bidRequest, 'mediaTypes.video'); - if (videoParams) { - imp.video = this.buildVideoRequest(bidRequest); - deepSetValue(imp, 'ext.is_rewarded_inventory', (videoParams.rewarded === 1 || deepAccess(videoParams, 'ext.rewarded') === 1) || undefined); + let returnIdMappings = true; + if (requestParameters.returnObjType === this.CONSTANTS.RETURN_OBJ_TYPE.URL_PARAMS_SPLIT) { + returnIdMappings = false; } - if (deepAccess(bidRequest, 'mediaTypes.banner')) { - imp.banner = this.buildBannerRequest(bidRequest); + let returnObject = {}; + returnObject.requests = []; + if (returnIdMappings) { + returnObject.idMappings = []; } + let errors = null; - if (deepAccess(bidRequest, 'mediaTypes.native')) { - const nativeImp = this.buildNativeRequest(bidRequest); - if (nativeImp) { - imp.native = nativeImp; + let baseUrl = `${requestParameters.adServerBaseUrl}/${this.CONSTANTS.END_POINT}?${this.CONSTANTS.AD_SERVER_URL_PARAM}`; + + let bidRequestObject = { + bid_request: this.createBasicBidRequestObject(requestParameters, extraRequestParameters) + }; + for (let counter = 0; counter < impressionObjects.length; counter++) { + impressionObject = impressionObjects[counter]; + + if (impressionObject.errorCode) { + errors = errors || []; + errors.push({ + errorCode: impressionObject.errorCode, + adUnitId: impressionObject.adUnitId + }); + } else { + if (returnIdMappings) { + returnObject.idMappings.push({ + adUnitId: impressionObject.adUnitId, + id: impressionObject.impressionObject.id + }); + } + bidRequestObject.bid_request.imp = bidRequestObject.bid_request.imp || []; + bidRequestObject.bid_request.imp.push(impressionObject.impressionObject); + + let writeLongRequest = false; + const outputUri = baseUrl + encodeURIComponent(JSON.stringify(bidRequestObject)); + if (outputUri.length > this.CONSTANTS.MAX_URL_LENGTH) { + writeLongRequest = true; + if (bidRequestObject.bid_request.imp.length > 1) { + // Pop the current request and process it again in the next iteration + bidRequestObject.bid_request.imp.pop(); + if (returnIdMappings) { + returnObject.idMappings.pop(); + } + counter--; + } + } + + if (writeLongRequest || + !requestParameters.singleRequestMode || + counter === impressionObjects.length - 1) { + returnObject.requests.push(this.formatRequest(requestParameters, bidRequestObject)); + bidRequestObject = { + bid_request: this.createBasicBidRequestObject(requestParameters, extraRequestParameters) + }; + } } } - return imp; - }, + if (errors) { + returnObject.errors = errors; + } - buildVideoRequest(bidRequest) { - const videoParams = deepClone(bidRequest.mediaTypes.video); - const videoImproveParams = deepClone(deepAccess(bidRequest, 'params.video', {})); - const video = {...videoParams, ...videoImproveParams}; + return returnObject; + }; - if (Array.isArray(video.playerSize)) { - // Player size can be defined as [w, h] or [[w, h]] - const size = Array.isArray(video.playerSize[0]) ? video.playerSize[0] : video.playerSize; - video.w = size[0]; - video.h = size[1]; + this.formatRequest = function(requestParameters, bidRequestObject) { + switch (requestParameters.returnObjType) { + case this.CONSTANTS.RETURN_OBJ_TYPE.URL_PARAMS_SPLIT: + return { + method: 'GET', + url: `${requestParameters.adServerBaseUrl}/${this.CONSTANTS.END_POINT}`, + data: `${this.CONSTANTS.AD_SERVER_URL_PARAM}${encodeURIComponent(JSON.stringify(bidRequestObject))}` + }; + default: + const baseUrl = `${requestParameters.adServerBaseUrl}/` + + `${this.CONSTANTS.END_POINT}?${this.CONSTANTS.AD_SERVER_URL_PARAM}`; + return { + url: baseUrl + encodeURIComponent(JSON.stringify(bidRequestObject)) + } } - video.placement = this.isOutstreamVideo(bidRequest) ? VIDEO_PARAMS.PLACEMENT_TYPE.OUTSTREAM : VIDEO_PARAMS.PLACEMENT_TYPE.INSTREAM; + }; - // Mimes is required - if (!video.mimes) { - video.mimes = VIDEO_PARAMS.DEFAULT_MIMES; + this.createBasicBidRequestObject = function(requestParameters, extraRequestParameters) { + let impressionBidRequestObject = {}; + impressionBidRequestObject.secure = 1; + if (requestParameters.requestId) { + impressionBidRequestObject.id = requestParameters.requestId; + } else { + impressionBidRequestObject.id = utils.getUniqueIdentifierStr(); } - - // skip must be 0 or 1 - if (video.skip !== 1) { - delete video.skipmin; - delete video.skipafter; - if (video.skip !== 0) { - logWarn(`video.skip: invalid value '${video.skip}'. Expected 0 or 1`); - delete video.skip; + if (requestParameters.domain) { + impressionBidRequestObject.domain = requestParameters.domain; + } + if (requestParameters.page) { + impressionBidRequestObject.page = requestParameters.page; + } + if (requestParameters.ref) { + impressionBidRequestObject.ref = requestParameters.ref; + } + if (requestParameters.callback) { + impressionBidRequestObject.callback = requestParameters.callback; + } + if (requestParameters.libVersion) { + impressionBidRequestObject.version = requestParameters.libVersion + '-' + this.CONSTANTS.CLIENT_VERSION; + } + if (requestParameters.referrer) { + impressionBidRequestObject.referrer = requestParameters.referrer; + } + if (requestParameters.gdpr || requestParameters.gdpr === 0) { + impressionBidRequestObject.gdpr = requestParameters.gdpr; + } + if (requestParameters.usPrivacy) { + impressionBidRequestObject.us_privacy = requestParameters.usPrivacy; + } + if (requestParameters.schain) { + impressionBidRequestObject.schain = requestParameters.schain; + } + if (requestParameters.user) { + impressionBidRequestObject.user = requestParameters.user; + } + if (extraRequestParameters) { + for (let prop in extraRequestParameters) { + impressionBidRequestObject[prop] = extraRequestParameters[prop]; } } - Object.keys(video).forEach(prop => { - if (VIDEO_PARAMS.SUPPORTED_PROPERTIES.indexOf(prop) === -1) delete video[prop]; - }); - return video; - }, + return impressionBidRequestObject; + }; - buildBannerRequest(bidRequest) { - // Set the desired creative sizes - // Input Format: array of pairs, i.e. [[300, 250], [250, 250]] - // Unless improvedigital.usePrebidSizes == true, no sizes are sent to the server - // and the sizes defined in the server for the placement will be used - const banner = {}; - if (config.getConfig('improvedigital.usePrebidSizes') === true && bidRequest.sizes) { - // Convert sizes from [x, y] to { w: x, h: y} - banner.format = bidRequest.sizes.map(sizePair => ({w: sizePair[0], h: sizePair[1]})); - } - return banner; - }, + this.createImpressionObject = function(placementObject) { + let outputObject = {}; + let impressionObject = {}; + outputObject.impressionObject = impressionObject; - buildNativeRequest(bidRequest) { - const nativeParams = bidRequest.nativeParams; - if (!nativeParams) { - return null; - } - const request = { - assets: [], - } - for (let i of Object.keys(nativeParams)) { - const assetOrtbParams = NATIVE_DATA.ASSETS[i]; - if (assetOrtbParams) { - const assetParams = nativeParams[i]; - const asset = { - id: assetOrtbParams.id, - required: ID_UTIL.toBit(assetParams.required), - }; - switch (assetOrtbParams.assetType) { - case NATIVE_DATA.ASSET_TYPES.TITLE: - asset.title = {len: assetParams.len || assetOrtbParams.default.len}; - break; - case NATIVE_DATA.ASSET_TYPES.DATA: - asset.data = cleanObj({type: assetOrtbParams.type, len: assetParams.len}) - break; - case NATIVE_DATA.ASSET_TYPES.IMG: - asset.img = cleanObj({ - type: assetOrtbParams.type, - w: deepAccess(assetParams, 'sizes.0'), - h: deepAccess(assetParams, 'sizes.1'), - wmin: deepAccess(assetParams, 'aspect_ratios.0.min_width'), - hmin: deepAccess(assetParams, 'aspect_ratios.0.min_height') - }); - break; - default: - return; - } - request.assets.push(asset); - } + if (placementObject.id) { + impressionObject.id = placementObject.id; + } else { + impressionObject.id = utils.getUniqueIdentifierStr(); } - if (!request.assets.length) { - logWarn('No native assets recognized. Ignoring native ad request'); - return null; + if (placementObject.adTypes) { + impressionObject.ad_types = placementObject.adTypes; } - return { ver: NATIVE_DATA.VERSION, request: JSON.stringify(request) }; - }, - - isOutstreamVideo(bidRequest) { - return deepAccess(bidRequest, 'mediaTypes.video.context') === 'outstream'; - }, - - getBidFloor(bidRequest) { - if (!isFn(bidRequest.getFloor)) { - return null; + if (placementObject.adUnitId) { + outputObject.adUnitId = placementObject.adUnitId; } - const floor = bidRequest.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*' - }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { - return floor.floor; + if (placementObject.currency) { + impressionObject.currency = placementObject.currency.toUpperCase(); } - return null; - }, - - buildSiteOrApp(request, bidderRequest) { - const app = {}; - const configAppSettings = config.getConfig('app') || {}; - const fpdAppSettings = config.getConfig('ortb2.app') || {}; - mergeDeep(app, configAppSettings, fpdAppSettings); - - if (Object.keys(app).length !== 0) { - request.app = app; - } else { - const site = {}; - const url = config.getConfig('pageUrl') || deepAccess(bidderRequest, 'refererInfo.referer'); - if (url) { - site.page = url; - site.domain = parseUrl(url).hostname; - } - const configSiteSettings = config.getConfig('site') || {}; - const fpdSiteSettings = config.getConfig('ortb2.site') || {}; - mergeDeep(site, configSiteSettings, fpdSiteSettings); - request.site = site; + if (placementObject.bidFloor) { + impressionObject.bidfloor = placementObject.bidFloor; } - }, -}; - -const ID_RESPONSE = { - buildAd(bid, bidRequest, bidResponse) { - if (bidRequest.mediaTypes && Object.keys(bidRequest.mediaTypes).length === 1) { - if (deepAccess(bidRequest, 'mediaTypes.video')) { - this.buildVideoAd(bid, bidRequest, bidResponse); - } else if (deepAccess(bidRequest, 'mediaTypes.banner')) { - this.buildBannerAd(bid, bidRequest, bidResponse); - } else if (deepAccess(bidRequest, 'mediaTypes.native')) { - this.buildNativeAd(bid, bidRequest, bidResponse) + if (placementObject.bidFloorCur) { + impressionObject.bidfloorcur = placementObject.bidFloorCur.toUpperCase(); + } + if (placementObject.placementId) { + impressionObject.pid = placementObject.placementId; + } + if (placementObject.publisherId) { + impressionObject.pubid = placementObject.publisherId; + } + if (placementObject.placementKey) { + impressionObject.pkey = placementObject.placementKey; + } + if (placementObject.transactionId) { + impressionObject.tid = placementObject.transactionId; + } + if (!utils.isEmpty(placementObject.video)) { + const video = Object.assign({}, placementObject.video); + // skip must be 0 or 1 + if (video.skip !== 1) { + delete video.skipmin; + delete video.skipafter; + if (video.skip !== 0) { + utils.logWarn(`video.skip: invalid value '${video.skip}'. Expected 0 or 1`); + delete video.skip; + } } - } else { - if (bidResponse.adm.search(/^ { - // Only handle impression event. Viewability events are not supported yet. - if (tracker.event !== 1) return; - switch (tracker.method) { - case 1: // img - nativeAd.impressionTrackers.push(tracker.url); - break; - case 2: // js - // javascriptTrackers is a string. If there's more than one JS tracker in bid response, the last script will be used. - nativeAd.javascriptTrackers = ``; - break; + if (placementObject.keyValues) { + for (let key in placementObject.keyValues) { + for (let valueCounter = 0; valueCounter < placementObject.keyValues[key].length; valueCounter++) { + impressionObject.kvw = impressionObject.kvw || {}; + impressionObject.kvw[key] = impressionObject.kvw[key] || []; + impressionObject.kvw[key].push(placementObject.keyValues[key][valueCounter]); } - }); - } else { - nativeAd.impressionTrackers = nativeResponse.imptrackers || []; - nativeAd.javascriptTrackers = nativeResponse.jstracker; - } - nativeResponse.assets.map(asset => { - const assetParams = NATIVE_DATA.getAssetById(asset.id); - switch (assetParams.assetType) { - case NATIVE_DATA.ASSET_TYPES.TITLE: - nativeAd.title = asset.title.text; - break; - case NATIVE_DATA.ASSET_TYPES.DATA: - nativeAd[assetParams.name] = asset.data.value; - break; - case NATIVE_DATA.ASSET_TYPES.IMG: - nativeAd[assetParams.name] = { - url: asset.img.url, - width: asset.img.w, - height: asset.img.h, - }; - break; } - }); - bid.native = nativeAd; - }, -}; - -const ID_OUTSTREAM = { - RENDERER_URL: 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js', - createRenderer(bidRequest) { - const renderer = Renderer.install({ - id: bidRequest.adUnitCode, - url: this.RENDERER_URL, - config: deepAccess(bidRequest, 'renderer.options'), - adUnitCode: bidRequest.adUnitCode - }); - try { - renderer.setRender(this.render); - } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); } - return renderer; - }, - - render(bid) { - bid.renderer.push(() => { - window.ANOutstreamVideo.renderAd({ - sizes: [bid.width, bid.height], - targetId: bid.adUnitCode, - adResponse: bid.adResponse, - rendererOptions: bid.renderer.getConfig() - }, ID_OUTSTREAM.handleRendererEvents.bind(null, bid)); - }); - }, - handleRendererEvents(bid, id, eventName) { - bid.renderer.handleVideoEvent({ id, eventName }); - }, -}; - -const ID_RAZR = { - RENDERER_URL: 'https://razr.improvedigital.com/renderer.js', - addBidData({bid, bidRequest}) { - if (this.isValidBid(bid)) { - bid.renderer = Renderer.install({ - url: this.RENDERER_URL, - config: {bidRequest} - }); - bid.renderer.setRender(this.render); + impressionObject.banner = {}; + if (placementObject.size && placementObject.size.w && placementObject.size.h) { + impressionObject.banner.w = placementObject.size.w; + impressionObject.banner.h = placementObject.size.h; } - }, - isValidBid(bid) { - return bid && /razr:\/\//.test(bid.ad); - }, - - render(bid) { - const {bidRequest} = bid.renderer.getConfig(); - - const payload = { - type: 'prebid', - bidRequest, - bid, - config: mergeDeep( - {}, - config.getConfig('improvedigital.rendererConfig'), - deepAccess(bidRequest, 'params.rendererConfig') - ) - }; - - const razr = window.razr = window.razr || {}; - razr.queue = razr.queue || []; - razr.queue.push(payload); - } -}; + // Set of desired creative sizes + // Input Format: array of pairs, i.e. [[300, 250], [250, 250]] + if (placementObject.format && utils.isArray(placementObject.format)) { + const format = placementObject.format + .filter(sizePair => sizePair.length === 2 && + utils.isInteger(sizePair[0]) && + utils.isInteger(sizePair[1]) && + sizePair[0] >= 0 && + sizePair[1] >= 0) + .map(sizePair => { + return { w: sizePair[0], h: sizePair[1] } + }); + if (format.length > 0) { + impressionObject.banner.format = format; + } + } -const ID_UTIL = { - toBit(val) { - return val ? 1 : 0; - }, -}; + if (!impressionObject.pid && + !impressionObject.pubid && + !impressionObject.pkey && + !(impressionObject.banner && impressionObject.banner.w && impressionObject.banner.h)) { + outputObject.impressionObject = null; + outputObject.errorCode = this.CONSTANTS.ERROR_CODES.MISSING_PLACEMENT_PARAMS; + } + return outputObject; + }; +} diff --git a/modules/imuIdSystem.js b/modules/imuIdSystem.js index 72e81d243a3..da03c63fc8a 100644 --- a/modules/imuIdSystem.js +++ b/modules/imuIdSystem.js @@ -5,7 +5,7 @@ * @requires module:modules/userId */ -import { timestamp, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js' import { ajax } from '../src/ajax.js' import { submodule } from '../src/hook.js'; import { getStorageManager } from '../src/storageManager.js'; @@ -20,7 +20,7 @@ const cookiesMaxAge = 97200000000; // 37 months ((365 * 3 + 30) * 24 * 60 * 60 * export function setImDataInLocalStorage(value) { storage.setDataInLocalStorage(storageKey, value); - storage.setDataInLocalStorage(`${storageKey}_mt`, new Date(timestamp()).toUTCString()); + storage.setDataInLocalStorage(`${storageKey}_mt`, new Date(utils.timestamp()).toUTCString()); } export function removeImDataFromLocalStorage() { @@ -32,7 +32,7 @@ function setImDataInCookie(value) { storage.setCookie( cookieKey, value, - new Date(timestamp() + cookiesMaxAge).toUTCString(), + new Date(utils.timestamp() + cookiesMaxAge).toUTCString(), 'none' ); } @@ -73,7 +73,7 @@ export function getApiCallback(callback) { responseObj = JSON.parse(response); apiSuccessProcess(responseObj); } catch (error) { - logError('User ID - imuid submodule: ' + error); + utils.logError('User ID - imuid submodule: ' + error); } } if (callback && responseObj.uid) { @@ -81,7 +81,7 @@ export function getApiCallback(callback) { } }, error: error => { - logError('User ID - imuid submodule was unable to get data from api: ' + error); + utils.logError('User ID - imuid submodule was unable to get data from api: ' + error); if (callback) { callback(); } @@ -128,7 +128,7 @@ export const imuIdSubmodule = { getId(config) { const configParams = (config && config.params) || {}; if (!configParams || typeof configParams.cid !== 'number') { - logError('User ID - imuid submodule requires a valid cid to be defined'); + utils.logError('User ID - imuid submodule requires a valid cid to be defined'); return undefined; } let apiUrl = getApiUrl(configParams.cid, configParams.url); diff --git a/modules/inmarBidAdapter.js b/modules/inmarBidAdapter.js index 0e056551b35..e1edd935587 100755 --- a/modules/inmarBidAdapter.js +++ b/modules/inmarBidAdapter.js @@ -1,4 +1,4 @@ -import { logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; @@ -83,7 +83,7 @@ export const spec = { bidResponses.push(bidResponse); } } catch (error) { - logError('Error while parsing inmar response', error); + utils.logError('Error while parsing inmar response', error); } return bidResponses; }, diff --git a/modules/innityBidAdapter.js b/modules/innityBidAdapter.js index 0a2f701ef64..ab7ee07db4a 100644 --- a/modules/innityBidAdapter.js +++ b/modules/innityBidAdapter.js @@ -1,4 +1,4 @@ -import { parseSizesInput, timestamp } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'innity'; @@ -11,13 +11,13 @@ export const spec = { }, buildRequests: function(validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { - let parseSized = parseSizesInput(bidRequest.sizes); + let parseSized = utils.parseSizesInput(bidRequest.sizes); let arrSize = parseSized[0].split('x'); return { method: 'GET', url: ENDPOINT, data: { - cb: timestamp(), + cb: utils.timestamp(), ver: 2, hb: 1, output: 'js', diff --git a/modules/inskinBidAdapter.js b/modules/inskinBidAdapter.js index 781bca90660..5173f1dca63 100644 --- a/modules/inskinBidAdapter.js +++ b/modules/inskinBidAdapter.js @@ -1,4 +1,4 @@ -import { createTrackPixelHtml } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'inskin'; @@ -55,22 +55,6 @@ export const spec = { parallel: true }, validBidRequests[0].params); - if (validBidRequests[0].schain) { - data.rtb = { - schain: validBidRequests[0].schain - }; - } else if (data.publisherId) { - data.rtb = { - schain: { - ext: { - sid: String(data.publisherId) - } - } - }; - } - - delete data.publisherId; - data.keywords = data.keywords || []; const restrictions = []; @@ -293,7 +277,7 @@ function getSize(sizes) { } function retrieveAd(bidId, decision) { - return "`; - break; - } - }); - } - - if (nativeAdm.privacy) { - native.privacyLink = nativeAdm.privacy; - } - - return native; -} - export const spec = { code: BIDDER_CODE, @@ -607,7 +221,7 @@ export const spec = { supportedMediaTypes: SUPPORTED_MEDIA_TYPES, isBidRequestValid: function(bid) { - return !!(bid && !isEmpty(bid)); + return !!(bid && !utils.isEmpty(bid)); }, buildRequests: function(validBidRequests, bidderRequest) { @@ -615,11 +229,11 @@ export const spec = { // Pass the auctionId as ortb2 id // See https://github.com/prebid/Prebid.js/issues/6563 - deepSetValue(payload, 'id', bidderRequest.auctionId); - deepSetValue(payload, 'source.tid', bidderRequest.auctionId); + utils.deepSetValue(payload, 'id', bidderRequest.auctionId); + utils.deepSetValue(payload, 'source.tid', bidderRequest.auctionId); validBidRequests.forEach(validBid => { - let bid = deepClone(validBid); + let bid = utils.deepClone(validBid); // No additional params atm. const imp = createImp(bid); @@ -628,37 +242,37 @@ export const spec = { }); if (validBidRequests[0].schain) { - deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); + utils.deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); } if (bidderRequest && bidderRequest.gdprConsent) { - deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(payload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + utils.deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(payload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); } if (bidderRequest && bidderRequest.uspConsent) { - deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); } if (config.getConfig('coppa') === true) { - deepSetValue(payload, 'regs.coppa', 1); + utils.deepSetValue(payload, 'regs.coppa', 1); } - if (deepAccess(validBidRequests[0], 'userId')) { - deepSetValue(payload, 'user.ext.eids', createEidsArray(validBidRequests[0].userId)); + if (utils.deepAccess(validBidRequests[0], 'userId')) { + utils.deepSetValue(payload, 'user.ext.eids', createEidsArray(validBidRequests[0].userId)); } // Assign payload.site from refererinfo if (bidderRequest.refererInfo) { if (bidderRequest.refererInfo.reachedTop) { const sitePage = bidderRequest.refererInfo.referer; - deepSetValue(payload, 'site.page', sitePage); - deepSetValue(payload, 'site.domain', parseUrl(sitePage, { + utils.deepSetValue(payload, 'site.page', sitePage); + utils.deepSetValue(payload, 'site.domain', utils.parseUrl(sitePage, { noDecodeWholeURL: true }).hostname); if (canAccessTopWindow()) { - deepSetValue(payload, 'site.ref', getWindowTop().document.referrer); + utils.deepSetValue(payload, 'site.ref', utils.getWindowTop().document.referrer); } } } @@ -666,10 +280,15 @@ export const spec = { // Handle First Party Data (need publisher fpd setup) const fpd = config.getConfig('ortb2') || {}; if (fpd.site) { - mergeDeep(payload, { site: fpd.site }); + utils.mergeDeep(payload, { site: fpd.site }); } if (fpd.user) { - mergeDeep(payload, { user: fpd.user }); + utils.mergeDeep(payload, { user: fpd.user }); + } + // Here we can handle device.geo prop + const deviceGeo = utils.deepAccess(fpd, 'device.geo'); + if (deviceGeo) { + utils.mergeDeep(payload.device, { geo: deviceGeo }); } const request = { @@ -688,19 +307,19 @@ export const spec = { const bidResponses = []; try { - if (serverResponse.body && serverResponse.body.seatbid && isArray(serverResponse.body.seatbid)) { + if (serverResponse.body && serverResponse.body.seatbid && utils.isArray(serverResponse.body.seatbid)) { const currency = serverResponse.body.cur || DEFAULT_CURRENCY; const referrer = bidRequest.site && bidRequest.site.ref ? bidRequest.site.ref : ''; serverResponse.body.seatbid.forEach(bidderSeat => { - if (!isArray(bidderSeat.bid) || !bidderSeat.bid.length) { + if (!utils.isArray(bidderSeat.bid) || !bidderSeat.bid.length) { return; } bidderSeat.bid.forEach(bid => { let mediaType; // Actually only BANNER is supported, but other types will be added soon. - switch (deepAccess(bid, 'ext.prebid.type')) { + switch (utils.deepAccess(bid, 'ext.prebid.type')) { case 'V': mediaType = VIDEO; break; @@ -713,8 +332,8 @@ export const spec = { const meta = { advertiserDomains: (Array.isArray(bid.adomain) && bid.adomain.length) ? bid.adomain : [], - advertiserName: deepAccess(bid, 'ext.advertiser_name', null), - agencyName: deepAccess(bid, 'ext.agency_name', null), + advertiserName: utils.deepAccess(bid, 'ext.advertiser_name', null), + agencyName: utils.deepAccess(bid, 'ext.agency_name', null), primaryCatId: getPrimaryCatFromResponse(bid.cat), mediaType } @@ -733,38 +352,15 @@ export const spec = { ad: bid.adm, mediaType, burl: bid.burl, - meta: cleanObj(meta) + meta: utils.cleanObj(meta) }; - if (mediaType === NATIVE) { - const native = nativeBidResponseHandler(bid); - if (native) { - newBid.native = native; - } - } - - if (mediaType === VIDEO) { - // Note: - // Mediakeys bid adapter expects a publisher has set his own video player - // in the `mediaTypes.video` configuration object. - - // Mediakeys bidder does not provide inline XML in the bid response - // newBid.vastXml = bid.ext.vast_url; - - // For instream video, disable server cache as vast is generated per bid request - newBid.videoCacheKey = 'no_cache'; - - // The vast URL is server independently and must be fetched before video rendering in the renderer - // appending '&no_cache' is safe and fast as the vast url always have parameters - newBid.vastUrl = bid.ext.vast_url + '&no_cache'; - } - bidResponses.push(newBid); }); }); } } catch (e) { - logError(BIDDER_CODE, e); + utils.logError(BIDDER_CODE, e); } return bidResponses; @@ -777,7 +373,7 @@ export const spec = { const url = bid.burl.replace(/\$\{AUCTION_PRICE\}/, bid.cpm); - triggerPixel(url); + utils.triggerPixel(url); } } diff --git a/modules/mediakeysBidAdapter.md b/modules/mediakeysBidAdapter.md index ec313c2fe3a..75e69659c8a 100644 --- a/modules/mediakeysBidAdapter.md +++ b/modules/mediakeysBidAdapter.md @@ -29,111 +29,3 @@ var adUnits = [ }] }, ``` - -## Native only Ad Unit - -The Mediakeys adapter accepts two optional params for native requests. Please see the [OpenRTB Native Ads Specification](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf) for valid values. - -``` -var adUnits = [ -{ - code: 'test', - mediaTypes: { - native: { - type: 'image', - } - }, - bids: [{ - bidder: 'mediakeys', - params: { - native: { - context: 1, // ORTB Native Context Type IDs. Default `1`. - plcmttype: 1, // ORTB Native Placement Type IDs. Default `1`. - } - } - }] -}, -``` - -## Video only Ad Unit - -The Mediakeys adapter accepts any valid openRTB 2.5 video property. Properties can be defined at the adUnit `mediaTypes.video` or `bid[].params` level. - -### Outstream context - -``` -var adUnits = [ -{ - code: 'test', - mediaTypes: { - video: { - context: 'outstream', - playerSize: [300, 250], - // additional OpenRTB video params - // placement: 2, - // api: [1], - // … - } - }, - renderer: { - url: 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js', - render: function (bid) { - var bidReqConfig = pbjs.adUnits.find(bidReq => bidReq.bidId === bid.impid); - - if (bidReqConfig && bidReqConfig.mediaTypes && bidReqConfig.mediaTypes.video && bidReqConfig.mediaTypes.video.context === 'outstream') { - var adResponse = fetch(bid.vastUrl).then(resp => resp.text()).then(text => ({ - ad: { - video: { - content: text, - player_width: bid.width || bidReqConfig.mediaTypes.video.playerSize[0], - player_height: bid.height || bidReqConfig.mediaTypes.video.playerSize[1], - } - } - })) - - adResponse.then((ad) => { - bid.renderer.push(() => { - ANOutstreamVideo.renderAd({ - targetId: bid.adUnitCode, - adResponse: ad - }); - }); - }) - } - } - }, - bids: [{ - bidder: 'mediakeys', - params: { - video: { - // additional OpenRTB video params. Will be merged with params defined at mediaTypes level - } - } - }] -}, -``` - -### Instream context - -``` -var adUnits = [ -{ - code: 'test', - mediaTypes: { - video: { - context: 'instream', - playerSize: [300, 250], - // additional OpenRTB video params - // placement: 2, - // api: [1], - // … - } - }, - bids: [{ - bidder: 'mediakeys', - params: { - // additional OpenRTB video params. Will be merged with params defined at mediaTypes level - } - }] -}, -``` diff --git a/modules/medianetAnalyticsAdapter.js b/modules/medianetAnalyticsAdapter.js index 09ebbc9bc31..cb65a6afc54 100644 --- a/modules/medianetAnalyticsAdapter.js +++ b/modules/medianetAnalyticsAdapter.js @@ -1,23 +1,11 @@ -import { - _map, - deepAccess, - getWindowTop, - groupBy, - isEmpty, - isPlainObject, - logError, - logInfo, - triggerPixel, - uniques, - getHighestCpm -} from '../src/utils.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; -import {ajax} from '../src/ajax.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import {AUCTION_COMPLETED, AUCTION_IN_PROGRESS, getPriceGranularity} from '../src/auction.js'; -import {includes} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { ajax } from '../src/ajax.js'; +import { getRefererInfo } from '../src/refererDetection.js'; +import { AUCTION_COMPLETED, AUCTION_IN_PROGRESS, getPriceGranularity } from '../src/auction.js'; +import includes from 'core-js-pure/features/array/includes.js'; const analyticsType = 'endpoint'; const ENDPOINT = 'https://pb-logs.media.net/log?logid=kfk&evtid=prebid_analytics_events_client'; @@ -54,10 +42,17 @@ const VALID_URL_KEY = ['canonical_url', 'og_url', 'twitter_url']; const DEFAULT_URL_KEY = 'page'; const LOG_TYPE = { + AP: 'AP', + PR: 'PR', APPR: 'APPR', RA: 'RA' }; +const BATCHING = { + SINGLE: 'SINGLE', + MULTI: 'MULTI' +} + let auctions = {}; let config; let pageDetails; @@ -71,6 +66,7 @@ class ErrorLogger { this.project = 'prebidanalytics'; this.dn = pageDetails.domain || ''; this.requrl = pageDetails.requrl || ''; + this.event = this.event; this.pbversion = PREBID_VERSION; this.cid = config.cid || ''; this.rd = additionalData; @@ -78,7 +74,7 @@ class ErrorLogger { send() { let url = EVENT_PIXEL_URL + '?' + formatQS(this); - triggerPixel(url); + utils.triggerPixel(url); } } @@ -93,10 +89,18 @@ class Configure { this.gdprConsent = undefined; this.gdprApplies = undefined; this.uspConsent = undefined; + this.pixelWaitTime = 0; + this.apLoggingPct = 0; + this.prLoggingPct = 0; + this.batching = BATCHING.SINGLE; this.shouldBeLogged = {}; this.mnetDebugConfig = ''; } + set publisherLper(plper) { + this.pubLper = plper; + } + getLoggingData() { return { cid: this.cid, @@ -135,10 +139,24 @@ class Configure { if (!isNaN(parseInt(response.percentage, 10))) { this.loggingPercent = response.percentage; } + + if (!isNaN(parseInt(response.pixelwaittime, 10))) { + this.pixelWaitTime = response.pixelwaittime; + } + + if (!isNaN(parseInt(response.aplper, 10))) { + this.apLoggingPct = response.aplper; + this.batching = BATCHING.MULTI; + } + + if (!isNaN(parseInt(response.prlper, 10))) { + this.prLoggingPct = response.prlper; + this.batching = BATCHING.MULTI; + } } overrideDomainLevelData(response) { - const domain = deepAccess(response, 'domain.' + pageDetails.domain); + const domain = utils.deepAccess(response, 'domain.' + pageDetails.domain); if (domain) { this.setDataFromResponse(domain); } @@ -161,14 +179,14 @@ class Configure { init() { // Forces Logging % to 100% let urlObj = URL.parseUrl(pageDetails.page); - if (deepAccess(urlObj, 'search.medianet_test') || urlObj.hostname === 'localhost') { + if (utils.deepAccess(urlObj, 'search.medianet_test') || urlObj.hostname === 'localhost') { this.loggingPercent = 100; this.ajaxState = CONFIG_PASS; this.debug = true; return; } - if (deepAccess(urlObj, 'search.mnet_setconfig')) { - this.mnetDebugConfig = deepAccess(urlObj, 'search.mnet_setconfig'); + if (utils.deepAccess(urlObj, 'search.mnet_setconfig')) { + this.mnetDebugConfig = utils.deepAccess(urlObj, 'search.mnet_setconfig'); } ajax( this._configURL(), @@ -213,7 +231,7 @@ class PageDetail { _getAttributeFromSelector(selector, attribute) { try { - let doc = getWindowTop().document; + let doc = utils.getWindowTop().document; let element = doc.querySelector(selector); if (element !== null && element[attribute]) { return element[attribute]; @@ -222,7 +240,7 @@ class PageDetail { } _getAbsoluteUrl(url) { - let aTag = getWindowTop().document.createElement('a'); + let aTag = utils.getWindowTop().document.createElement('a'); aTag.href = url; return aTag.href; @@ -250,14 +268,18 @@ class AdSlot { this.context = context; this.adext = adext; this.logged = {}; + this.logged[LOG_TYPE.PR] = false; + this.logged[LOG_TYPE.AP] = false; + this.logged[LOG_TYPE.APPR] = false; this.targeting = undefined; this.medianetPresent = 0; } getShouldBeLogged(logType) { if (!config.shouldBeLogged.hasOwnProperty(logType)) { - config.shouldBeLogged[logType] = isSampled(); + config.shouldBeLogged[logType] = isSampled(logType); } + config.shouldBeLogged[logType] = isSampled(logType); return config.shouldBeLogged[logType]; } @@ -321,7 +343,7 @@ class Bid { bdp: this.cpm, cbdp: this.dfpbd, dfpbd: this.dfpbd, - szs: this.allMediaTypeSizes.join('|'), + szs: this.allMediaTypeSizes.map(sz => sz.join('x')).join('|'), size: this.size, mtype: this.mediaType, dId: this.dealId, @@ -370,8 +392,8 @@ class Auction { flrdata: this._mergeFieldsToLog({ ln: this.floorData.location, skp: this.floorData.skipped, - enfj: deepAccess(this.floorData, 'enforcements.enforceJS'), - enfd: deepAccess(this.floorData, 'enforcements.floorDeals'), + enfj: utils.deepAccess(this.floorData, 'enforcements.enforceJS'), + enfd: utils.deepAccess(this.floorData, 'enforcements.floorDeals'), sr: this.floorData.skipRate, fs: this.floorData.fetchStatus }), @@ -423,7 +445,7 @@ function auctionInitHandler({auctionId, adUnits, timeout, timestamp, bidderReque auctions[auctionId].auctionInitTime = timestamp; } addAddSlots(auctionId, adUnits, timeout); - const floorData = deepAccess(bidderRequests, '0.bids.0.floorData'); + const floorData = utils.deepAccess(bidderRequests, '0.bids.0.floorData'); if (floorData) { auctions[auctionId].floorData = {...floorData}; } @@ -431,10 +453,10 @@ function auctionInitHandler({auctionId, adUnits, timeout, timestamp, bidderReque function addAddSlots(auctionId, adUnits, tmax) { adUnits = adUnits || []; - const groupedAdUnits = groupBy(adUnits, 'code'); + const groupedAdUnits = utils.groupBy(adUnits, 'code'); Object.keys(groupedAdUnits).forEach((adUnitCode) => { const adUnits = groupedAdUnits[adUnitCode]; - const supplyAdCode = deepAccess(adUnits, '0.adUnitCode') || adUnitCode; + const supplyAdCode = utils.deepAccess(adUnits, '0.adUnitCode') || adUnitCode; let context = ''; let adext = {}; @@ -442,20 +464,21 @@ function addAddSlots(auctionId, adUnits, tmax) { const oSizes = {banner: [], video: []}; adUnits.forEach(({mediaTypes, sizes, ext}) => { mediaTypes = mediaTypes || {}; - adext = Object.assign(adext, ext || deepAccess(mediaTypes, 'banner.ext')); - context = deepAccess(mediaTypes, 'video.context') || context; + adext = Object.assign(adext, ext || utils.deepAccess(mediaTypes, 'banner.ext')); + context = utils.deepAccess(mediaTypes, 'video.context') || context; Object.keys(mediaTypes).forEach((mediaType) => mediaTypeMap[mediaType] = 1); const sizeObject = _getSizes(mediaTypes, sizes); sizeObject.banner.forEach(size => oSizes.banner.push(size)); sizeObject.video.forEach(size => oSizes.video.push(size)); }); - adext = isEmpty(adext) ? undefined : adext; - oSizes.banner = oSizes.banner.filter(uniques); - oSizes.video = oSizes.video.filter(uniques); - oSizes.native = mediaTypeMap.native === 1 ? [[1, 1].join('x')] : []; + adext = utils.isEmpty(adext) ? undefined : adext; + oSizes.banner = oSizes.banner.filter(utils.uniques); + oSizes.video = oSizes.video.filter(utils.uniques); + oSizes.native = mediaTypeMap.native === 1 ? [[1, 1]] : []; const allMediaTypeSizes = [].concat(oSizes.banner, oSizes.native, oSizes.video); const mediaTypes = Object.keys(mediaTypeMap).join('|'); + auctions[auctionId].addSlot({adUnitCode, supplyAdCode, mediaTypes, allMediaTypeSizes, context, tmax, adext}); }); } @@ -480,47 +503,22 @@ function bidRequestedHandler({ auctionId, auctionStart, bids, start, uspConsent, const bidObj = new Bid(bidId, bidder, src, start, adUnitCode, mediaTypes && Object.keys(mediaTypes).join('|'), requestSizes); auctions[auctionId].addBid(bidObj); if (bidder === MEDIANET_BIDDER_CODE) { - bidObj.crid = deepAccess(bid, 'params.crid'); - bidObj.pubcrid = deepAccess(bid, 'params.crid'); + bidObj.crid = utils.deepAccess(bid, 'params.crid'); + bidObj.pubcrid = utils.deepAccess(bid, 'params.crid'); auctions[auctionId].adSlots[adUnitCode].medianetPresent = 1; } }); } function _getSizes(mediaTypes, sizes) { - const banner = deepAccess(mediaTypes, 'banner.sizes') || sizes || []; - const native = deepAccess(mediaTypes, 'native') ? [[1, 1]] : []; - const playerSize = deepAccess(mediaTypes, 'video.playerSize') || []; + const banner = utils.deepAccess(mediaTypes, 'banner.sizes') || sizes || []; + const native = utils.deepAccess(mediaTypes, 'native') ? [[1, 1]] : []; + const playerSize = utils.deepAccess(mediaTypes, 'video.playerSize') || []; let video = []; if (playerSize.length === 2) { video = [playerSize] } - return { - banner: banner.map(size => size.join('x')), - native: native.map(size => size.join('x')), - video: video.map(size => size.join('x')) - } -} - -/* - - The code is used to determine if the current bid is higher than the previous bid. - - If it is, then the code will return true and if not, it will return false. - */ -function canSelectCurrentBid(previousBid, currentBid) { - if (!(previousBid instanceof Bid)) return false; - - // For first bid response the previous bid will be containing bid request obj - // in which the cpm would be undefined so the current bid can directly be selected. - const isFirstBidResponse = previousBid.cpm === undefined && currentBid.cpm !== undefined; - if (isFirstBidResponse) return true; - - // if there are 2 bids, get the highest bid - const selectedBid = getHighestCpm(previousBid, currentBid); - - // Return true if selectedBid is currentBid, - // The timeToRespond field is used as an identifier for distinguishing - // between the current iterating bid and the previous bid. - return selectedBid.timeToRespond === currentBid.timeToRespond; + return { banner, native, video } } function bidResponseHandler(bid) { @@ -531,7 +529,7 @@ function bidResponseHandler(bid) { return; } let bidObj = auctions[auctionId].findBid('bidId', requestId); - if (!canSelectCurrentBid(bidObj, bid)) { + if (!(bidObj instanceof Bid)) { return; } Object.assign( @@ -539,12 +537,12 @@ function bidResponseHandler(bid) { { cpm, width, height, mediaType, timeToRespond, dealId, creativeId }, { adId, currency } ); - bidObj.floorPrice = deepAccess(bid, 'floorData.floorValue'); - bidObj.floorRule = deepAccess(bid, 'floorData.floorRule'); + bidObj.floorPrice = utils.deepAccess(bid, 'floorData.floorValue'); + bidObj.floorRule = utils.deepAccess(bid, 'floorData.floorRule'); bidObj.originalCpm = originalCpm || cpm; - let dfpbd = deepAccess(bid, 'adserverTargeting.hb_pb'); + let dfpbd = utils.deepAccess(bid, 'adserverTargeting.hb_pb'); if (!dfpbd) { - let priceGranularity = getPriceGranularity(bid); + let priceGranularity = getPriceGranularity(mediaType, bid); let priceGranularityKey = PRICE_GRANULARITY[priceGranularity]; dfpbd = bid[priceGranularityKey] || cpm; } @@ -595,12 +593,18 @@ function bidTimeoutHandler(timedOutBids) { }) } -function auctionEndHandler({auctionId, auctionEnd}) { +function auctionEndHandler({auctionId, auctionEnd, adUnitCodes}) { if (!(auctions[auctionId] instanceof Auction)) { return; } auctions[auctionId].status = AUCTION_COMPLETED; auctions[auctionId].auctionEndTime = auctionEnd; + + if (config.batching === BATCHING.MULTI) { + adUnitCodes.forEach(function (adUnitCode) { + sendEvent(auctionId, adUnitCode, LOG_TYPE.PR); + }); + } } function setTargetingHandler(params) { @@ -631,15 +635,34 @@ function setTargetingHandler(params) { auctionObj.bids.forEach(bid => { if (bid.bidder === DUMMY_BIDDER && bid.adUnitCode === adunit) { bid.iwb = bidAdIds.length === 0 ? 0 : 1; - bid.width = deepAccess(winningBid, 'width'); - bid.height = deepAccess(winningBid, 'height'); + bid.width = utils.deepAccess(winningBid, 'width'); + bid.height = utils.deepAccess(winningBid, 'height'); } }); - sendEvent(auctionId, adunit, LOG_TYPE.APPR); + sendEvent(auctionId, adunit, getLogType()); } } } +function getLogType() { + if (config.batching === BATCHING.SINGLE) { + return LOG_TYPE.APPR; + } + return LOG_TYPE.AP; +} + +function setBidderDone(params) { + if (config.pixelWaitTime != null && config.pixelWaitTime > 0) { + setTimeout(fireApAfterWait, config.pixelWaitTime, params) + } +} + +function fireApAfterWait(params) { + params.bids.forEach(function (adUnit) { + sendEvent(params.auctionId, adUnit.adUnitCode, LOG_TYPE.AP); + }); +} + function bidWonHandler(bid) { const { requestId, auctionId, adUnitCode } = bid; if (!(auctions[auctionId] instanceof Auction)) { @@ -654,8 +677,20 @@ function bidWonHandler(bid) { sendEvent(auctionId, adUnitCode, LOG_TYPE.RA); } -function isSampled() { - return Math.random() * 100 < parseFloat(config.loggingPercent); +function isSampled(logType) { + return Math.random() * 100 < parseFloat(getLogPercentage(logType)); +} + +function getLogPercentage(logType) { + let logPercentage = config.loggingPercent; + if (config.batching === BATCHING.MULTI) { + if (logType === LOG_TYPE.AP) { + logPercentage = config.apLoggingPct; + } else if (logType === LOG_TYPE.PR) { + logPercentage = config.prLoggingPct; + } + } + return logPercentage; } function isValidAuctionAdSlot(acid, adtag) { @@ -676,8 +711,13 @@ function sendEvent(id, adunit, logType) { function fireApPrLog(auctionId, adUnitName, logType) { const adSlot = auctions[auctionId].adSlots[adUnitName]; if (adSlot.getShouldBeLogged(logType) && !adSlot.logged[logType]) { + if (config.batching === BATCHING.SINGLE) { + adSlot.logged[LOG_TYPE.AP] = true; + adSlot.logged[LOG_TYPE.PR] = true; + } else { + adSlot.logged[logType] = true; + } fireAuctionLog(auctionId, adUnitName, logType); - adSlot.logged[logType] = true; } } @@ -691,7 +731,7 @@ function getCommonLoggingData(acid, adtag) { function fireAuctionLog(acid, adtag, logType) { let commonParams = getCommonLoggingData(acid, adtag); commonParams.lgtp = logType; - let targeting = deepAccess(commonParams, 'targ'); + let targeting = utils.deepAccess(commonParams, 'targ'); Object.keys(commonParams).forEach((key) => (commonParams[key] == null) && delete commonParams[key]); delete commonParams.targ; @@ -719,11 +759,11 @@ function fireAuctionLog(acid, adtag, logType) { } function formatQS(data) { - return _map(data, (value, key) => { + return utils._map(data, (value, key) => { if (value === undefined) { return key + '='; } - if (isPlainObject(value)) { + if (utils.isPlainObject(value)) { value = JSON.stringify(value); } return key + '=' + encodeURIComponent(value); @@ -732,7 +772,7 @@ function formatQS(data) { function firePixel(qs) { logsQueue.push(ENDPOINT + '&' + qs); - triggerPixel(ENDPOINT + '&' + qs); + utils.triggerPixel(ENDPOINT + '&' + qs); } class URL { @@ -773,7 +813,7 @@ let medianetAnalytics = Object.assign(adapter({URL, analyticsType}), { }, track({ eventType, args }) { if (config.debug) { - logInfo(eventType, args); + utils.logInfo(eventType, args); } switch (eventType) { case CONSTANTS.EVENTS.AUCTION_INIT: { @@ -804,6 +844,10 @@ let medianetAnalytics = Object.assign(adapter({URL, analyticsType}), { setTargetingHandler(args); break; } + case CONSTANTS.EVENTS.BIDDER_DONE : { + setBidderDone(args); + break; + } case CONSTANTS.EVENTS.BID_WON: { bidWonHandler(args); break; @@ -815,7 +859,7 @@ medianetAnalytics.originEnableAnalytics = medianetAnalytics.enableAnalytics; medianetAnalytics.enableAnalytics = function (configuration) { if (!configuration || !configuration.options || !configuration.options.cid) { - logError('Media.net Analytics adapter: cid is required.'); + utils.logError('Media.net Analytics adapter: cid is required.'); return; } $$PREBID_GLOBAL$$.medianetGlobals = $$PREBID_GLOBAL$$.medianetGlobals || {}; @@ -824,7 +868,7 @@ medianetAnalytics.enableAnalytics = function (configuration) { pageDetails = new PageDetail(); config = new Configure(configuration.options.cid); - config.pubLper = configuration.options.sampling || ''; + config.publisherLper = configuration.options.sampling || ''; config.init(); configuration.options.sampling = 1; medianetAnalytics.originEnableAnalytics(configuration); diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index db3921c9a47..3b7e555cc72 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -1,5 +1,5 @@ -import { parseUrl, getWindowTop, isArray, getGptSlotInfoForAdUnitCode, isStr, deepAccess, isEmpty, logError, triggerPixel, buildUrl, isEmptyStr, logInfo } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { getRefererInfo } from '../src/refererDetection.js'; @@ -27,7 +27,7 @@ window.mnet = window.mnet || {}; window.mnet.queue = window.mnet.queue || []; mnData.urlData = { - domain: parseUrl(refererInfo.referer).hostname, + domain: utils.parseUrl(refererInfo.referer).hostname, page: refererInfo.referer, isTop: refererInfo.reachedTop } @@ -78,7 +78,7 @@ function getUrlFromSelector(selector, attribute) { function getAttributeFromSelector(selector, attribute) { try { - let doc = getWindowTop().document; + let doc = utils.getWindowTop().document; let element = doc.querySelector(selector); if (element !== null && element[attribute]) { return element[attribute]; @@ -87,7 +87,7 @@ function getAttributeFromSelector(selector, attribute) { } function getAbsoluteUrl(url) { - let aTag = getWindowTop().document.createElement('a'); + let aTag = utils.getWindowTop().document.createElement('a'); aTag.href = url; return aTag.href; @@ -98,7 +98,7 @@ function filterUrlsByType(urls, type) { } function transformSizes(sizes) { - if (isArray(sizes) && sizes.length === 2 && !isArray(sizes[0])) { + if (utils.isArray(sizes) && sizes.length === 2 && !utils.isArray(sizes[0])) { return [getSize(sizes)]; } @@ -123,8 +123,8 @@ function getCoordinates(adUnitCode) { let element = document.getElementById(adUnitCode); if (!element && adUnitCode.indexOf('/') !== -1) { // now it means that adUnitCode is GAM AdUnitPath - const {divId} = getGptSlotInfoForAdUnitCode(adUnitCode); - if (isStr(divId)) { + const {divId} = utils.getGptSlotInfoForAdUnitCode(adUnitCode); + if (utils.isStr(divId)) { element = document.getElementById(divId); } } @@ -145,11 +145,11 @@ function getCoordinates(adUnitCode) { } function extParams(bidRequest, bidderRequests) { - const params = deepAccess(bidRequest, 'params'); - const gdpr = deepAccess(bidderRequests, 'gdprConsent'); - const uspConsent = deepAccess(bidderRequests, 'uspConsent'); - const userId = deepAccess(bidRequest, 'userId'); - const sChain = deepAccess(bidRequest, 'schain') || {}; + const params = utils.deepAccess(bidRequest, 'params'); + const gdpr = utils.deepAccess(bidderRequests, 'gdprConsent'); + const uspConsent = utils.deepAccess(bidderRequests, 'uspConsent'); + const userId = utils.deepAccess(bidRequest, 'userId'); + const sChain = utils.deepAccess(bidRequest, 'schain') || {}; const windowSize = spec.getWindowSize(); const gdprApplies = !!(gdpr && gdpr.gdprApplies); const uspApplies = !!(uspConsent); @@ -165,7 +165,7 @@ function extParams(bidRequest, bidderRequests) { windowSize.w !== -1 && windowSize.h !== -1 && { screen: windowSize }, userId && { user_id: userId }, $$PREBID_GLOBAL$$.medianetGlobals.analyticsEnabled && { analytics: true }, - !isEmpty(sChain) && {schain: sChain} + !utils.isEmpty(sChain) && {schain: sChain} ); } @@ -179,18 +179,13 @@ function slotParams(bidRequest) { }, all: bidRequest.params }; + let bannerSizes = utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes') || []; - if (bidRequest.ortb2Imp) { - params.ortb2Imp = bidRequest.ortb2Imp; - } - - let bannerSizes = deepAccess(bidRequest, 'mediaTypes.banner.sizes') || []; - - const videoInMediaType = deepAccess(bidRequest, 'mediaTypes.video') || {}; - const videoInParams = deepAccess(bidRequest, 'params.video') || {}; + const videoInMediaType = utils.deepAccess(bidRequest, 'mediaTypes.video') || {}; + const videoInParams = utils.deepAccess(bidRequest, 'params.video') || {}; const videoCombinedObj = Object.assign({}, videoInParams, videoInMediaType); - if (!isEmpty(videoCombinedObj)) { + if (!utils.isEmpty(videoCombinedObj)) { params.video = videoCombinedObj; } @@ -201,7 +196,7 @@ function slotParams(bidRequest) { try { params.native = JSON.stringify(bidRequest.nativeParams); } catch (e) { - logError((`${BIDDER_CODE} : Incorrect JSON : bidRequest.nativeParams`)); + utils.logError((`${BIDDER_CODE} : Incorrect JSON : bidRequest.nativeParams`)); } } @@ -319,8 +314,8 @@ function isValidBid(bid) { } function fetchCookieSyncUrls(response) { - if (!isEmpty(response) && response[0].body && - response[0].body.ext && isArray(response[0].body.ext.csUrl)) { + if (!utils.isEmpty(response) && response[0].body && + response[0].body.ext && utils.isArray(response[0].body.ext.csUrl)) { return response[0].body.ext.csUrl; } @@ -328,15 +323,15 @@ function fetchCookieSyncUrls(response) { } function getLoggingData(event, data) { - data = (isArray(data) && data) || []; + data = (utils.isArray(data) && data) || []; let params = {}; params.logid = 'kfk'; params.evtid = 'projectevents'; params.project = 'prebid'; - params.acid = deepAccess(data, '0.auctionId') || ''; + params.acid = utils.deepAccess(data, '0.auctionId') || ''; params.cid = $$PREBID_GLOBAL$$.medianetGlobals.cid || ''; - params.crid = data.map((adunit) => deepAccess(adunit, 'params.0.crid') || adunit.adUnitCode).join('|'); + params.crid = data.map((adunit) => utils.deepAccess(adunit, 'params.0.crid') || adunit.adUnitCode).join('|'); params.adunit_count = data.length || 0; params.dn = mnData.urlData.domain || ''; params.requrl = mnData.urlData.page || ''; @@ -354,7 +349,7 @@ function logEvent (event, data) { hostname: EVENT_PIXEL_URL, search: getLoggingData(event, data) }; - triggerPixel(buildUrl(getParams)); + utils.triggerPixel(utils.buildUrl(getParams)); } function clearMnData() { @@ -362,8 +357,8 @@ function clearMnData() { } function addRenderer(bid) { - const videoContext = deepAccess(bid, 'context') || ''; - const vastTimeout = deepAccess(bid, 'vto'); + const videoContext = utils.deepAccess(bid, 'context') || ''; + const vastTimeout = utils.deepAccess(bid, 'vto'); /* Adding renderer only when the context is Outstream and the provider has responded with a renderer. */ @@ -389,7 +384,7 @@ function newVideoRenderer(bid) { mute: bid.mt } const adUnitCode = bid.dfp_id; - const divId = getGptSlotInfoForAdUnitCode(adUnitCode).divId || adUnitCode; + const divId = utils.getGptSlotInfoForAdUnitCode(adUnitCode).divId || adUnitCode; window.mnet.mediaNetoutstreamPlayer(bid, divId, obj); }); }); @@ -410,12 +405,12 @@ export const spec = { */ isBidRequestValid: function(bid) { if (!bid.params) { - logError(`${BIDDER_CODE} : Missing bid parameters`); + utils.logError(`${BIDDER_CODE} : Missing bid parameters`); return false; } - if (!bid.params.cid || !isStr(bid.params.cid) || isEmptyStr(bid.params.cid)) { - logError(`${BIDDER_CODE} : cid should be a string`); + if (!bid.params.cid || !utils.isStr(bid.params.cid) || utils.isEmptyStr(bid.params.cid)) { + utils.logError(`${BIDDER_CODE} : cid should be a string`); return false; } @@ -450,13 +445,13 @@ export const spec = { let validBids = []; if (!serverResponse || !serverResponse.body) { - logInfo(`${BIDDER_CODE} : response is empty`); + utils.logInfo(`${BIDDER_CODE} : response is empty`); return validBids; } let bids = serverResponse.body.bidList; - if (!isArray(bids) || bids.length === 0) { - logInfo(`${BIDDER_CODE} : no bids`); + if (!utils.isArray(bids) || bids.length === 0) { + utils.logInfo(`${BIDDER_CODE} : no bids`); return validBids; } validBids = bids.filter(bid => isValidBid(bid)); diff --git a/modules/medianetRtdProvider.js b/modules/medianetRtdProvider.js index 07b1d66fbc5..77889db5ff2 100644 --- a/modules/medianetRtdProvider.js +++ b/modules/medianetRtdProvider.js @@ -1,7 +1,7 @@ -import {insertElement, isEmptyStr, isFn, isStr, logError, mergeDeep} from '../src/utils.js'; -import {submodule} from '../src/hook.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import {includes} from '../src/polyfill.js'; +import { submodule } from '../src/hook.js'; +import * as utils from '../src/utils.js'; +import { getGlobal } from '../src/prebidGlobal.js'; +import includes from 'core-js-pure/features/array/includes.js'; const MODULE_NAME = 'medianet'; const SOURCE = MODULE_NAME + 'rtd'; @@ -15,8 +15,8 @@ window.mnjs.que = window.mnjs.que || []; function init(config) { const customerId = config.params && config.params.cid; - if (!customerId || !isStr(customerId) || isEmptyStr(customerId)) { - logError(`${SOURCE}: cid should be a string`); + if (!customerId || !utils.isStr(customerId) || utils.isEmptyStr(customerId)) { + utils.logError(`${SOURCE}: cid should be a string`); return false; } @@ -40,8 +40,8 @@ function getBidRequestData(requestBidsProps, callback, config, userConsent) { const success = (adUnitProps, openRtbProps) => { adUnits.forEach(adUnit => { adUnit[OPEN_RTB_FIELD] = adUnit[OPEN_RTB_FIELD] || {}; - mergeDeep(adUnit[OPEN_RTB_FIELD], openRtbProps[adUnit.code]); - mergeDeep(adUnit, adUnitProps[adUnit.code]); + utils.mergeDeep(adUnit[OPEN_RTB_FIELD], openRtbProps[adUnit.code]); + utils.mergeDeep(adUnit, adUnitProps[adUnit.code]); }); callback(); }; @@ -61,7 +61,7 @@ function onAuctionInitEvent(auctionInit) { function getTargetingData(adUnitCode) { const adUnits = getAdUnits(undefined, adUnitCode); let targetingData = {}; - if (window.mnjs.loaded && isFn(window.mnjs.getTargetingData)) { + if (window.mnjs.loaded && utils.isFn(window.mnjs.getTargetingData)) { targetingData = window.mnjs.getTargetingData(adUnitCode, adUnits, SOURCE) || {}; } const targeting = {}; @@ -86,7 +86,7 @@ function loadRtdScript(customerId) { script.type = 'text/javascript'; script.async = true; script.src = getClientUrl(customerId, window.location.hostname); - insertElement(script, window.document, 'head'); + utils.insertElement(script, window.document, 'head'); } function getAdUnits(adUnits, adUnitCodes) { diff --git a/modules/mediasniperBidAdapter.js b/modules/mediasniperBidAdapter.js deleted file mode 100644 index 3e57503f7fb..00000000000 --- a/modules/mediasniperBidAdapter.js +++ /dev/null @@ -1,335 +0,0 @@ -import { - deepAccess, - deepClone, - deepSetValue, - getWindowTop, - inIframe, - isArray, - isEmpty, - isFn, - isNumber, - isStr, - logWarn, - logError, - logMessage, - parseUrl, - getBidIdParameter, - triggerPixel, -} from '../src/utils.js'; - -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER } from '../src/mediaTypes.js'; - -const BIDDER_CODE = 'mediasniper'; -const DEFAULT_BID_TTL = 360; -const DEFAULT_CURRENCY = 'RUB'; -const DEFAULT_NET_REVENUE = true; -const ENDPOINT = 'https://sapi.bumlam.com/prebid/'; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER], - - isBidRequestValid: function (bid) { - logMessage('Hello!! bid: ', JSON.stringify(bid)); - - if (!bid || isEmpty(bid)) { - return false; - } - - if (!bid.params || isEmpty(bid.params)) { - return false; - } - - if (!isStr(bid.params.placementId) && !isNumber(bid.params.placementId)) { - return false; - } - - const banner = deepAccess(bid, 'mediaTypes.banner', {}); - if (!banner || isEmpty(banner)) { - return false; - } - - const sizes = deepAccess(bid, 'mediaTypes.banner.sizes', []); - if (!isArray(sizes) || isEmpty(sizes)) { - return false; - } - - return true; - }, - - buildRequests: function (validBidRequests, bidderRequest) { - const payload = createOrtbTemplate(); - - deepSetValue(payload, 'id', bidderRequest.auctionId); - - validBidRequests.forEach((validBid) => { - let bid = deepClone(validBid); - - const imp = createImp(bid); - payload.imp.push(imp); - }); - - // params - const siteId = getBidIdParameter('siteid', validBidRequests[0].params) + ''; - deepSetValue(payload, 'site.id', siteId); - - // Assign payload.site from refererinfo - if (bidderRequest.refererInfo) { - if (bidderRequest.refererInfo.reachedTop) { - const sitePage = bidderRequest.refererInfo.referer; - deepSetValue(payload, 'site.page', sitePage); - deepSetValue( - payload, - 'site.domain', - parseUrl(sitePage, { - noDecodeWholeURL: true, - }).hostname - ); - - if (canAccessTopWindow()) { - deepSetValue(payload, 'site.ref', getWindowTop().document.referrer); - } - } - } - - const request = { - method: 'POST', - url: ENDPOINT, - data: JSON.stringify(payload), - }; - - return request; - }, - - interpretResponse(serverResponse, bidRequest) { - const bidResponses = []; - - try { - if ( - serverResponse.body && - serverResponse.body.seatbid && - isArray(serverResponse.body.seatbid) - ) { - serverResponse.body.seatbid.forEach((bidderSeat) => { - if (!isArray(bidderSeat.bid) || !bidderSeat.bid.length) { - return; - } - - bidderSeat.bid.forEach((bid) => { - const newBid = { - requestId: bid.impid, - bidderCode: spec.code, - cpm: bid.price || 0, - width: bid.w, - height: bid.h, - creativeId: bid.crid || bid.adid || bid.id, - dealId: bid.dealid || null, - currency: serverResponse.body.cur || DEFAULT_CURRENCY, - netRevenue: DEFAULT_NET_REVENUE, - ttl: DEFAULT_BID_TTL, // seconds. https://docs.prebid.org/dev-docs/faq.html#does-prebidjs-cache-bids - ad: bid.adm, - mediaType: BANNER, - burl: bid.nurl, - meta: { - advertiserDomains: - Array.isArray(bid.adomain) && bid.adomain.length - ? bid.adomain - : [], - mediaType: BANNER, - }, - }; - - logMessage('answer: ', JSON.stringify(newBid)); - - bidResponses.push(newBid); - }); - }); - } - } catch (e) { - logError(BIDDER_CODE, e); - } - - return bidResponses; - }, - - onBidWon: function (bid) { - if (!bid.burl) { - return; - } - - const url = bid.burl.replace(/\$\{AUCTION_PRICE\}/, bid.cpm); - - triggerPixel(url); - }, -}; -registerBidder(spec); - -/** - * Detects the capability to reach window.top. - * - * @returns {boolean} - */ -function canAccessTopWindow() { - try { - return !!getWindowTop().location.href; - } catch (error) { - return false; - } -} - -/** - * Returns an openRTB 2.5 object. - * This one will be populated at each step of the buildRequest process. - * - * @returns {object} - */ -function createOrtbTemplate() { - return { - id: '', - cur: [DEFAULT_CURRENCY], - imp: [], - site: {}, - device: { - ip: '', - js: 1, - ua: navigator.userAgent, - }, - user: {}, - }; -} - -/** - * Create the OpenRTB 2.5 imp object. - * - * @param {*} bid Prebid bid object from request - * @returns - */ -function createImp(bid) { - let placementId = ''; - if (isStr(bid.params.placementId)) { - placementId = bid.params.placementId; - } else if (isNumber(bid.params.placementId)) { - placementId = bid.params.placementId.toString(); - } - - const imp = { - id: bid.bidId, - tagid: placementId, - bidfloorcur: DEFAULT_CURRENCY, - secure: 1, - }; - - // There is no default floor. bidfloor is set only - // if the priceFloors module is activated and returns a valid floor. - const floor = getMinFloor(bid); - if (isNumber(floor)) { - imp.bidfloor = floor; - } - - // Only supports proper mediaTypes definition… - for (let mediaType in bid.mediaTypes) { - switch (mediaType) { - case BANNER: - imp.banner = createBannerImp(bid); - break; - } - } - - // dealid - const dealId = getBidIdParameter('dealid', bid.params); - if (dealId) { - imp.pmp = { - private_auction: 1, - deals: [ - { - id: dealId, - bidfloor: floor || 0, - bidfloorcur: DEFAULT_CURRENCY, - }, - ], - }; - } - - return imp; -} - -/** - * Returns floor from priceFloors module or MediaKey default value. - * - * @param {*} bid a Prebid.js bid (request) object - * @param {string} mediaType the mediaType or the wildcard '*' - * @param {string|array} size the size array or the wildcard '*' - * @returns {number|boolean} - */ -function getFloor(bid, mediaType, size = '*') { - if (!isFn(bid.getFloor)) { - return false; - } - - if (spec.supportedMediaTypes.indexOf(mediaType) === -1) { - logWarn( - `${BIDDER_CODE}: Unable to detect floor price for unsupported mediaType ${mediaType}. No floor will be used.` - ); - return false; - } - - const floor = bid.getFloor({ - currency: DEFAULT_CURRENCY, - mediaType, - size, - }); - - return !isNaN(floor.floor) && floor.currency === DEFAULT_CURRENCY - ? floor.floor - : false; -} - -function getMinFloor(bid) { - const floors = []; - - for (let mediaType in bid.mediaTypes) { - const floor = getFloor(bid, mediaType); - - if (isNumber(floor)) { - floors.push(floor); - } - } - - if (!floors.length) { - return false; - } - - return floors.reduce((a, b) => { - return Math.min(a, b); - }); -} - -/** - * Returns an openRtb 2.5 banner object. - * - * @param {object} bid Prebid bid object from request - * @returns {object} - */ -function createBannerImp(bid) { - let sizes = bid.mediaTypes.banner.sizes; - const params = deepAccess(bid, 'params', {}); - - const banner = {}; - - banner.w = parseInt(sizes[0][0], 10); - banner.h = parseInt(sizes[0][1], 10); - - const format = []; - sizes.forEach(function (size) { - if (size.length && size.length > 1) { - format.push({ w: size[0], h: size[1] }); - } - }); - banner.format = format; - - banner.topframe = inIframe() ? 0 : 1; - banner.pos = params.pos || 0; - - return banner; -} diff --git a/modules/mediasniperBidAdapter.md b/modules/mediasniperBidAdapter.md deleted file mode 100644 index e47513c7fb2..00000000000 --- a/modules/mediasniperBidAdapter.md +++ /dev/null @@ -1,31 +0,0 @@ -# Overview - -``` -Module Name: Mediasniper Bid Adapter -Module Type: Bidder Adapter -Maintainer: oleg@rtbtech.org -``` - -# Description - -Connects to Mediasniper demand source to fetch bids. - -# Test Parameters - -``` -var adUnits = [ -{ - code: 'test', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]], - } - }, - bids: [{ - bidder: 'mediasniper', - params: { - placementId: "123456" - } - }] -}, -``` diff --git a/modules/mediasquareBidAdapter.js b/modules/mediasquareBidAdapter.js index 427a16f1341..e442b01a115 100644 --- a/modules/mediasquareBidAdapter.js +++ b/modules/mediasquareBidAdapter.js @@ -7,11 +7,11 @@ const BIDDER_CODE = 'mediasquare'; const BIDDER_URL_PROD = 'https://pbs-front.mediasquare.fr/' const BIDDER_URL_TEST = 'https://bidder-test.mediasquare.fr/' const BIDDER_ENDPOINT_AUCTION = 'msq_prebid'; +const BIDDER_ENDPOINT_SYNC = 'cookie_sync'; const BIDDER_ENDPOINT_WINNING = 'winning'; export const spec = { code: BIDDER_CODE, - gvlid: 791, aliases: ['msq'], // short code supportedMediaTypes: [BANNER, NATIVE, VIDEO], /** @@ -32,16 +32,10 @@ export const spec = { buildRequests: function(validBidRequests, bidderRequest) { let codes = []; let endpoint = document.location.search.match(/msq_test=true/) ? BIDDER_URL_TEST : BIDDER_URL_PROD; - let floor = {}; const test = config.getConfig('debug') ? 1 : 0; let adunitValue = null; Object.keys(validBidRequests).forEach(key => { adunitValue = validBidRequests[key]; - if (typeof adunitValue.getFloor === 'function') { - floor = adunitValue.getFloor({currency: 'EUR', mediaType: '*', size: '*'}); - } else { - floor = {}; - } codes.push({ owner: adunitValue.params.owner, code: adunitValue.params.code, @@ -49,14 +43,12 @@ export const spec = { bidId: adunitValue.bidId, auctionId: adunitValue.auctionId, transactionId: adunitValue.transactionId, - mediatypes: adunitValue.mediaTypes, - floor: floor + mediatypes: adunitValue.mediaTypes }); }); const payload = { codes: codes, - referer: encodeURIComponent(bidderRequest.refererInfo.referer), - pbjs: '$prebid.version$' + referer: encodeURIComponent(bidderRequest.refererInfo.referer) }; if (bidderRequest) { // modules informations (gdpr, ccpa, schain, userId) if (bidderRequest.gdprConsent) { @@ -117,9 +109,6 @@ export const spec = { if ('match' in value) { bidResponse['mediasquare']['match'] = value['match']; } - if ('hasConsent' in value) { - bidResponse['mediasquare']['hasConsent'] = value['hasConsent']; - } if ('native' in value) { bidResponse['native'] = value['native']; bidResponse['mediaType'] = 'native'; @@ -143,11 +132,18 @@ export const spec = { * @return {UserSync[]} The user syncs which should be dropped. */ getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { + let params = ''; + let endpoint = document.location.search.match(/msq_test=true/) ? BIDDER_URL_TEST : BIDDER_URL_PROD; if (typeof serverResponses === 'object' && serverResponses != null && serverResponses.length > 0 && serverResponses[0].hasOwnProperty('body') && serverResponses[0].body.hasOwnProperty('cookies') && typeof serverResponses[0].body.cookies === 'object') { return serverResponses[0].body.cookies; } else { - return []; + if (gdprConsent && typeof gdprConsent.consentString === 'string') { params += typeof gdprConsent.gdprApplies === 'boolean' ? `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}` : `&gdpr_consent=${gdprConsent.consentString}`; } + if (uspConsent && typeof uspConsent === 'string') { params += '&uspConsent=' + uspConsent } + return { + type: 'iframe', + url: endpoint + BIDDER_ENDPOINT_SYNC + '?type=iframe' + params + }; } }, @@ -157,22 +153,19 @@ export const spec = { */ onBidWon: function(bid) { // fires a pixel to confirm a winning bid - let params = {'pbjs': '$prebid.version$'}; + let params = []; let endpoint = document.location.search.match(/msq_test=true/) ? BIDDER_URL_TEST : BIDDER_URL_PROD; let paramsToSearchFor = ['cpm', 'size', 'mediaType', 'currency', 'creativeId', 'adUnitCode', 'timeToRespond', 'requestId', 'auctionId'] if (bid.hasOwnProperty('mediasquare')) { - if (bid['mediasquare'].hasOwnProperty('bidder')) { params['bidder'] = bid['mediasquare']['bidder']; } - if (bid['mediasquare'].hasOwnProperty('code')) { params['code'] = bid['mediasquare']['code']; } - if (bid['mediasquare'].hasOwnProperty('match')) { params['match'] = bid['mediasquare']['match']; } - if (bid['mediasquare'].hasOwnProperty('hasConsent')) { params['hasConsent'] = bid['mediasquare']['hasConsent']; } + if (bid['mediasquare'].hasOwnProperty('bidder')) { params.push('bidder=' + bid['mediasquare']['bidder']); } + if (bid['mediasquare'].hasOwnProperty('code')) { params.push('code=' + bid['mediasquare']['code']); } + if (bid['mediasquare'].hasOwnProperty('match')) { params.push('match=' + bid['mediasquare']['match']); } }; for (let i = 0; i < paramsToSearchFor.length; i++) { - if (bid.hasOwnProperty(paramsToSearchFor[i])) { - params[paramsToSearchFor[i]] = bid[paramsToSearchFor[i]]; - if (typeof params[paramsToSearchFor[i]] == 'number') { params[paramsToSearchFor[i]] = params[paramsToSearchFor[i]].toString() } - } + if (bid.hasOwnProperty(paramsToSearchFor[i])) { params.push(paramsToSearchFor[i] + '=' + bid[paramsToSearchFor[i]]); } } - ajax(endpoint + BIDDER_ENDPOINT_WINNING, null, JSON.stringify(params), {method: 'POST', withCredentials: true}); + if (params.length > 0) { params = '?' + params.join('&'); } + ajax(endpoint + BIDDER_ENDPOINT_WINNING + params, null, undefined, {method: 'GET', withCredentials: true}); return true; } diff --git a/modules/merkleIdSystem.js b/modules/merkleIdSystem.js index 352c2d074e8..4ab29ec6f68 100644 --- a/modules/merkleIdSystem.js +++ b/modules/merkleIdSystem.js @@ -5,8 +5,8 @@ * @requires module:modules/userId */ -import { logInfo, logError, logWarn } from '../src/utils.js'; -import * as ajaxLib from '../src/ajax.js'; +import * as utils from '../src/utils.js' +import {ajax} from '../src/ajax.js'; import {submodule} from '../src/hook.js' import {getStorageManager} from '../src/storageManager.js'; @@ -34,7 +34,7 @@ function setCookie(name, value, expires) { } function setSession(storage, response) { - logInfo('Merkle setting session '); + utils.logInfo('Merkle setting session '); if (response && response.c && response.c.value && typeof response.c.value === 'string') { setCookie(SESSION_COOKIE_NAME, response.c.value, storage.expires); } @@ -42,11 +42,11 @@ function setSession(storage, response) { function constructUrl(configParams) { const session = getSession(configParams); - let url = configParams.endpoint + `?vendor=${configParams.vendor}&sv_cid=${configParams.sv_cid}&sv_domain=${configParams.sv_domain}&sv_pubid=${configParams.sv_pubid}`; + let url = ID_URL + `?vendor=${configParams.vendor}&sv_cid=${configParams.sv_cid}&sv_domain=${configParams.sv_domain}&sv_pubid=${configParams.sv_pubid}`; if (session) { url = `${url}&sv_session=${session}`; } - logInfo('Merkle url :' + url); + utils.logInfo('Merkle url :' + url); return url; } @@ -54,31 +54,30 @@ function generateId(configParams, configStorage) { const url = constructUrl(configParams); const resp = function (callback) { - ajaxLib.ajaxBuilder()( - url, - response => { + const callbacks = { + success: response => { let responseObj; if (response) { try { responseObj = JSON.parse(response); setSession(configStorage, responseObj) - logInfo('Merkle responseObj ' + JSON.stringify(responseObj)); + utils.logInfo('Merkle responseObj ' + JSON.stringify(responseObj)); } catch (error) { - logError(error); + utils.logError(error); } } const date = new Date().toUTCString(); responseObj.date = date; - logInfo('Merkle responseObj with date ' + JSON.stringify(responseObj)); + utils.logInfo('Merkle responseObj with date ' + JSON.stringify(responseObj)); callback(responseObj); }, - error => { - logError(`${MODULE_NAME}: merkleId fetch encountered an error`, error); + error: error => { + utils.logError(`${MODULE_NAME}: merkleId fetch encountered an error`, error); callback(); - }, - {method: 'GET', withCredentials: true} - ); + } + }; + ajax(url, callbacks, undefined, {method: 'GET', withCredentials: true}); }; return resp; } @@ -98,7 +97,7 @@ export const merkleIdSubmodule = { */ decode(value) { const id = (value && value.pam_id && typeof value.pam_id.id === 'string') ? value.pam_id : undefined; - logInfo('Merkle id ' + JSON.stringify(id)); + utils.logInfo('Merkle id ' + JSON.stringify(id)); return id ? {'merkleId': id} : undefined; }, /** @@ -109,33 +108,28 @@ export const merkleIdSubmodule = { * @returns {IdResponse|undefined} */ getId(config, consentData) { - logInfo('User ID - merkleId generating id'); + utils.logInfo('User ID - merkleId generating id'); const configParams = (config && config.params) || {}; if (!configParams || typeof configParams.vendor !== 'string') { - logError('User ID - merkleId submodule requires a valid vendor to be defined'); + utils.logError('User ID - merkleId submodule requires a valid vendor to be defined'); return; } if (typeof configParams.sv_cid !== 'string') { - logError('User ID - merkleId submodule requires a valid sv_cid string to be defined'); + utils.logError('User ID - merkleId submodule requires a valid sv_cid string to be defined'); return; } if (typeof configParams.sv_pubid !== 'string') { - logError('User ID - merkleId submodule requires a valid sv_pubid string to be defined'); + utils.logError('User ID - merkleId submodule requires a valid sv_pubid string to be defined'); return; } - if (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) { - logError('User ID - merkleId submodule does not currently handle consent strings'); + utils.logError('User ID - merkleId submodule does not currently handle consent strings'); return; } - if (typeof configParams.endpoint !== 'string') { - logWarn('User ID - merkleId submodule endpoint string is not defined'); - configParams.endpoint = ID_URL - } if (typeof configParams.sv_domain !== 'string') { configParams.sv_domain = merkleIdSubmodule.findRootDomain(); @@ -146,16 +140,11 @@ export const merkleIdSubmodule = { return {callback: resp}; }, extendId: function (config = {}, consentData, storedId) { - logInfo('User ID - merkleId stored id ' + storedId); + utils.logInfo('User ID - merkleId stored id ' + storedId); const configParams = (config && config.params) || {}; - if (typeof configParams.endpoint !== 'string') { - logWarn('User ID - merkleId submodule endpoint string is not defined'); - configParams.endpoint = ID_URL - } - if (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) { - logError('User ID - merkleId submodule does not currently handle consent strings'); + utils.logError('User ID - merkleId submodule does not currently handle consent strings'); return; } @@ -169,19 +158,19 @@ export const merkleIdSubmodule = { let refreshInSeconds = DEFAULT_REFRESH; if (configParams && configParams.refreshInSeconds && typeof configParams.refreshInSeconds === 'number') { refreshInSeconds = configParams.refreshInSeconds; - logInfo('User ID - merkleId param refreshInSeconds' + refreshInSeconds); + utils.logInfo('User ID - merkleId param refreshInSeconds' + refreshInSeconds); } const storedDate = new Date(storedId.date); let refreshNeeded = false; if (storedDate) { refreshNeeded = storedDate && (Date.now() - storedDate.getTime() > refreshInSeconds * 1000); if (refreshNeeded) { - logInfo('User ID - merkleId needs refreshing id'); + utils.logInfo('User ID - merkleId needs refreshing id'); const resp = generateId(configParams, configStorage) return {callback: resp}; } } - logInfo('User ID - merkleId not refreshed'); + utils.logInfo('User ID - merkleId not refreshed'); return {id: storedId}; } diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js deleted file mode 100644 index 51b713c8958..00000000000 --- a/modules/mgidBidAdapter.js +++ /dev/null @@ -1,617 +0,0 @@ -import { _each, deepAccess, isPlainObject, isArray, isStr, logInfo, parseUrl, isEmpty, triggerPixel, logWarn, getBidIdParameter, isFn, isNumber } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import { getStorageManager } from '../src/storageManager.js'; - -const GVLID = 358; -const DEFAULT_CUR = 'USD'; -const BIDDER_CODE = 'mgid'; -export const storage = getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE}); -const ENDPOINT_URL = 'https://prebid.mgid.com/prebid/'; -const LOG_WARN_PREFIX = '[MGID warn]: '; -const LOG_INFO_PREFIX = '[MGID info]: '; -const NATIVE_ASSETS = { - 'TITLE': { ID: 1, KEY: 'title', TYPE: 0 }, - 'IMAGE': { ID: 2, KEY: 'image', TYPE: 0 }, - 'ICON': { ID: 3, KEY: 'icon', TYPE: 0 }, - 'SPONSOREDBY': { ID: 4, KEY: 'sponsoredBy', TYPE: 1 }, // please note that type of SPONSORED is also 1 - 'DESC': { ID: 5, KEY: 'data', TYPE: 2 }, // please note that type of BODY is also set to 2 - 'PRICE': { ID: 6, KEY: 'price', TYPE: 6 }, - 'SALEPRICE': { ID: 7, KEY: 'saleprice', TYPE: 7 }, - 'DISPLAYURL': { ID: 8, KEY: 'displayurl', TYPE: 11 }, - 'CTA': { ID: 9, KEY: 'cta', TYPE: 12 }, - 'BODY': { ID: 10, KEY: 'body', TYPE: 2 }, // please note that type of DESC is also set to 2 - 'SPONSORED': { ID: 11, KEY: 'sponsored', TYPE: 1 }, // please note that type of SPONSOREDBY is also set to 1 -}; -const NATIVE_ASSET_IMAGE_TYPE = { - 'ICON': 1, - 'IMAGE': 3 -}; -const DEFAULT_IMAGE_WIDTH = 492; -const DEFAULT_IMAGE_HEIGHT = 328; -const DEFAULT_ICON_WIDTH = 50; -const DEFAULT_ICON_HEIGHT = 50; -const DEFAULT_TITLE_LENGTH = 80; - -let isInvalidNativeRequest = false; - -// check if title, image can be added with mandatory field default values -const NATIVE_MINIMUM_REQUIRED_IMAGE_ASSETS = [ - { - id: NATIVE_ASSETS.SPONSOREDBY.ID, - required: true, - data: { - type: 1 - } - }, - { - id: NATIVE_ASSETS.TITLE.ID, - required: true, - }, - { - id: NATIVE_ASSETS.IMAGE.ID, - required: true, - } -]; -let _NATIVE_ASSET_ID_TO_KEY_MAP = {}; -let _NATIVE_ASSET_KEY_TO_ASSET_MAP = {}; - -// loading _NATIVE_ASSET_ID_TO_KEY_MAP -_each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] = anAsset.KEY }); -// loading _NATIVE_ASSET_KEY_TO_ASSET_MAP -_each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); - -export const spec = { - VERSION: '1.5', - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, NATIVE], - reId: /^[1-9][0-9]*$/, - NATIVE_ASSET_ID_TO_KEY_MAP: _NATIVE_ASSET_ID_TO_KEY_MAP, - NATIVE_ASSET_KEY_TO_ASSET_MAP: _NATIVE_ASSET_KEY_TO_ASSET_MAP, - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: (bid) => { - const banner = deepAccess(bid, 'mediaTypes.banner'); - const native = deepAccess(bid, 'mediaTypes.native'); - let nativeOk = isPlainObject(native); - if (nativeOk) { - const nativeParams = deepAccess(bid, 'nativeParams'); - let assetsCount = 0; - if (isPlainObject(nativeParams)) { - for (let k in nativeParams) { - let v = nativeParams[k]; - const supportProp = spec.NATIVE_ASSET_KEY_TO_ASSET_MAP.hasOwnProperty(k); - if (supportProp) { - assetsCount++ - } - if (!isPlainObject(v) || (!supportProp && deepAccess(v, 'required'))) { - nativeOk = false; - break; - } - } - } - nativeOk = nativeOk && (assetsCount > 0); - } - let bannerOk = isPlainObject(banner); - if (bannerOk) { - const sizes = deepAccess(banner, 'sizes'); - bannerOk = isArray(sizes) && sizes.length > 0; - for (let f = 0; bannerOk && f < sizes.length; f++) { - bannerOk = sizes[f].length === 2; - } - } - let acc = Number(bid.params.accountId); - let plcmt = Number(bid.params.placementId); - return (bannerOk || nativeOk) && isPlainObject(bid.params) && !!bid.adUnitCode && isStr(bid.adUnitCode) && (plcmt > 0 ? bid.params.placementId.toString().search(spec.reId) === 0 : true) && - !!acc && acc > 0 && bid.params.accountId.toString().search(spec.reId) === 0; - }, - /** - * Make a server request from the list of BidRequests. - * - * @param {validBidRequests[]} - an array of bids - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: (validBidRequests, bidderRequest) => { - logInfo(LOG_INFO_PREFIX + `buildRequests`); - if (validBidRequests.length === 0) { - return; - } - const info = pageInfo(); - const page = info.location || deepAccess(bidderRequest, 'refererInfo.referer') || deepAccess(bidderRequest, 'refererInfo.canonicalUrl'); - const hostname = parseUrl(page).hostname; - let domain = extractDomainFromHost(hostname) || hostname; - const accountId = setOnAny(validBidRequests, 'params.accountId'); - const muid = getLocalStorageSafely('mgMuidn'); - let url = (setOnAny(validBidRequests, 'params.bidUrl') || ENDPOINT_URL) + accountId; - if (isStr(muid) && muid.length > 0) { - url += '?muid=' + muid; - } - const cur = setOnAny(validBidRequests, 'params.currency') || setOnAny(validBidRequests, 'params.cur') || config.getConfig('currency.adServerCurrency') || DEFAULT_CUR; - const secure = window.location.protocol === 'https:' ? 1 : 0; - let imp = []; - validBidRequests.forEach(bid => { - let tagid = deepAccess(bid, 'params.placementId') || 0; - tagid = !tagid ? bid.adUnitCode : tagid + '/' + bid.adUnitCode; - let impObj = { - id: bid.bidId, - tagid, - secure, - }; - const floorData = getBidFloor(bid, cur); - if (floorData.floor) { - impObj.bidfloor = floorData.floor; - } - if (floorData.cur) { - impObj.bidfloorcur = floorData.cur - } - for (let mediaTypes in bid.mediaTypes) { - switch (mediaTypes) { - case BANNER: - impObj.banner = createBannerRequest(bid); - imp.push(impObj); - break; - case NATIVE: - const native = createNativeRequest(bid.nativeParams); - if (!isInvalidNativeRequest) { - impObj.native = { - 'request': native - }; - imp.push(impObj); - } - break; - } - } - }); - - if (imp.length === 0) { - return; - } - - let request = { - id: deepAccess(bidderRequest, 'bidderRequestId'), - site: {domain, page}, - cur: [cur], - geo: {utcoffset: info.timeOffset}, - device: { - ua: navigator.userAgent, - js: 1, - dnt: (navigator.doNotTrack === 'yes' || navigator.doNotTrack === '1' || navigator.msDoNotTrack === '1') ? 1 : 0, - h: screen.height, - w: screen.width, - language: getLanguage() - }, - ext: {mgid_ver: spec.VERSION, prebid_ver: '$prebid.version$'}, - imp - }; - if (bidderRequest && bidderRequest.gdprConsent) { - request.user = {ext: {consent: bidderRequest.gdprConsent.consentString}}; - request.regs = {ext: {gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)}} - } - if (info.referrer) { - request.site.ref = info.referrer - } - logInfo(LOG_INFO_PREFIX + `buildRequest:`, request); - return { - method: 'POST', - url: url, - data: JSON.stringify(request), - }; - }, - /** - * Unpack the response from the server into a list of bids. - * - * @param {ServerResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: (serverResponse, bidRequests) => { - logInfo(LOG_INFO_PREFIX + `interpretResponse`, serverResponse); - if (serverResponse == null || serverResponse.body == null || serverResponse.body === '' || !isArray(serverResponse.body.seatbid) || !serverResponse.body.seatbid.length) { - return; - } - const returnedBids = []; - const muidn = deepAccess(serverResponse.body, 'ext.muidn') - if (isStr(muidn) && muidn.length > 0) { - setLocalStorageSafely('mgMuidn', muidn) - } - serverResponse.body.seatbid.forEach((bids) => { - bids.bid.forEach((bid) => { - const pbid = prebidBid(bid, serverResponse.body.cur); - if (pbid.mediaType === NATIVE && isEmpty(pbid.native)) { - return; - } - returnedBids.push(pbid); - }) - }); - - logInfo(LOG_INFO_PREFIX + `interpretedResponse`, returnedBids); - return returnedBids; - }, - onBidWon: (bid) => { - const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || ''; - if (isStr(bid.nurl) && bid.nurl !== '') { - bid.nurl = bid.nurl.replace( - /\${AUCTION_PRICE}/, - cpm - ); - triggerPixel(bid.nurl); - } - if (bid.isBurl) { - if (bid.mediaType === BANNER) { - bid.ad = bid.ad.replace( - /\${AUCTION_PRICE}/, - cpm - ) - } else { - bid.burl = bid.burl.replace( - /\${AUCTION_PRICE}/, - cpm - ); - triggerPixel(bid.burl); - } - } - logInfo(LOG_INFO_PREFIX + `onBidWon`); - }, - getUserSyncs: (syncOptions, serverResponses) => { - logInfo(LOG_INFO_PREFIX + `getUserSyncs`); - } -}; - -registerBidder(spec); - -function setOnAny(collection, key) { - for (let i = 0, result; i < collection.length; i++) { - result = deepAccess(collection[i], key); - if (result) { - return result; - } - } -} - -/** - * Unpack the Server's Bid into a Prebid-compatible one. - * @param serverBid - * @return Bid - */ -function prebidBid(serverBid, cur) { - if (!isStr(cur) || cur === '') { - cur = DEFAULT_CUR; - } - const bid = { - requestId: serverBid.impid, - ad: serverBid.adm, - cpm: serverBid.price, - creativeId: serverBid.adid, - currency: cur, - dealId: serverBid.dealid || '', - width: serverBid.w, - height: serverBid.h, - mediaType: 'banner', - netRevenue: true, - ttl: serverBid.ttl || 300, - nurl: serverBid.nurl || '', - burl: serverBid.burl || '', - isBurl: isStr(serverBid.burl) && serverBid.burl.length > 0, - meta: { advertiserDomains: (isArray(serverBid.adomain) && serverBid.adomain.length > 0 ? serverBid.adomain : []) }, - }; - setMediaType(serverBid, bid); - switch (bid.mediaType) { - case BANNER: - break; - case NATIVE: - parseNativeResponse(serverBid, bid); - break; - } - return bid; -} - -function setMediaType(bid, newBid) { - if (deepAccess(bid, 'ext.crtype') === 'native') { - newBid.mediaType = NATIVE; - } else { - newBid.mediaType = BANNER; - } -} - -function extractDomainFromHost(pageHost) { - if (pageHost == 'localhost') { - return 'localhost' - } - let domain = null; - try { - let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost); - if (domains != null && domains.length > 0) { - domain = domains[0]; - for (let i = 1; i < domains.length; i++) { - if (domains[i].length > domain.length) { - domain = domains[i]; - } - } - } - } catch (e) { - domain = null; - } - return domain; -} - -function getLanguage() { - const language = navigator.language ? 'language' : 'userLanguage'; - const lang2 = navigator[language].split('-')[0]; - if (lang2.length === 2 || lang2.length === 3) { - return lang2; - } - return ''; -} - -function getLocalStorageSafely(key) { - try { - return storage.getDataFromLocalStorage(key); - } catch (e) { - return null; - } -} - -function setLocalStorageSafely(key, val) { - try { - return storage.setDataInLocalStorage(key, val); - } catch (e) { - return null; - } -} - -function createBannerRequest(bid) { - const sizes = deepAccess(bid, 'mediaTypes.banner.sizes'); - let format = []; - if (sizes.length > 1) { - for (let f = 0; f < sizes.length; f++) { - if (sizes[f].length === 2) { - format.push({w: sizes[f][0], h: sizes[f][1]}); - } - } - } - let r = { - w: sizes && sizes[0][0], - h: sizes && sizes[0][1], - }; - if (format.length) { - r.format = format - } - const pos = deepAccess(bid, 'mediaTypes.banner.pos') || 0 - if (pos) { - r.pos = pos - } - return r -} - -function createNativeRequest(params) { - let nativeRequestObject = { - plcmtcnt: 1, - assets: [] - }; - for (let key in params) { - let assetObj = {}; - if (params.hasOwnProperty(key)) { - if (!(nativeRequestObject.assets && nativeRequestObject.assets.length > 0 && nativeRequestObject.assets.hasOwnProperty(key))) { - switch (key) { - case NATIVE_ASSETS.TITLE.KEY: - assetObj = { - id: NATIVE_ASSETS.TITLE.ID, - required: params[key].required ? 1 : 0, - title: { - len: params[key].len || params[key].length || DEFAULT_TITLE_LENGTH - } - }; - break; - case NATIVE_ASSETS.IMAGE.KEY: - const wmin = params[key].wmin || params[key].minimumWidth || (isArray(params[key].minsizes) && params[key].minsizes.length > 0 ? params[key].minsizes[0] : 0); - const hmin = params[key].hmin || params[key].minimumHeight || (isArray(params[key].minsizes) && params[key].minsizes.length > 1 ? params[key].minsizes[1] : 0); - assetObj = { - id: NATIVE_ASSETS.IMAGE.ID, - required: params[key].required ? 1 : 0, - img: { - type: NATIVE_ASSET_IMAGE_TYPE.IMAGE, - w: params[key].w || params[key].width || (isArray(params[key].sizes) && params[key].sizes.length > 0 ? params[key].sizes[0] : 0), - h: params[key].h || params[key].height || (isArray(params[key].sizes) && params[key].sizes.length > 1 ? params[key].sizes[1] : 0), - mimes: params[key].mimes, - ext: params[key].ext, - } - }; - if (wmin > 0) { - assetObj.img.wmin = wmin; - } - if (hmin > 0) { - assetObj.img.hmin = hmin; - } - if (!assetObj.img.w) { - assetObj.img.w = DEFAULT_IMAGE_WIDTH; - } - if (!assetObj.img.h) { - assetObj.img.h = DEFAULT_IMAGE_HEIGHT; - } - break; - case NATIVE_ASSETS.ICON.KEY: - assetObj = { - id: NATIVE_ASSETS.ICON.ID, - required: params[key].required ? 1 : 0, - img: { - type: NATIVE_ASSET_IMAGE_TYPE.ICON, - w: params[key].w || params[key].width || (isArray(params[key].sizes) && params[key].sizes.length > 0 ? params[key].sizes[0] : 0), - h: params[key].h || params[key].height || (isArray(params[key].sizes) && params[key].sizes.length > 0 ? params[key].sizes[1] : 0), - } - }; - if (!assetObj.img.w) { - assetObj.img.w = DEFAULT_ICON_WIDTH; - } - if (!assetObj.img.h) { - assetObj.img.h = DEFAULT_ICON_HEIGHT; - } - break; - case NATIVE_ASSETS.SPONSORED.KEY: - case NATIVE_ASSETS.SPONSOREDBY.KEY: - case NATIVE_ASSETS.PRICE.KEY: - case NATIVE_ASSETS.SALEPRICE.KEY: - case NATIVE_ASSETS.DESC.KEY: - case NATIVE_ASSETS.BODY.KEY: - case NATIVE_ASSETS.DISPLAYURL.KEY: - case NATIVE_ASSETS.CTA.KEY: - assetObj = commonNativeRequestObject(spec.NATIVE_ASSET_KEY_TO_ASSET_MAP[key], params); - break; - default: - if (params[key].required) { - isInvalidNativeRequest = true; - return; - } - } - } - } - if (assetObj.id) { - nativeRequestObject.assets[nativeRequestObject.assets.length] = assetObj; - } - } - - // for native image adtype prebid has to have few required assests i.e. title,sponsoredBy, image - // if any of these are missing from the request then request will not be sent - let requiredAssetCount = NATIVE_MINIMUM_REQUIRED_IMAGE_ASSETS.length; - let presentrequiredAssetCount = 0; - NATIVE_MINIMUM_REQUIRED_IMAGE_ASSETS.forEach(ele => { - let lengthOfExistingAssets = nativeRequestObject.assets.length; - for (let i = 0; i < lengthOfExistingAssets; i++) { - if (ele.id === nativeRequestObject.assets[i].id) { - presentrequiredAssetCount++; - break; - } else { - if (ele.id === 4 && nativeRequestObject.assets[i].id === 11) { - if (deepAccess(nativeRequestObject.assets[i], 'data.type') === ele.data.type) { - presentrequiredAssetCount++; - break; - } - } - } - } - }); - isInvalidNativeRequest = requiredAssetCount !== presentrequiredAssetCount; - return nativeRequestObject; -} - -function commonNativeRequestObject(nativeAsset, params) { - const key = nativeAsset.KEY; - return { - id: nativeAsset.ID, - required: params[key].required ? 1 : 0, - data: { - type: nativeAsset.TYPE, - len: params[key].len, - ext: params[key].ext - } - }; -} - -function parseNativeResponse(bid, newBid) { - newBid.native = {}; - if (bid.hasOwnProperty('adm')) { - let adm = ''; - try { - adm = JSON.parse(bid.adm); - } catch (ex) { - logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native response for ad response: ' + newBid.adm); - return; - } - if (adm && adm.native && adm.native.assets && adm.native.assets.length > 0) { - newBid.mediaType = NATIVE; - for (let i = 0, len = adm.native.assets.length; i < len; i++) { - switch (adm.native.assets[i].id) { - case NATIVE_ASSETS.TITLE.ID: - newBid.native.title = adm.native.assets[i].title && adm.native.assets[i].title.text; - break; - case NATIVE_ASSETS.IMAGE.ID: - newBid.native.image = { - url: adm.native.assets[i].img && adm.native.assets[i].img.url, - height: adm.native.assets[i].img && adm.native.assets[i].img.h, - width: adm.native.assets[i].img && adm.native.assets[i].img.w, - }; - break; - case NATIVE_ASSETS.ICON.ID: - newBid.native.icon = { - url: adm.native.assets[i].img && adm.native.assets[i].img.url, - height: adm.native.assets[i].img && adm.native.assets[i].img.h, - width: adm.native.assets[i].img && adm.native.assets[i].img.w, - }; - break; - case NATIVE_ASSETS.SPONSOREDBY.ID: - case NATIVE_ASSETS.SPONSORED.ID: - case NATIVE_ASSETS.PRICE: - case NATIVE_ASSETS.SALEPRICE.ID: - case NATIVE_ASSETS.DESC.ID: - case NATIVE_ASSETS.BODY.ID: - case NATIVE_ASSETS.DISPLAYURL.ID: - case NATIVE_ASSETS.CTA.ID: - newBid.native[spec.NATIVE_ASSET_ID_TO_KEY_MAP[adm.native.assets[i].id]] = adm.native.assets[i].data && adm.native.assets[i].data.value; - break; - } - } - newBid.native.clickUrl = adm.native.link && adm.native.link.url; - newBid.native.clickTrackers = (adm.native.link && adm.native.link.clicktrackers) || []; - newBid.native.impressionTrackers = adm.native.imptrackers || []; - newBid.native.jstracker = adm.native.jstracker || []; - newBid.width = 0; - newBid.height = 0; - } - } -} - -function pageInfo() { - var w, d, l, r, m, p, t; - for (w = window, d = w.document, l = d.location.href, r = d.referrer, m = 0, t = new Date(); w !== w.parent;) { - try { - p = w.parent; l = p.location.href; r = p.document.referrer; w = p; - } catch (e) { - m = top !== w.parent ? 2 : 1; - break - } - } - return { - location: l, - referrer: r || '', - masked: m, - wWidth: w.innerWidth, - wHeight: w.innerHeight, - date: t.toUTCString(), - timeOffset: t.getTimezoneOffset() - }; -} - -/** - * Get the floor price from bid.params for backward compatibility. - * If not found, then check floor module. - * @param bid A valid bid object - * @returns {*|number} floor price - */ -function getBidFloor(bid, cur) { - let bidFloor = getBidIdParameter('bidfloor', bid.params) || getBidIdParameter('bidFloor', bid.params) || 0; - const reqCur = cur - - if (!bidFloor && isFn(bid.getFloor)) { - const floorObj = bid.getFloor({ - currency: '*', - mediaType: '*', - size: '*' - }); - if (isPlainObject(floorObj) && isNumber(floorObj.floor)) { - if (!floorObj.currency && reqCur !== DEFAULT_CUR) { - floorObj.currency = DEFAULT_CUR - } - if (floorObj.currency && reqCur !== floorObj.currency) { - cur = floorObj.currency - } - bidFloor = floorObj.floor; - } - } - if (reqCur === cur) { - cur = '' - } - return {floor: bidFloor, cur: cur} -} diff --git a/modules/microadBidAdapter.js b/modules/microadBidAdapter.js index 982bd61840a..c78a66aecee 100644 --- a/modules/microadBidAdapter.js +++ b/modules/microadBidAdapter.js @@ -1,6 +1,6 @@ -import { deepAccess, isEmpty, isStr } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'microad'; @@ -82,8 +82,8 @@ export const spec = { } } - const idlEnv = deepAccess(bid, 'userId.idl_env') - if (!isEmpty(idlEnv) && isStr(idlEnv)) { + const idlEnv = utils.deepAccess(bid, 'userId.idl_env') + if (!utils.isEmpty(idlEnv) && utils.isStr(idlEnv)) { params['idl_env'] = idlEnv } diff --git a/modules/minutemediaBidAdapter.js b/modules/minutemediaBidAdapter.js deleted file mode 100644 index 604a5dd7ea8..00000000000 --- a/modules/minutemediaBidAdapter.js +++ /dev/null @@ -1,431 +0,0 @@ -import { logWarn, logInfo, isArray, isFn, deepAccess, isEmpty, contains, timestamp, getBidIdParameter, triggerPixel, isInteger } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; - -const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; -const BIDDER_CODE = 'minutemedia'; -const ADAPTER_VERSION = '6.0.0'; -const TTL = 360; -const CURRENCY = 'USD'; -const SELLER_ENDPOINT = 'https://hb.minutemedia-prebid.com/'; -const MODES = { - PRODUCTION: 'hb-mm-multi', - TEST: 'hb-multi-mm-test' -} -const SUPPORTED_SYNC_METHODS = { - IFRAME: 'iframe', - PIXEL: 'pixel' -} - -export const spec = { - code: BIDDER_CODE, - gvlid: 918, - version: ADAPTER_VERSION, - supportedMediaTypes: SUPPORTED_AD_TYPES, - isBidRequestValid: function (bidRequest) { - if (!bidRequest.params) { - logWarn('no params have been set to MinuteMedia adapter'); - return false; - } - - if (!bidRequest.params.org) { - logWarn('org is a mandatory param for MinuteMedia adapter'); - return false; - } - - return true; - }, - buildRequests: function (validBidRequests, bidderRequest) { - const combinedRequestsObject = {}; - - // use data from the first bid, to create the general params for all bids - const generalObject = validBidRequests[0]; - const testMode = generalObject.params.testMode; - - combinedRequestsObject.params = generateGeneralParams(generalObject, bidderRequest); - combinedRequestsObject.bids = generateBidsParams(validBidRequests, bidderRequest); - - return { - method: 'POST', - url: getEndpoint(testMode), - data: combinedRequestsObject - } - }, - interpretResponse: function ({body}) { - const bidResponses = []; - - if (body.bids) { - body.bids.forEach(adUnit => { - const bidResponse = { - requestId: adUnit.requestId, - cpm: adUnit.cpm, - currency: adUnit.currency || CURRENCY, - width: adUnit.width, - height: adUnit.height, - ttl: adUnit.ttl || TTL, - creativeId: adUnit.requestId, - netRevenue: adUnit.netRevenue || true, - nurl: adUnit.nurl, - mediaType: adUnit.mediaType, - meta: { - mediaType: adUnit.mediaType - } - }; - - if (adUnit.mediaType === VIDEO) { - bidResponse.vastXml = adUnit.vastXml; - } else if (adUnit.mediaType === BANNER) { - bidResponse.ad = adUnit.ad; - } - - if (adUnit.adomain && adUnit.adomain.length) { - bidResponse.meta.advertiserDomains = adUnit.adomain; - } - - bidResponses.push(bidResponse); - }); - } - - return bidResponses; - }, - getUserSyncs: function (syncOptions, serverResponses) { - const syncs = []; - for (const response of serverResponses) { - if (syncOptions.iframeEnabled && response.body.params.userSyncURL) { - syncs.push({ - type: 'iframe', - url: response.body.params.userSyncURL - }); - } - if (syncOptions.pixelEnabled && isArray(response.body.params.userSyncPixels)) { - const pixels = response.body.params.userSyncPixels.map(pixel => { - return { - type: 'image', - url: pixel - } - }) - syncs.push(...pixels) - } - } - return syncs; - }, - onBidWon: function (bid) { - if (bid == null) { - return; - } - - logInfo('onBidWon:', bid); - if (bid.hasOwnProperty('nurl') && bid.nurl.length > 0) { - triggerPixel(bid.nurl); - } - } -}; - -registerBidder(spec); - -/** - * Get floor price - * @param bid {bid} - * @returns {Number} - */ -function getFloor(bid, mediaType) { - if (!isFn(bid.getFloor)) { - return 0; - } - let floorResult = bid.getFloor({ - currency: CURRENCY, - mediaType: mediaType, - size: '*' - }); - return floorResult.currency === CURRENCY && floorResult.floor ? floorResult.floor : 0; -} - -/** - * Get the the ad sizes array from the bid - * @param bid {bid} - * @returns {Array} - */ -function getSizesArray(bid, mediaType) { - let sizesArray = [] - - if (deepAccess(bid, `mediaTypes.${mediaType}.sizes`)) { - sizesArray = bid.mediaTypes[mediaType].sizes; - } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) { - sizesArray = bid.sizes; - } - - return sizesArray; -} - -/** - * Get schain string value - * @param schainObject {Object} - * @returns {string} - */ -function getSupplyChain(schainObject) { - if (isEmpty(schainObject)) { - return ''; - } - let scStr = `${schainObject.ver},${schainObject.complete}`; - schainObject.nodes.forEach((node) => { - scStr += '!'; - scStr += `${getEncodedValIfNotEmpty(node.asi)},`; - scStr += `${getEncodedValIfNotEmpty(node.sid)},`; - scStr += `${node.hp ? encodeURIComponent(node.hp) : ''},`; - scStr += `${getEncodedValIfNotEmpty(node.rid)},`; - scStr += `${getEncodedValIfNotEmpty(node.name)},`; - scStr += `${getEncodedValIfNotEmpty(node.domain)}`; - }); - return scStr; -} - -/** - * Get encoded node value - * @param val {string} - * @returns {string} - */ -function getEncodedValIfNotEmpty(val) { - return !isEmpty(val) ? encodeURIComponent(val) : ''; -} - -/** - * Get preferred user-sync method based on publisher configuration - * @param bidderCode {string} - * @returns {string} - */ -function getAllowedSyncMethod(filterSettings, bidderCode) { - const iframeConfigsToCheck = ['all', 'iframe']; - const pixelConfigToCheck = 'image'; - if (filterSettings && iframeConfigsToCheck.some(config => isSyncMethodAllowed(filterSettings[config], bidderCode))) { - return SUPPORTED_SYNC_METHODS.IFRAME; - } - if (!filterSettings || !filterSettings[pixelConfigToCheck] || isSyncMethodAllowed(filterSettings[pixelConfigToCheck], bidderCode)) { - return SUPPORTED_SYNC_METHODS.PIXEL; - } -} - -/** - * Check if sync rule is supported - * @param syncRule {Object} - * @param bidderCode {string} - * @returns {boolean} - */ -function isSyncMethodAllowed(syncRule, bidderCode) { - if (!syncRule) { - return false; - } - const isInclude = syncRule.filter === 'include'; - const bidders = isArray(syncRule.bidders) ? syncRule.bidders : [bidderCode]; - return isInclude && contains(bidders, bidderCode); -} - -/** - * Get the seller endpoint - * @param testMode {boolean} - * @returns {string} - */ -function getEndpoint(testMode) { - return testMode - ? SELLER_ENDPOINT + MODES.TEST - : SELLER_ENDPOINT + MODES.PRODUCTION; -} - -/** - * get device type - * @param uad {ua} - * @returns {string} - */ -function getDeviceType(ua) { - if (/ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i - .test(ua.toLowerCase())) { - return '5'; - } - if (/iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i - .test(ua.toLowerCase())) { - return '4'; - } - if (/smart[-_\s]?tv|hbbtv|appletv|googletv|hdmi|netcast|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b/i - .test(ua.toLowerCase())) { - return '3'; - } - return '1'; -} - -function generateBidsParams(validBidRequests, bidderRequest) { - const bidsArray = []; - - if (validBidRequests.length) { - validBidRequests.forEach(bid => { - bidsArray.push(generateBidParameters(bid, bidderRequest)); - }); - } - - return bidsArray; -} - -/** - * Generate bid specific parameters - * @param {bid} bid - * @param {bidderRequest} bidderRequest - * @returns {Object} bid specific params object - */ -function generateBidParameters(bid, bidderRequest) { - const {params} = bid; - const mediaType = isBanner(bid) ? BANNER : VIDEO; - const sizesArray = getSizesArray(bid, mediaType); - - // fix floor price in case of NAN - if (isNaN(params.floorPrice)) { - params.floorPrice = 0; - } - - const bidObject = { - mediaType, - adUnitCode: getBidIdParameter('adUnitCode', bid), - sizes: sizesArray, - floorPrice: Math.max(getFloor(bid, mediaType), params.floorPrice), - bidId: getBidIdParameter('bidId', bid), - bidderRequestId: getBidIdParameter('bidderRequestId', bid), - transactionId: getBidIdParameter('transactionId', bid), - }; - - const pos = deepAccess(bid, `mediaTypes.${mediaType}.pos`); - if (pos) { - bidObject.pos = pos; - } - - const gpid = deepAccess(bid, `ortb2Imp.ext.gpid`); - if (gpid) { - bidObject.gpid = gpid; - } - - const placementId = params.placementId || deepAccess(bid, `mediaTypes.${mediaType}.name`); - if (placementId) { - bidObject.placementId = placementId; - } - - if (mediaType === VIDEO) { - const playbackMethod = deepAccess(bid, `mediaTypes.video.playbackmethod`); - let playbackMethodValue; - - // verify playbackMethod is of type integer array, or integer only. - if (Array.isArray(playbackMethod) && isInteger(playbackMethod[0])) { - // only the first playbackMethod in the array will be used, according to OpenRTB 2.5 recommendation - playbackMethodValue = playbackMethod[0]; - } else if (isInteger(playbackMethod)) { - playbackMethodValue = playbackMethod; - } - - if (playbackMethodValue) { - bidObject.playbackMethod = playbackMethodValue; - } - - const placement = deepAccess(bid, `mediaTypes.video.placement`); - if (placement) { - bidObject.placement = placement; - } - - const minDuration = deepAccess(bid, `mediaTypes.video.minduration`); - if (minDuration) { - bidObject.minDuration = minDuration; - } - - const maxDuration = deepAccess(bid, `mediaTypes.video.maxduration`); - if (maxDuration) { - bidObject.maxDuration = maxDuration; - } - - const skip = deepAccess(bid, `mediaTypes.video.skip`); - if (skip) { - bidObject.skip = skip; - } - - const linearity = deepAccess(bid, `mediaTypes.video.linearity`); - if (linearity) { - bidObject.linearity = linearity; - } - } - - return bidObject; -} - -function isBanner(bid) { - return bid.mediaTypes && bid.mediaTypes.banner; -} - -/** - * Generate params that are common between all bids - * @param {single bid object} generalObject - * @param {bidderRequest} bidderRequest - * @returns {object} the common params object - */ -function generateGeneralParams(generalObject, bidderRequest) { - const domain = window.location.hostname; - const {syncEnabled, filterSettings} = config.getConfig('userSync') || {}; - const {bidderCode} = bidderRequest; - const generalBidParams = generalObject.params; - const timeout = config.getConfig('bidderTimeout'); - - // these params are snake_case instead of camelCase to allow backwards compatability on the server. - // in the future, these will be converted to camelCase to match our convention. - const generalParams = { - wrapper_type: 'prebidjs', - wrapper_vendor: '$$PREBID_GLOBAL$$', - wrapper_version: '$prebid.version$', - adapter_version: ADAPTER_VERSION, - auction_start: timestamp(), - publisher_id: generalBidParams.org, - publisher_name: domain, - site_domain: domain, - dnt: (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0, - device_type: getDeviceType(navigator.userAgent), - ua: navigator.userAgent, - session_id: getBidIdParameter('auctionId', generalObject), - tmax: timeout - } - - const userIdsParam = getBidIdParameter('userId', generalObject); - if (userIdsParam) { - generalParams.userIds = JSON.stringify(userIdsParam); - } - - const ortb2Metadata = config.getConfig('ortb2') || {}; - if (ortb2Metadata.site) { - generalParams.site_metadata = JSON.stringify(ortb2Metadata.site); - } - if (ortb2Metadata.user) { - generalParams.user_metadata = JSON.stringify(ortb2Metadata.user); - } - - if (syncEnabled) { - const allowedSyncMethod = getAllowedSyncMethod(filterSettings, bidderCode); - if (allowedSyncMethod) { - generalParams.cs_method = allowedSyncMethod; - } - } - - if (bidderRequest.uspConsent) { - generalParams.us_privacy = bidderRequest.uspConsent; - } - - if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { - generalParams.gdpr = bidderRequest.gdprConsent.gdprApplies; - generalParams.gdpr_consent = bidderRequest.gdprConsent.consentString; - } - - if (generalBidParams.ifa) { - generalParams.ifa = generalBidParams.ifa; - } - - if (generalObject.schain) { - generalParams.schain = getSupplyChain(generalObject.schain); - } - - if (bidderRequest && bidderRequest.refererInfo) { - generalParams.referrer = deepAccess(bidderRequest, 'refererInfo.referer'); - generalParams.page_url = config.getConfig('pageUrl') || deepAccess(window, 'location.href'); - } - - return generalParams -} diff --git a/modules/minutemediaBidAdapter.md b/modules/minutemediaBidAdapter.md deleted file mode 100644 index 70f106a745f..00000000000 --- a/modules/minutemediaBidAdapter.md +++ /dev/null @@ -1,76 +0,0 @@ -#Overview - -Module Name: MinuteMedia Bidder Adapter - -Module Type: Bidder Adapter - -Maintainer: hb@minutemedia.com - - -# Description - -Module that connects to MinuteMedia's demand sources. - -The MinuteMedia adapter requires setup and approval from the MinuteMedia. Please reach out to hb@minutemedia.com to create an MinuteMedia account. - -The adapter supports Video(instream) & Banner. - -# Bid Parameters -## Video - -| Name | Scope | Type | Description | Example -| ---- | ----- | ---- | ----------- | ------- -| `org` | required | String | MinuteMedia publisher Id provided by your MinuteMedia representative | "56f91cd4d3e3660002000033" -| `floorPrice` | optional | Number | Minimum price in USD. Misuse of this parameter can impact revenue | 2.00 -| `placementId` | optional | String | A unique placement identifier | "12345678" -| `testMode` | optional | Boolean | This activates the test mode | false - -# Test Parameters -```javascript -var adUnits = [{ - code: 'dfp-video-div', - sizes: [ - [640, 480] - ], - mediaTypes: { - video: { - playerSize: [ - [640, 480] - ], - context: 'instream' - } - }, - bids: [{ - bidder: 'minutemedia', - params: { - org: '56f91cd4d3e3660002000033', // Required - floorPrice: 2.00, // Optional - placementId: 'video-test', // Optional - testMode: false // Optional - } - }] - }, - { - code: 'dfp-banner-div', - sizes: [ - [640, 480] - ], - mediaTypes: { - banner: { - sizes: [ - [640, 480] - ] - } - }, - bids: [{ - bidder: 'minutemedia', - params: { - org: '56f91cd4d3e3660002000033', // Required - floorPrice: 2.00, // Optional - placementId: 'banner-test', // Optional - testMode: false // Optional - } - }] - } -]; -``` diff --git a/modules/missenaBidAdapter.js b/modules/missenaBidAdapter.js deleted file mode 100644 index 41bae4d6568..00000000000 --- a/modules/missenaBidAdapter.js +++ /dev/null @@ -1,89 +0,0 @@ -import { formatQS, logInfo } from '../src/utils.js'; -import { BANNER } from '../src/mediaTypes.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; - -const BIDDER_CODE = 'missena'; -const ENDPOINT_URL = 'https://bid.missena.io/'; - -export const spec = { - aliases: [BIDDER_CODE], - code: BIDDER_CODE, - gvlid: 687, - supportedMediaTypes: [BANNER], - - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function (bid) { - return typeof bid == 'object' && !!bid.params.apiKey; - }, - - /** - * Make a server request from the list of BidRequests. - * - * @param {validBidRequests[]} - an array of bids - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function (validBidRequests, bidderRequest) { - return validBidRequests.map((bidRequest) => { - const payload = { - request_id: bidRequest.bidId, - timeout: bidderRequest.timeout, - }; - - if (bidderRequest && bidderRequest.refererInfo) { - payload.referer = bidderRequest.refererInfo.referer; - payload.referer_canonical = bidderRequest.refererInfo.canonicalUrl; - } - - if (bidderRequest && bidderRequest.gdprConsent) { - payload.consent_string = bidderRequest.gdprConsent.consentString; - payload.consent_required = bidderRequest.gdprConsent.gdprApplies; - } - const baseUrl = bidRequest.params.baseUrl || ENDPOINT_URL; - return { - method: 'POST', - url: baseUrl + '?' + formatQS({ t: bidRequest.params.apiKey }), - data: JSON.stringify(payload), - }; - }); - }, - - /** - * Unpack the response from the server into a list of bids. - * - * @param {ServerResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function (serverResponse, bidRequest) { - const bidResponses = []; - const response = serverResponse.body; - - if (response && !response.timeout && !!response.ad) { - bidResponses.push(response); - } - - return bidResponses; - }, - - /** - * Register bidder specific code, which will execute if bidder timed out after an auction - * @param {data} Containing timeout specific data - */ - onTimeout: function onTimeout(timeoutData) { - logInfo('Missena - Timeout from adapter', timeoutData); - }, - - /** - * Register bidder specific code, which@ will execute if a bid from this bidder won the auction - * @param {Bid} The bid that won the auction - */ - onBidWon: function (bid) { - logInfo('Missena - Bid won', bid); - }, -}; - -registerBidder(spec); diff --git a/modules/mobfoxpbBidAdapter.js b/modules/mobfoxpbBidAdapter.js deleted file mode 100644 index a4af7133370..00000000000 --- a/modules/mobfoxpbBidAdapter.js +++ /dev/null @@ -1,135 +0,0 @@ -import { isFn, deepAccess, getWindowTop } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; - -const BIDDER_CODE = 'mobfoxpb'; -const AD_URL = 'https://bes.mobfox.com/pbjs'; - -function isBidResponseValid(bid) { - if (!bid.requestId || !bid.cpm || !bid.creativeId || - !bid.ttl || !bid.currency) { - return false; - } - switch (bid.mediaType) { - case BANNER: - return Boolean(bid.width && bid.height && bid.ad); - case VIDEO: - return Boolean(bid.vastUrl); - case NATIVE: - return Boolean(bid.native && bid.native.impressionTrackers); - default: - return false; - } -} - -function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidfloor', 0); - } - - try { - const bidFloor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*', - }); - return bidFloor.floor; - } catch (_) { - return 0 - } -} - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO, NATIVE], - - isBidRequestValid: (bid) => { - return Boolean(bid.bidId && bid.params && bid.params.placementId); - }, - - buildRequests: (validBidRequests = [], bidderRequest) => { - const winTop = getWindowTop(); - const location = winTop.location; - const placements = []; - const request = { - 'deviceWidth': winTop.screen.width, - 'deviceHeight': winTop.screen.height, - 'language': (navigator && navigator.language) ? navigator.language.split('-')[0] : '', - 'secure': 1, - 'host': location.host, - 'page': location.pathname, - 'placements': placements - }; - - if (bidderRequest) { - if (bidderRequest.uspConsent) { - request.ccpa = bidderRequest.uspConsent; - } - if (bidderRequest.gdprConsent) { - request.gdpr = bidderRequest.gdprConsent - } - } - - const len = validBidRequests.length; - for (let i = 0; i < len; i++) { - const bid = validBidRequests[i]; - const placement = { - placementId: bid.params.placementId, - bidId: bid.bidId, - schain: bid.schain || {}, - bidfloor: getBidFloor(bid) - }; - const mediaType = bid.mediaTypes - - if (mediaType && mediaType[BANNER] && mediaType[BANNER].sizes) { - placement.traffic = BANNER; - placement.sizes = mediaType[BANNER].sizes; - } else if (mediaType && mediaType[VIDEO] && mediaType[VIDEO].playerSize) { - placement.traffic = VIDEO; - placement.wPlayer = mediaType[VIDEO].playerSize[0]; - placement.hPlayer = mediaType[VIDEO].playerSize[1]; - placement.playerSize = mediaType[VIDEO].playerSize; - placement.minduration = mediaType[VIDEO].minduration; - placement.maxduration = mediaType[VIDEO].maxduration; - placement.mimes = mediaType[VIDEO].mimes; - placement.protocols = mediaType[VIDEO].protocols; - placement.startdelay = mediaType[VIDEO].startdelay; - placement.placement = mediaType[VIDEO].placement; - placement.skip = mediaType[VIDEO].skip; - placement.skipafter = mediaType[VIDEO].skipafter; - placement.minbitrate = mediaType[VIDEO].minbitrate; - placement.maxbitrate = mediaType[VIDEO].maxbitrate; - placement.delivery = mediaType[VIDEO].delivery; - placement.playbackmethod = mediaType[VIDEO].playbackmethod; - placement.api = mediaType[VIDEO].api; - placement.linearity = mediaType[VIDEO].linearity; - } else if (mediaType && mediaType[NATIVE]) { - placement.traffic = NATIVE; - placement.native = mediaType[NATIVE]; - } - placements.push(placement); - } - - return { - method: 'POST', - url: AD_URL, - data: request - }; - }, - - interpretResponse: (serverResponse) => { - let response = []; - for (let i = 0; i < serverResponse.body.length; i++) { - let resItem = serverResponse.body[i]; - if (isBidResponseValid(resItem)) { - resItem.meta = resItem.meta || {}; - resItem.meta.advertiserDomains = resItem.adomain || []; - - response.push(resItem); - } - } - return response; - }, -}; - -registerBidder(spec); diff --git a/modules/mobfoxpbBidAdapter.md b/modules/mobfoxpbBidAdapter.md index f434b2792a9..6eb549919d7 100644 --- a/modules/mobfoxpbBidAdapter.md +++ b/modules/mobfoxpbBidAdapter.md @@ -24,7 +24,7 @@ Module that connects to mobfox demand sources { bidder: 'mobfoxpb', params: { - placementId: 'testBanner' + placementId: 0 } } ] @@ -41,7 +41,7 @@ Module that connects to mobfox demand sources { bidder: 'mobfoxpb', params: { - placementId: 'testVideo' + placementId: 0 } } ] @@ -63,7 +63,7 @@ Module that connects to mobfox demand sources { bidder: 'mobfoxpb', params: { - placementId: 'testNative' + placementId: 0 } } ] diff --git a/modules/multibid/index.js b/modules/multibid/index.js index 8081e40ccb2..dd4999b2dca 100644 --- a/modules/multibid/index.js +++ b/modules/multibid/index.js @@ -5,10 +5,8 @@ import {config} from '../../src/config.js'; import {setupBeforeHookFnOnce, getHook} from '../../src/hook.js'; -import { - logWarn, deepAccess, getUniqueIdentifierStr, deepSetValue, groupBy -} from '../../src/utils.js'; -import * as events from '../../src/events.js'; +import * as utils from '../../src/utils.js'; +import events from '../../src/events.js'; import CONSTANTS from '../../src/constants.json'; import {addBidderRequests} from '../../src/auction.js'; import {getHighestCpmBidsFromBidPool, sortByDealAndPriceBucketOrCpm} from '../../src/targeting.js'; @@ -52,7 +50,7 @@ export function validateMultibid(conf) { let duplicate = conf.filter(entry => { // Check if entry.bidder is not defined or typeof string, filter entry and reset configuration if ((!entry.bidder || typeof entry.bidder !== 'string') && (!entry.bidders || !Array.isArray(entry.bidders))) { - logWarn('Filtering multibid entry. Missing required bidder or bidders property.'); + utils.logWarn('Filtering multibid entry. Missing required bidder or bidders property.'); check = false; return false; } @@ -99,26 +97,26 @@ export function adjustBidderRequestsHook(fn, bidderRequests) { * @param {Object} bid object */ export function addBidResponseHook(fn, adUnitCode, bid) { - let floor = deepAccess(bid, 'floorData.floorValue'); + let floor = utils.deepAccess(bid, 'floorData.floorValue'); if (!config.getConfig('multibid')) resetMultiConfig(); // Checks if multiconfig exists and bid bidderCode exists within config and is an adpod bid // Else checks if multiconfig exists and bid bidderCode exists within config // Else continue with no modifications - if (hasMultibid && multiConfig[bid.bidderCode] && deepAccess(bid, 'video.context') === 'adpod') { + if (hasMultibid && multiConfig[bid.bidderCode] && utils.deepAccess(bid, 'video.context') === 'adpod') { fn.call(this, adUnitCode, bid); } else if (hasMultibid && multiConfig[bid.bidderCode]) { // Set property multibidPrefix on bid if (multiConfig[bid.bidderCode].prefix) bid.multibidPrefix = multiConfig[bid.bidderCode].prefix; bid.originalBidder = bid.bidderCode; // Check if stored bids for auction include adUnitCode.bidder and max limit not reach for ad unit - if (deepAccess(multibidUnits, [adUnitCode, bid.bidderCode])) { + if (utils.deepAccess(multibidUnits, `${adUnitCode}.${bid.bidderCode}`)) { // Store request id under new property originalRequestId, create new unique bidId, // and push bid into multibid stored bids for auction if max not reached and bid cpm above floor if (!multibidUnits[adUnitCode][bid.bidderCode].maxReached && (!floor || floor <= bid.cpm)) { bid.originalRequestId = bid.requestId; - bid.requestId = getUniqueIdentifierStr(); + bid.requestId = utils.getUniqueIdentifierStr(); multibidUnits[adUnitCode][bid.bidderCode].ads.push(bid); let length = multibidUnits[adUnitCode][bid.bidderCode].ads.length; @@ -128,12 +126,12 @@ export function addBidResponseHook(fn, adUnitCode, bid) { fn.call(this, adUnitCode, bid); } else { - logWarn(`Filtering multibid received from bidder ${bid.bidderCode}: ` + ((multibidUnits[adUnitCode][bid.bidderCode].maxReached) ? `Maximum bid limit reached for ad unit code ${adUnitCode}` : 'Bid cpm under floors value.')); + utils.logWarn(`Filtering multibid received from bidder ${bid.bidderCode}: ` + ((multibidUnits[adUnitCode][bid.bidderCode].maxReached) ? `Maximum bid limit reached for ad unit code ${adUnitCode}` : 'Bid cpm under floors value.')); } } else { - if (deepAccess(bid, 'floorData.floorValue')) deepSetValue(multibidUnits, [adUnitCode, bid.bidderCode], {floor: deepAccess(bid, 'floorData.floorValue')}); + if (utils.deepAccess(bid, 'floorData.floorValue')) utils.deepSetValue(multibidUnits, `${adUnitCode}.${bid.bidderCode}`, {floor: utils.deepAccess(bid, 'floorData.floorValue')}); - deepSetValue(multibidUnits, [adUnitCode, bid.bidderCode], {ads: [bid]}); + utils.deepSetValue(multibidUnits, `${adUnitCode}.${bid.bidderCode}`, {ads: [bid]}); if (multibidUnits[adUnitCode][bid.bidderCode].ads.length === multiConfig[bid.bidderCode].maxbids) multibidUnits[adUnitCode][bid.bidderCode].maxReached = true; fn.call(this, adUnitCode, bid); @@ -172,11 +170,11 @@ export function targetBidPoolHook(fn, bidsReceived, highestCpmCallback, adUnitBi if (hasMultibid) { const dealPrioritization = config.getConfig('sendBidsControl.dealPrioritization'); let modifiedBids = []; - let buckets = groupBy(bidsReceived, 'adUnitCode'); + let buckets = utils.groupBy(bidsReceived, 'adUnitCode'); let bids = [].concat.apply([], Object.keys(buckets).reduce((result, slotId) => { let bucketBids = []; // Get bids and group by property originalBidder - let bidsByBidderName = groupBy(buckets[slotId], 'originalBidder'); + let bidsByBidderName = utils.groupBy(buckets[slotId], 'originalBidder'); let adjustedBids = [].concat.apply([], Object.keys(bidsByBidderName).map(key => { // Reset all bidderCodes to original bidder values and sort by CPM return bidsByBidderName[key].sort((bidA, bidB) => { @@ -185,7 +183,7 @@ export function targetBidPoolHook(fn, bidsReceived, highestCpmCallback, adUnitBi return bidA.cpm > bidB.cpm ? -1 : (bidA.cpm < bidB.cpm ? 1 : 0); }).map((bid, index) => { // For each bid (post CPM sort), set dynamic bidderCode using prefix and index if less than maxbid amount - if (deepAccess(multiConfig, `${bid.bidderCode}.prefix`) && index !== 0 && index < multiConfig[bid.bidderCode].maxbids) { + if (utils.deepAccess(multiConfig, `${bid.bidderCode}.prefix`) && index !== 0 && index < multiConfig[bid.bidderCode].maxbids) { bid.bidderCode = multiConfig[bid.bidderCode].prefix + (index + 1); } @@ -193,7 +191,7 @@ export function targetBidPoolHook(fn, bidsReceived, highestCpmCallback, adUnitBi }) })); // Get adjustedBids by bidderCode and reduce using highestCpmCallback - let bidsByBidderCode = groupBy(adjustedBids, 'bidderCode'); + let bidsByBidderCode = utils.groupBy(adjustedBids, 'bidderCode'); Object.keys(bidsByBidderCode).forEach(key => bucketBids.push(bidsByBidderCode[key].reduce(highestCpmCallback))); // if adUnitBidLimit is set, pass top N number bids if (adUnitBidLimit > 0) { diff --git a/modules/mwOpenLinkIdSystem.js b/modules/mwOpenLinkIdSystem.js index 552223fa73c..b2381836d5d 100644 --- a/modules/mwOpenLinkIdSystem.js +++ b/modules/mwOpenLinkIdSystem.js @@ -5,7 +5,7 @@ * @requires module:modules/userId */ -import { timestamp, logError, deepClone, generateUUID, isPlainObject } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { ajax } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; import { getStorageManager } from '../src/storageManager.js'; @@ -18,20 +18,20 @@ const openLinkID = { const storage = getStorageManager(); function getExpirationDate() { - return (new Date(timestamp() + openLinkID.cookie_expiration)).toGMTString(); + return (new Date(utils.timestamp() + openLinkID.cookie_expiration)).toGMTString(); } function isValidConfig(configParams) { if (!configParams) { - logError('User ID - mwOlId submodule requires configParams'); + utils.logError('User ID - mwOlId submodule requires configParams'); return false; } if (!configParams.accountId) { - logError('User ID - mwOlId submodule requires accountId to be defined'); + utils.logError('User ID - mwOlId submodule requires accountId to be defined'); return false; } if (!configParams.partnerId) { - logError('User ID - mwOlId submodule requires partnerId to be defined'); + utils.logError('User ID - mwOlId submodule requires partnerId to be defined'); return false; } return true; @@ -96,7 +96,7 @@ function register(configParams, olid) { function setID(configParams) { if (!isValidConfig(configParams)) return undefined; const mwOlId = readCookie(); - const newMwOlId = mwOlId ? deepClone(mwOlId) : {eid: generateUUID()}; + const newMwOlId = mwOlId ? utils.deepClone(mwOlId) : {eid: utils.generateUUID()}; writeCookie(newMwOlId); register(configParams, newMwOlId.eid); return { @@ -122,7 +122,7 @@ export const mwOpenLinkIdSubModule = { * @return {(Object|undefined} */ decode(mwOlId) { - const id = mwOlId && isPlainObject(mwOlId) ? mwOlId.eid : undefined; + const id = mwOlId && utils.isPlainObject(mwOlId) ? mwOlId.eid : undefined; return id ? { 'mwOpenLinkId': id } : undefined; }, diff --git a/modules/mytargetBidAdapter.js b/modules/mytargetBidAdapter.js deleted file mode 100644 index f55f2e6b802..00000000000 --- a/modules/mytargetBidAdapter.js +++ /dev/null @@ -1,112 +0,0 @@ -import { _map } from '../src/utils.js'; -import { config } from '../src/config.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; - -const BIDDER_CODE = 'mytarget'; -const BIDDER_URL = '//ad.mail.ru/hbid_prebid/'; -const DEFAULT_CURRENCY = 'RUB'; -const DEFAULT_TTL = 180; - -function buildPlacement(bidRequest) { - let { bidId, params } = bidRequest; - let { placementId, position, response, bidfloor } = params; - let placement = { - placementId, - id: bidId, - position: position || 0, - response: response || 0 - }; - - if (typeof bidfloor !== 'undefined') { - placement.bidfloor = bidfloor; - } - - return placement; -} - -function getSiteName(referrer) { - let sitename = config.getConfig('mytarget.sitename'); - - if (!sitename) { - const parsed = document.createElement('a'); - parsed.href = decodeURIComponent(referrer); - sitename = parsed.hostname; - } - - return sitename; -} - -function generateRandomId() { - return Math.random().toString(16).substring(2); -} - -export const spec = { - code: BIDDER_CODE, - - isBidRequestValid: function(bid) { - return !!bid.params.placementId; - }, - - buildRequests: function(validBidRequests, bidderRequest) { - let referrer = ''; - - if (bidderRequest && bidderRequest.refererInfo) { - referrer = bidderRequest.refererInfo.referer; - } - - const payload = { - places: _map(validBidRequests, buildPlacement), - site: { - sitename: getSiteName(referrer), - page: referrer - }, - settings: { - currency: DEFAULT_CURRENCY, - windowSize: { - width: window.screen.width, - height: window.screen.height - } - } - }; - - return { - method: 'POST', - url: BIDDER_URL, - data: payload, - }; - }, - - interpretResponse: function(serverResponse, bidRequest) { - let { body } = serverResponse; - - if (body.bids) { - return _map(body.bids, (bid) => { - let bidResponse = { - requestId: bid.id, - cpm: bid.price, - width: bid.size.width, - height: bid.size.height, - ttl: bid.ttl || DEFAULT_TTL, - currency: bid.currency || DEFAULT_CURRENCY, - creativeId: bid.creativeId || generateRandomId(), - netRevenue: true, - meta: { - advertiserDomains: bid.adomain && bid.adomain.length > 0 ? bid.adomain : [], - } - } - - if (bid.adm) { - bidResponse.ad = bid.adm; - } else { - bidResponse.adUrl = bid.displayUrl; - } - - return bidResponse; - }); - } - - return []; - } -} - -registerBidder(spec); diff --git a/modules/nativoBidAdapter.js b/modules/nativoBidAdapter.js index e07a124665f..880ff4b6a8e 100644 --- a/modules/nativoBidAdapter.js +++ b/modules/nativoBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, isEmpty } from '../src/utils.js' +import * as utils from '../src/utils.js' import { registerBidder } from '../src/adapters/bidderFactory.js' import { BANNER } from '../src/mediaTypes.js' // import { config } from 'src/config' @@ -6,93 +6,17 @@ import { BANNER } from '../src/mediaTypes.js' const BIDDER_CODE = 'nativo' const BIDDER_ENDPOINT = 'https://exchange.postrelease.com/prebid' -const GVLID = 263 - const TIME_TO_LIVE = 360 const SUPPORTED_AD_TYPES = [BANNER] -/** - * Keep track of bid data by keys - * @returns {Object} - Map of bid data that can be referenced by multiple keys - */ -const BidDataMap = () => { - const referenceMap = {} - const bids = [] - - /** - * Add a refence to the index by key value - * @param {String} key - The key to store the index reference - * @param {Integer} index - The index value of the bidData - */ - function adKeyReference(key, index) { - if (!referenceMap.hasOwnProperty(key)) { - referenceMap[key] = index - } - } - - /** - * Adds a bid to the map - * @param {Object} bid - Bid data - * @param {Array/String} keys - Keys to reference the index value - */ - function addBidData(bid, keys) { - const index = bids.length - bids.push(bid) - - if (Array.isArray(keys)) { - keys.forEach((key) => { - adKeyReference(String(key), index) - }) - return - } - - adKeyReference(String(keys), index) - } - - /** - * Get's the bid data refrerenced by the key - * @param {String} key - The key value to find the bid data by - * @returns {Object} - The bid data - */ - function getBidData(key) { - const stringKey = String(key) - if (referenceMap.hasOwnProperty(stringKey)) { - return bids[referenceMap[stringKey]] - } - } - - // Return API - return { - addBidData, - getBidData, - } -} - const bidRequestMap = {} const adUnitsRequested = {} -const extData = {} - -// Filtering -const adsToFilter = new Set() -const advertisersToFilter = new Set() -const campaignsToFilter = new Set() // Prebid adapter referrence doc: https://docs.prebid.org/dev-docs/bidder-adaptor.html -// Validity checks for optionsl paramters -const validParameter = { - url: (value) => typeof value === 'string', - placementId: (value) => { - const isString = typeof value === 'string' - const isNumber = typeof value === 'number' - return isString || isNumber - }, -} - export const spec = { code: BIDDER_CODE, - gvlid: GVLID, aliases: ['ntv'], // short code supportedMediaTypes: SUPPORTED_AD_TYPES, @@ -103,23 +27,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - // We don't need any specific parameters to make a bid request - // If not parameters are supplied just verify it's the correct bidder code - if (!bid.params) return bid.bidder === BIDDER_CODE - - // Check if any supplied parameters are invalid - const hasInvalidParameters = Object.keys(bid.params).some((key) => { - const value = bid.params[key] - const validityCheck = validParameter[key] - - // We don't have a test for this so it's not a paramter we care about - if (!validityCheck) return false - - // Return if the check is not passed - return !validityCheck(value) - }) - - return !hasInvalidParameters + return bid.params && !!bid.params.placementId }, /** @@ -131,37 +39,27 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function (validBidRequests, bidderRequest) { - const placementIds = new Set() + const placementIds = [] + const placmentBidIdMap = {} let placementId, pageUrl - const bidDataMap = BidDataMap() validBidRequests.forEach((request) => { - pageUrl = deepAccess( - request, - 'params.url', - bidderRequest.refererInfo.referer - ) - placementId = deepAccess(request, 'params.placementId') - - if (placementId) { - placementIds.add(placementId) - } - - const bidData = { + pageUrl = pageUrl || request.params.url // Use the first url value found + placementId = request.params.placementId + placementIds.push(placementId) + placmentBidIdMap[placementId] = { bidId: request.bidId, size: getLargestSize(request.sizes), } - bidDataMap.addBidData(bidData, [placementId, request.adUnitCode]) }) - bidRequestMap[bidderRequest.bidderRequestId] = bidDataMap + bidRequestMap[bidderRequest.bidderRequestId] = placmentBidIdMap + + if (!pageUrl) pageUrl = bidderRequest.refererInfo.referer // Build adUnit data const adUnitData = { adUnits: validBidRequests.map((adUnit) => { // Track if we've already requested for this ad unit code - adUnitsRequested[adUnit.adUnitCode] = - adUnitsRequested[adUnit.adUnitCode] !== undefined - ? adUnitsRequested[adUnit.adUnitCode] + 1 - : 0 + adUnitsRequested[adUnit.adUnitCode] = adUnitsRequested[adUnit.adUnitCode] !== undefined ? adUnitsRequested[adUnit.adUnitCode]++ : 0 return { adUnitCode: adUnit.adUnitCode, mediaTypes: adUnit.mediaTypes, @@ -171,6 +69,7 @@ export const spec = { // Build QS Params let params = [ + { key: 'ntv_ptd', value: placementIds.toString() }, { key: 'ntv_pb_rid', value: bidderRequest.bidderRequestId }, { key: 'ntv_ppc', @@ -178,37 +77,14 @@ export const spec = { }, { key: 'ntv_dbr', - value: btoa(JSON.stringify(adUnitsRequested)), + value: btoa(JSON.stringify(adUnitsRequested)) }, { key: 'ntv_url', value: encodeURIComponent(pageUrl), - }, + } ] - // Add filtering - if (adsToFilter.size > 0) { - params.unshift({ key: 'ntv_atf', value: Array.from(adsToFilter).join(',') }) - } - - if (advertisersToFilter.size > 0) { - params.unshift({ key: 'ntv_avtf', value: Array.from(advertisersToFilter).join(',') }) - } - - if (campaignsToFilter.size > 0) { - params.unshift({ key: 'ntv_ctf', value: Array.from(campaignsToFilter).join(',') }) - } - - // Add placement IDs - if (placementIds.size > 0) { - // Convert Set to Array (IE 11 Safe) - const placements = [] - placementIds.forEach((value) => placements.push(value)) - // Append to query string paramters - params.unshift({ key: 'ntv_ptd', value: placements.join(',') }) - } - - // Add GDPR params if (bidderRequest.gdprConsent) { // Put on the beginning of the qs param array params.unshift({ @@ -217,7 +93,6 @@ export const spec = { }) } - // Add USP params if (bidderRequest.uspConsent) { // Put on the beginning of the qs param array params.unshift({ key: 'us_privacy', value: bidderRequest.uspConsent }) @@ -242,7 +117,7 @@ export const spec = { */ interpretResponse: function (response, request) { // If the bid response was empty, return [] - if (!response || !response.body || isEmpty(response.body)) return [] + if (!response || !response.body || utils.isEmpty(response.body)) return [] try { const body = @@ -257,7 +132,7 @@ export const spec = { let bidResponse, adUnit seatbids.forEach((seatbid) => { seatbid.bid.forEach((bid) => { - adUnit = this.getAdUnitData(body.id, bid) + adUnit = this.getRequestId(body.id, bid.impid) bidResponse = { requestId: adUnit.bidId, cpm: bid.price, @@ -274,8 +149,6 @@ export const spec = { }, } - if (bid.ext) extData[bid.id] = bid.ext - bidResponses.push(bidResponse) }) }) @@ -340,7 +213,7 @@ export const spec = { let body serverResponses.forEach((response) => { // If the bid response was empty, return [] - if (!response || !response.body || isEmpty(response.body)) { + if (!response || !response.body || utils.isEmpty(response.body)) { return syncs } @@ -381,15 +254,7 @@ export const spec = { * Will be called when a bid from the adapter won the auction. * @param {Object} bid - The bid that won the auction */ - onBidWon: function (bid) { - const ext = extData[bid.dealId] - - if (!ext) return - - appendFilterData(adsToFilter, ext.adsToFilter) - appendFilterData(advertisersToFilter, ext.advertisersToFilter) - appendFilterData(campaignsToFilter, ext.campaignsToFilter) - }, + onBidWon: function (bid) {}, /** * Will be called when the adserver targeting has been set for a bid from the adapter. @@ -400,17 +265,13 @@ export const spec = { /** * Maps Prebid's bidId to Nativo's placementId values per unique bidderRequestId * @param {String} bidderRequestId - The unique ID value associated with the bidderRequest - * @param {Object} bid - The placement ID value from Nativo + * @param {String} placementId - The placement ID value from Nativo * @returns {String} - The bidId value associated with the corresponding placementId */ - getAdUnitData: function (bidderRequestId, bid) { - const bidDataMap = bidRequestMap[bidderRequestId] - - const placementId = bid.impid - const adUnitCode = deepAccess(bid, 'ext.ad_unit_id') - + getRequestId: function (bidderRequestId, placementId) { return ( - bidDataMap.getBidData(adUnitCode) || bidDataMap.getBidData(placementId) + bidRequestMap[bidderRequestId] && + bidRequestMap[bidderRequestId][placementId] ) }, } @@ -466,14 +327,3 @@ function getLargestSize(sizes, method = area) { * @returns The calculated area */ const area = (size) => size[0] * size[1] - -/** - * Save any filter data from winning bid requests for subsequent requests - * @param {Array} filter - The filter data bucket currently stored - * @param {Array} filterData - The filter data to add - */ -function appendFilterData(filter, filterData) { - if (filterData && Array.isArray(filterData) && filterData.length) { - filterData.forEach((ad) => filter.add(ad)) - } -} diff --git a/modules/nativoBidAdapter.md b/modules/nativoBidAdapter.md index f83fb45b52e..ec0980aae50 100644 --- a/modules/nativoBidAdapter.md +++ b/modules/nativoBidAdapter.md @@ -29,6 +29,7 @@ var adUnits = [ bids: [{ bidder: 'nativo', params: { + placementId: 1125609, url: 'https://test-sites.internal.nativo.net/testing/prebid_adpater.html' } }] diff --git a/modules/naveggIdSystem.js b/modules/naveggIdSystem.js deleted file mode 100644 index 7bd86879e9d..00000000000 --- a/modules/naveggIdSystem.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - * This module adds naveggId to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/naveggId - * @requires module:modules/userId - */ -import { isStr, isPlainObject, logError } from '../src/utils.js'; -import { submodule } from '../src/hook.js'; -import { getStorageManager } from '../src/storageManager.js'; - -const MODULE_NAME = 'naveggId'; -const OLD_NAVEGG_ID = 'nid'; -const NAVEGG_ID = 'nvggid' - -export const storage = getStorageManager(); - -function readnaveggIdFromLocalStorage() { - return storage.getDataFromLocalStorage(NAVEGG_ID); -} - -function readnaveggIDFromCookie() { - return storage.cookiesAreEnabled ? storage.getCookie(NAVEGG_ID) : null; -} - -function readoldnaveggIDFromCookie() { - return storage.cookiesAreEnabled ? storage.getCookie(OLD_NAVEGG_ID) : null; -} - -function readnvgIDFromCookie() { - return storage.cookiesAreEnabled ? (storage.findSimilarCookies('nvg') ? storage.findSimilarCookies('nvg')[0] : null) : null; -} - -function readnavIDFromCookie() { - return storage.cookiesAreEnabled ? (storage.findSimilarCookies('nav') ? storage.findSimilarCookies('nav')[0] : null) : null; -} - -function readnvgnavFromLocalStorage() { - var i; - const query = '^nvg|^nav'; - for (i in window.localStorage) { - if (i.match(query) || (!query && typeof i === 'string')) { - return storage.getDataFromLocalStorage(i.match(query).input); - } - } -} - -/** @type {Submodule} */ -export const naveggIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - /** - * decode the stored id value for passing to bid requests - * @function - * @param { Object | string | undefined } value - * @return { Object | string | undefined } - */ - decode(value) { - const naveggIdVal = value ? isStr(value) ? value : isPlainObject(value) ? value.id : undefined : undefined; - return naveggIdVal ? { - 'naveggId': naveggIdVal - } : undefined; - }, - /** - * performs action to obtain id and return a value in the callback's response argument - * @function - * @param {SubmoduleConfig} config - * @return {{id: string | undefined } | undefined} - */ - getId() { - let naveggIdStringFromLocalStorage = null; - if (storage.localStorageIsEnabled) { - naveggIdStringFromLocalStorage = readnaveggIdFromLocalStorage() || readnvgnavFromLocalStorage(); - } - - const naveggIdString = naveggIdStringFromLocalStorage || readnaveggIDFromCookie() || readoldnaveggIDFromCookie() || readnvgIDFromCookie() || readnavIDFromCookie(); - - if (typeof naveggIdString == 'string' && naveggIdString) { - try { - return { id: naveggIdString }; - } catch (error) { - logError(error); - } - } - return undefined; - } -}; -submodule('userId', naveggIdSubmodule); diff --git a/modules/naveggIdSystem.md b/modules/naveggIdSystem.md deleted file mode 100644 index f758fbc9d5d..00000000000 --- a/modules/naveggIdSystem.md +++ /dev/null @@ -1,22 +0,0 @@ -## Navegg User ID Submodule - -For assistance setting up your module please contact us at [prebid@navegg.com](prebid@navegg.com). - -### Prebid Params - -Individual params may be set for the IDx Submodule. -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'naveggId', - }] - } -}); -``` -## Parameter Descriptions for the `userSync` Configuration Section -The below parameters apply only to the naveggID integration. - -| Param under usersync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | ID of the module - `"naveggId"` | `"naveggId"` | diff --git a/modules/nextMillenniumBidAdapter.js b/modules/nextMillenniumBidAdapter.js index 91508d38ca0..2101bb34e2b 100644 --- a/modules/nextMillenniumBidAdapter.js +++ b/modules/nextMillenniumBidAdapter.js @@ -1,11 +1,9 @@ -import { isStr, _each, parseUrl, getWindowTop, getBidIdParameter } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import { BANNER } from '../src/mediaTypes.js'; const BIDDER_CODE = 'nextMillennium'; const ENDPOINT = 'https://pbs.nextmillmedia.com/openrtb2/auction'; -const TEST_ENDPOINT = 'https://test.pbs.nextmillmedia.com/openrtb2/auction'; -const SYNC_ENDPOINT = 'https://statics.nextmillmedia.com/load-cookie.html?v=4'; const TIME_TO_LIVE = 360; export const spec = { @@ -14,60 +12,38 @@ export const spec = { isBidRequestValid: function(bid) { return !!( - (bid.params.placement_id && isStr(bid.params.placement_id)) || (bid.params.group_id && isStr(bid.params.group_id)) + bid.params.placement_id && utils.isStr(bid.params.placement_id) ); }, buildRequests: function(validBidRequests, bidderRequest) { const requests = []; - window.nmmRefreshCounts = window.nmmRefreshCounts || {}; - _each(validBidRequests, function(bid) { - window.nmmRefreshCounts[bid.adUnitCode] = window.nmmRefreshCounts[bid.adUnitCode] || 0; + utils._each(validBidRequests, function(bid) { const postBody = { 'id': bid.auctionId, 'ext': { 'prebid': { 'storedrequest': { - 'id': getPlacementId(bid) + 'id': utils.getBidIdParameter('placement_id', bid.params) } - }, - - 'nextMillennium': { - 'refresh_count': window.nmmRefreshCounts[bid.adUnitCode]++, } } } - const gdprConsent = bidderRequest && bidderRequest.gdprConsent; - const uspConsent = bidderRequest && bidderRequest.uspConsent - - if (gdprConsent || uspConsent) { - postBody.regs = { ext: {} } - if (uspConsent) { - postBody.regs.ext.us_privacy = uspConsent; + if (gdprConsent) { + if (typeof gdprConsent.gdprApplies !== 'undefined') { + postBody.gdprApplies = !!gdprConsent.gdprApplies; } - - if (gdprConsent) { - if (typeof gdprConsent.gdprApplies !== 'undefined') { - postBody.regs.ext.gdpr = gdprConsent.gdprApplies ? 1 : 0; - } - - if (typeof gdprConsent.consentString !== 'undefined') { - postBody.user = { - ext: { consent: gdprConsent.consentString } - } - } + if (typeof gdprConsent.consentString !== 'undefined') { + postBody.consentString = gdprConsent.consentString; } } - const urlParameters = parseUrl(getWindowTop().location.href).search; - const isTest = urlParameters['pbs'] && urlParameters['pbs'] === 'test'; - requests.push({ method: 'POST', - url: isTest ? TEST_ENDPOINT : ENDPOINT, + url: ENDPOINT, data: JSON.stringify(postBody), options: { contentType: 'application/json', @@ -84,8 +60,8 @@ export const spec = { const response = serverResponse.body; const bidResponses = []; - _each(response.seatbid, (resp) => { - _each(resp.bid, (bid) => { + utils._each(response.seatbid, (resp) => { + utils._each(resp.bid, (bid) => { bidResponses.push({ requestId: bidRequest.bidId, cpm: bid.price, @@ -98,69 +74,13 @@ export const spec = { meta: { advertiserDomains: bid.adomain || [] }, - ad: bid.adm }); }); }); return bidResponses; - }, - - getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent) { - if (!syncOptions.iframeEnabled) { - return - } - - let syncurl = gdprConsent && gdprConsent.gdprApplies ? `${SYNC_ENDPOINT}&gdpr=1&gdpr_consent=${gdprConsent.consentString}` : SYNC_ENDPOINT - - let bidders = [] - if (responses) { - _each(responses, (response) => { - if (!(response && response.body && response.body.ext && response.body.ext.responsetimemillis)) return - _each(Object.keys(response.body.ext.responsetimemillis), b => bidders.push(b)) - }) - } - - if (bidders.length) { - syncurl += `&bidders=${bidders.join(',')}` - } - - return [{ - type: 'iframe', - url: syncurl - }]; - }, -}; - -function getPlacementId(bid) { - const groupId = getBidIdParameter('group_id', bid.params) - const placementId = getBidIdParameter('placement_id', bid.params) - if (!groupId) return placementId - - let windowTop = getTopWindow(window) - let size = [] - if (bid.mediaTypes) { - if (bid.mediaTypes.banner) size = bid.mediaTypes.banner.sizes && bid.mediaTypes.banner.sizes[0] - if (bid.mediaTypes.video) size = bid.mediaTypes.video.playerSize } - - const host = (windowTop && windowTop.location && windowTop.location.host) || '' - return `g${groupId};${size.join('x')};${host}` -} - -function getTopWindow(curWindow, nesting = 0) { - if (nesting > 10) { - return curWindow - } - - try { - if (curWindow.parent.document) { - return getTopWindow(curWindow.parent.window, ++nesting) - } - } catch (err) { - return curWindow - } -} +}; registerBidder(spec); diff --git a/modules/nextMillenniumBidAdapter.md b/modules/nextMillenniumBidAdapter.md index 136f97d94d5..048fe907ac7 100644 --- a/modules/nextMillenniumBidAdapter.md +++ b/modules/nextMillenniumBidAdapter.md @@ -21,9 +21,8 @@ Currently module supports only banner mediaType. bids: [{ bidder: 'nextMillennium', params: { - placement_id: '-1', - group_id: '6731' + placement_id: '-1' } }] }]; -``` +``` \ No newline at end of file diff --git a/modules/nextrollBidAdapter.js b/modules/nextrollBidAdapter.js deleted file mode 100644 index 4e82bc1cbda..00000000000 --- a/modules/nextrollBidAdapter.js +++ /dev/null @@ -1,375 +0,0 @@ -import { - deepAccess, - getBidIdParameter, - isArray, - isFn, - isNumber, - isPlainObject, - isStr, - parseUrl, - replaceAuctionPrice, -} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE} from '../src/mediaTypes.js'; - -import {find} from '../src/polyfill.js'; - -const BIDDER_CODE = 'nextroll'; -const BIDDER_ENDPOINT = 'https://d.adroll.com/bid/prebid/'; -const ADAPTER_VERSION = 5; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, NATIVE], - - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function (bidRequest) { - return bidRequest !== undefined && !!bidRequest.params && !!bidRequest.bidId; - }, - - /** - * Make a server request from the list of BidRequests. - * - * @param {validBidRequests[]} - an array of bids - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function (validBidRequests, bidderRequest) { - let topLocation = parseUrl(deepAccess(bidderRequest, 'refererInfo.referer')); - - return validBidRequests.map((bidRequest) => { - return { - method: 'POST', - options: { - withCredentials: true, - }, - url: BIDDER_ENDPOINT, - data: { - id: bidRequest.bidId, - imp: { - id: bidRequest.bidId, - bidfloor: _getFloor(bidRequest), - banner: _getBanner(bidRequest), - native: _getNative(deepAccess(bidRequest, 'mediaTypes.native')), - ext: { - zone: { - id: getBidIdParameter('zoneId', bidRequest.params) - }, - nextroll: { - adapter_version: ADAPTER_VERSION - } - } - }, - - user: _getUser(validBidRequests), - site: _getSite(bidRequest, topLocation), - seller: _getSeller(bidRequest), - device: _getDevice(bidRequest), - regs: _getRegs(bidderRequest) - } - }; - }); - }, - - /** - * Unpack the response from the server into a list of bids. - * - * @param {ServerResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function (serverResponse, bidRequest) { - if (!serverResponse.body) { - return []; - } else { - let response = serverResponse.body - let bids = response.seatbid.reduce((acc, seatbid) => acc.concat(seatbid.bid), []); - return bids.map((bid) => _buildResponse(response, bid)); - } - } -} - -function _getBanner(bidRequest) { - let sizes = _getSizes(bidRequest); - if (sizes === undefined) return undefined; - return {format: sizes}; -} - -function _getNative(mediaTypeNative) { - if (mediaTypeNative === undefined) return undefined; - let assets = _getNativeAssets(mediaTypeNative); - if (assets === undefined || assets.length == 0) return undefined; - return { - request: { - native: { - assets: assets - } - } - }; -} - -/* - id: Unique numeric id for the asset - kind: OpenRTB kind of asset. Supported: title, img and data. - key: Name of property that comes in the mediaType.native object. - type: OpenRTB type for that spefic kind of asset. - required: Overrides the asset required field configured, only overrides when is true. -*/ -const NATIVE_ASSET_MAP = [ - {id: 1, kind: 'title', key: 'title', required: true}, - {id: 2, kind: 'img', key: 'image', type: 3, required: true}, - {id: 3, kind: 'img', key: 'icon', type: 1}, - {id: 4, kind: 'img', key: 'logo', type: 2}, - {id: 5, kind: 'data', key: 'sponsoredBy', type: 1}, - {id: 6, kind: 'data', key: 'body', type: 2} -]; - -const ASSET_KIND_MAP = { - title: _getTitleAsset, - img: _getImageAsset, - data: _getDataAsset, -}; - -function _getAsset(mediaTypeNative, assetMap) { - const asset = mediaTypeNative[assetMap.key]; - if (asset === undefined) return undefined; - const assetFunc = ASSET_KIND_MAP[assetMap.kind]; - return { - id: assetMap.id, - required: (assetMap.required || !!asset.required) ? 1 : 0, - [assetMap.kind]: assetFunc(asset, assetMap) - }; -} - -function _getTitleAsset(title, _assetMap) { - return {len: title.len || 0}; -} - -function _getMinAspectRatio(aspectRatio, property) { - if (!isPlainObject(aspectRatio)) return 1; - - const ratio = aspectRatio['ratio_' + property]; - const min = aspectRatio['min_' + property]; - - if (isNumber(ratio)) return ratio; - if (isNumber(min)) return min; - - return 1; -} - -function _getImageAsset(image, assetMap) { - const sizes = image.sizes; - const aspectRatio = image.aspect_ratios ? image.aspect_ratios[0] : undefined; - - return { - type: assetMap.type, - w: (sizes ? sizes[0] : undefined), - h: (sizes ? sizes[1] : undefined), - wmin: _getMinAspectRatio(aspectRatio, 'width'), - hmin: _getMinAspectRatio(aspectRatio, 'height'), - }; -} - -function _getDataAsset(data, assetMap) { - return { - type: assetMap.type, - len: data.len || 0 - }; -} - -function _getNativeAssets(mediaTypeNative) { - return NATIVE_ASSET_MAP - .map(assetMap => _getAsset(mediaTypeNative, assetMap)) - .filter(asset => asset !== undefined); -} - -function _getUser(requests) { - const id = deepAccess(requests, '0.userId.nextrollId'); - if (id === undefined) { - return; - } - - return { - ext: { - eid: [{ - 'source': 'nextroll', - id - }] - } - }; -} - -function _getFloor(bidRequest) { - if (!isFn(bidRequest.getFloor)) { - return (bidRequest.params.bidfloor) ? bidRequest.params.bidfloor : null; - } - - let floor = bidRequest.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*' - }); - - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { - return floor.floor; - } - return null; -} - -function _buildResponse(bidResponse, bid) { - let response = { - requestId: bidResponse.id, - cpm: bid.price, - width: bid.w, - height: bid.h, - creativeId: bid.crid, - dealId: bidResponse.dealId, - currency: 'USD', - netRevenue: true, - ttl: 300, - meta: { - advertiserDomains: bidResponse.adomain || [] - } - }; - if (isStr(bid.adm)) { - response.mediaType = BANNER; - response.ad = replaceAuctionPrice(bid.adm, bid.price); - } else { - response.mediaType = NATIVE; - response.native = _getNativeResponse(bid.adm, bid.price); - } - return response; -} - -const privacyLink = 'https://app.adroll.com/optout/personalized'; -const privacyIcon = 'https://s.adroll.com/j/ad-choices-small.png'; - -function _getNativeResponse(adm, price) { - let baseResponse = { - clickTrackers: (adm.link && adm.link.clicktrackers) || [], - jstracker: adm.jstracker || [], - clickUrl: replaceAuctionPrice(adm.link.url, price), - impressionTrackers: adm.imptrackers.map(impTracker => replaceAuctionPrice(impTracker, price)), - privacyLink: privacyLink, - privacyIcon: privacyIcon - }; - return adm.assets.reduce((accResponse, asset) => { - const assetMaps = NATIVE_ASSET_MAP.filter(assetMap => assetMap.id === asset.id && asset[assetMap.kind] !== undefined); - if (assetMaps.length === 0) return accResponse; - const assetMap = assetMaps[0]; - accResponse[assetMap.key] = _getAssetResponse(asset, assetMap); - return accResponse; - }, baseResponse); -} - -function _getAssetResponse(asset, assetMap) { - switch (assetMap.kind) { - case 'title': - return asset.title.text; - - case 'img': - return { - url: asset.img.url, - width: asset.img.w, - height: asset.img.h - }; - - case 'data': - return asset.data.value; - } -} - -function _getSite(bidRequest, topLocation) { - return { - page: topLocation.href, - domain: topLocation.hostname, - publisher: { - id: getBidIdParameter('publisherId', bidRequest.params) - } - }; -} - -function _getSeller(bidRequest) { - return { - id: getBidIdParameter('sellerId', bidRequest.params) - }; -} - -function _getSizes(bidRequest) { - if (!isArray(bidRequest.sizes)) { - return undefined; - } - return bidRequest.sizes.filter(_isValidSize).map(size => { - return { - w: size[0], - h: size[1] - } - }); -} - -function _isValidSize(size) { - const isNumber = x => typeof x === 'number'; - return (size.length === 2 && isNumber(size[0]) && isNumber(size[1])); -} - -function _getDevice(_bidRequest) { - return { - ua: navigator.userAgent, - language: navigator['language'], - os: _getOs(navigator.userAgent.toLowerCase()), - osv: _getOsVersion(navigator.userAgent) - }; -} - -function _getRegs(bidderRequest) { - if (!bidderRequest || !bidderRequest.uspConsent) { - return undefined; - } - return { - ext: { - us_privacy: bidderRequest.uspConsent - } - }; -} - -function _getOs(userAgent) { - const osTable = { - 'android': /android/i, - 'ios': /iphone|ipad/i, - 'mac': /mac/i, - 'linux': /linux/i, - 'windows': /windows/i - }; - - return find(Object.keys(osTable), os => { - if (userAgent.match(osTable[os])) { - return os; - } - }) || 'etc'; -} - -function _getOsVersion(userAgent) { - const clientStrings = [ - { s: 'Android', r: /Android/ }, - { s: 'iOS', r: /(iPhone|iPad|iPod)/ }, - { s: 'Mac OS X', r: /Mac OS X/ }, - { s: 'Mac OS', r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ }, - { s: 'Linux', r: /(Linux|X11)/ }, - { s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ }, - { s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ }, - { s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ }, - { s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ }, - { s: 'Windows Vista', r: /Windows NT 6.0/ }, - { s: 'Windows Server 2003', r: /Windows NT 5.2/ }, - { s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ }, - { s: 'UNIX', r: /UNIX/ }, - { s: 'Search Bot', r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ } - ]; - let cs = find(clientStrings, cs => cs.r.test(userAgent)); - return cs ? cs.s : 'unknown'; -} - -registerBidder(spec); diff --git a/modules/nexx360BidAdapter.js b/modules/nexx360BidAdapter.js deleted file mode 100644 index 814a2f55299..00000000000 --- a/modules/nexx360BidAdapter.js +++ /dev/null @@ -1,175 +0,0 @@ -import {ajax} from '../src/ajax.js'; -import {config} from '../src/config.js'; -import { transformBidderParamKeywords } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; - -const BIDDER_CODE = 'nexx360'; -const BIDDER_URL = 'https://fast.nexx360.io/prebid'; -const CACHE_URL = 'https://fast.nexx360.io/cache'; -const METRICS_TRACKER_URL = 'https://fast.nexx360.io/track-imp'; - -const GVLID = 965; - -export const spec = { - code: BIDDER_CODE, - gvlid: GVLID, - aliases: ['revenuemaker'], // short code - supportedMediaTypes: [BANNER, VIDEO], - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function(bid) { - if (!!bid.params.bidfloorCurrency && !['EUR', 'USD'].includes(bid.params.bidfloorCurrency)) return false; - if (!!bid.params.bidfloor && typeof bid.params.bidfloor !== 'number') return false; - if (!!bid.params.keywords && typeof bid.params.keywords !== 'object') return false; - return !!(bid.params.account && bid.params.tagId); - }, - /** - * Make a server request from the list of BidRequests. - * - * @param {validBidRequests[]} - an array of bids - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function(validBidRequests, bidderRequest) { - const adUnits = []; - const test = config.getConfig('debug') ? 1 : 0; - let adunitValue = null; - let userEids = null; - Object.keys(validBidRequests).forEach(key => { - adunitValue = validBidRequests[key]; - const foo = { - account: adunitValue.params.account, - tagId: adunitValue.params.tagId, - videoExt: adunitValue.params.videoExt, - label: adunitValue.adUnitCode, - bidId: adunitValue.bidId, - auctionId: adunitValue.auctionId, - transactionId: adunitValue.transactionId, - mediatypes: adunitValue.mediaTypes, - bidfloor: adunitValue.params.bidfloor || 0, - bidfloorCurrency: adunitValue.params.bidfloorCurrency || 'USD', - keywords: adunitValue.params.keywords ? transformBidderParamKeywords(adunitValue.params.keywords) : [], - } - adUnits.push(foo); - if (adunitValue.userIdAsEids) userEids = adunitValue.userIdAsEids; - }); - const payload = { - adUnits, - href: encodeURIComponent(bidderRequest.refererInfo.referer) - }; - if (bidderRequest) { // modules informations (gdpr, ccpa, schain, userId) - if (bidderRequest.gdprConsent) { - payload.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; - payload.gdprConsent = bidderRequest.gdprConsent.consentString; - } else { - payload.gdpr = 0; - payload.gdprConsent = ''; - } - if (bidderRequest.uspConsent) { payload.uspConsent = bidderRequest.uspConsent; } - if (bidderRequest.schain) { payload.schain = bidderRequest.schain; } - if (userEids !== null) payload.userEids = userEids; - }; - if (test) payload.test = 1; - const payloadString = JSON.stringify(payload); - return { - method: 'POST', - url: BIDDER_URL, - data: payloadString, - }; - }, - /** - * Unpack the response from the server into a list of bids. - * - * @param {ServerResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function(serverResponse, bidRequest) { - const serverBody = serverResponse.body; - const bidResponses = []; - let bidResponse = null; - let value = null; - if (serverBody.hasOwnProperty('responses')) { - Object.keys(serverBody['responses']).forEach(key => { - value = serverBody['responses'][key]; - const url = `${CACHE_URL}?uuid=${value['uuid']}`; - bidResponse = { - requestId: value['bidId'], - cpm: value['cpm'], - currency: value['currency'], - width: value['width'], - height: value['height'], - ttl: value['ttl'], - creativeId: value['creativeId'], - netRevenue: true, - nexx360: { - 'ssp': value['bidder'], - 'consent': value['consent'], - 'tagId': value['tagId'] - }, - /* - meta: { - 'advertiserDomains': value['adomain'] - } - */ - }; - if (value.type === 'banner') bidResponse.adUrl = url; - if (value.type === 'video') { - const params = { - type: 'prebid', - mediatype: 'video', - ssp: value.bidder, - tag_id: value.tagId, - consent: value.consent, - price: value.cpm, - }; - bidResponse.cpm = value.cpm; - bidResponse.mediaType = 'video'; - bidResponse.vastUrl = url; - bidResponse.vastImpUrl = `${METRICS_TRACKER_URL}?${new URLSearchParams(params).toString()}`; - } - bidResponses.push(bidResponse); - }); - } - return bidResponses; - }, - - /** - * Register the user sync pixels which should be dropped after the auction. - * - * @param {SyncOptions} syncOptions Which user syncs are allowed? - * @param {ServerResponse[]} serverResponses List of server's responses. - * @return {UserSync[]} The user syncs which should be dropped. - */ - getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { - if (typeof serverResponses === 'object' && serverResponses != null && serverResponses.length > 0 && serverResponses[0].hasOwnProperty('body') && - serverResponses[0].body.hasOwnProperty('cookies') && typeof serverResponses[0].body.cookies === 'object') { - return serverResponses[0].body.cookies.slice(0, 5); - } else { - return []; - } - }, - - /** - * Register bidder specific code, which will execute if a bid from this bidder won the auction - * @param {Bid} The bid that won the auction - */ - onBidWon: function(bid) { - // fires a pixel to confirm a winning bid - const params = { type: 'prebid', mediatype: 'banner' }; - if (bid.hasOwnProperty('nexx360')) { - if (bid.nexx360.hasOwnProperty('ssp')) params.ssp = bid.nexx360.ssp; - if (bid.nexx360.hasOwnProperty('tagId')) params.tag_id = bid.nexx360.tagId; - if (bid.nexx360.hasOwnProperty('consent')) params.consent = bid.nexx360.consent; - }; - params.price = bid.cpm; - const url = `${METRICS_TRACKER_URL}?${new URLSearchParams(params).toString()}`; - ajax(url, null, undefined, {method: 'GET', withCredentials: true}); - return true; - } - -} -registerBidder(spec); diff --git a/modules/nexx360BidAdapter.md b/modules/nexx360BidAdapter.md deleted file mode 100644 index 532d48418b6..00000000000 --- a/modules/nexx360BidAdapter.md +++ /dev/null @@ -1,59 +0,0 @@ -# Overview - -``` -Module Name: Nexx360 Bid Adapter -Module Type: Bidder Adapter -Maintainer: gabriel@nexx360.io -``` - -# Description - -Connects to Nexx360 network for bids. - -To use us as a bidder you must have an account and an active "tagId" on our Nexx360 platform. - -# Test Parameters - -## Web - -### Display -``` -var adUnits = [ - // Banner adUnit - { - code: 'banner-div', - mediaTypes: { - banner: { - sizes: [[300, 250], [300,600]] - } - }, - bids: [{ - bidder: 'nexx360', - params: { - account: '1067', - tagId: 'luvxjvgn' - } - }] - }, -]; -``` - -### Video Instream -``` - var videoAdUnit = { - code: 'video1', - mediaTypes: { - video: { - playerSize: [640, 480], - context: 'instream' - } - }, - bids: [{ - bidder: 'nexx360', - params: { - account: '1067', - tagId: 'luvxjvgn' - } - }] - }; -``` diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index f788093f833..619b46ecd1f 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -1,4 +1,4 @@ -import { logInfo, deepAccess, logWarn, isArray, getParameterByName } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; @@ -6,15 +6,15 @@ import { getStorageManager } from '../src/storageManager.js'; const GVLID = 816; const BIDDER_CODE = 'nobid'; -const storage = getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE}); -window.nobidVersion = '1.3.2'; +const storage = getStorageManager(GVLID, BIDDER_CODE); +window.nobidVersion = '1.3.1'; window.nobid = window.nobid || {}; window.nobid.bidResponses = window.nobid.bidResponses || {}; window.nobid.timeoutTotal = 0; window.nobid.bidWonTotal = 0; window.nobid.refreshCount = 0; function log(msg, obj) { - logInfo('-NoBid- ' + msg, obj) + utils.logInfo('-NoBid- ' + msg, obj) } function nobidSetCookie(cname, cvalue, hours) { var d = new Date(); @@ -29,7 +29,7 @@ function nobidHasPurpose1Consent(bidderRequest) { let result = true; if (bidderRequest && bidderRequest.gdprConsent) { if (bidderRequest.gdprConsent.gdprApplies && bidderRequest.gdprConsent.apiVersion === 2) { - result = !!(deepAccess(bidderRequest.gdprConsent, 'vendorData.purpose.consents.1') === true); + result = !!(utils.deepAccess(bidderRequest.gdprConsent, 'vendorData.purpose.consents.1') === true); } } return result; @@ -112,11 +112,11 @@ function nobidBuildRequests(bids, bidderRequest) { var height = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); return `${width}x${height}`; } catch (e) { - logWarn('Could not parse screen dimensions, error details:', e); + utils.logWarn('Could not parse screen dimensions, error details:', e); } } var getEIDs = function(eids) { - if (isArray(eids) && eids.length > 0) { + if (utils.isArray(eids) && eids.length > 0) { let src = []; eids.forEach((eid) => { let ids = []; @@ -150,9 +150,8 @@ function nobidBuildRequests(bids, bidderRequest) { if (sch) state['schain'] = sch; const cop = coppa(); if (cop) state['coppa'] = cop; - const eids = getEIDs(deepAccess(bids, '0.userIdAsEids')); + const eids = getEIDs(utils.deepAccess(bids, '0.userIdAsEids')); if (eids && eids.length > 0) state['eids'] = eids; - if (config && config.getConfig('ortb2')) state['ortb2'] = config.getConfig('ortb2'); return state; } function newAdunit(adunitObject, adunits) { @@ -229,8 +228,8 @@ function nobidBuildRequests(bids, bidderRequest) { var placementId = bid.params['placementId']; var adType = 'banner'; - const videoMediaType = deepAccess(bid, 'mediaTypes.video'); - const context = deepAccess(bid, 'mediaTypes.video.context'); + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); if (bid.mediaType === VIDEO || (videoMediaType && (context === 'instream' || context === 'outstream'))) { adType = 'video'; } @@ -364,7 +363,7 @@ export const spec = { buildRequests: function(validBidRequests, bidderRequest) { function resolveEndpoint() { var ret = 'https://ads.servenobid.com/'; - var env = (typeof getParameterByName === 'function') && (getParameterByName('nobid-env')); + var env = (typeof utils.getParameterByName === 'function') && (utils.getParameterByName('nobid-env')); if (!env) ret = 'https://ads.servenobid.com/'; else if (env == 'beta') ret = 'https://beta.servenobid.com/'; else if (env == 'dev') ret = '//localhost:8282/'; @@ -449,7 +448,7 @@ export const spec = { } return syncs; } else { - logWarn('-NoBid- Please enable iframe based user sync.', syncOptions); + utils.logWarn('-NoBid- Please enable iframe based user sync.', syncOptions); return []; } }, diff --git a/modules/novatiqIdSystem.js b/modules/novatiqIdSystem.js index ae9cc4c818f..fbfa6ca8abc 100644 --- a/modules/novatiqIdSystem.js +++ b/modules/novatiqIdSystem.js @@ -5,25 +5,24 @@ * @requires module:modules/userId */ -import { logInfo, getWindowLocation } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { ajax } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; -import { getStorageManager } from '../src/storageManager.js'; /** @type {Submodule} */ export const novatiqIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ +/** +* used to link submodule with config +* @type {string} +*/ name: 'novatiq', /** - * decode the stored id value for passing to bid requests - * @function - * @returns {novatiq: {snowflake: string}} - */ +* decode the stored id value for passing to bid requests +* @function +* @returns {novatiq: {snowflake: string}} +*/ decode(novatiqId, config) { let responseObj = { novatiq: { @@ -34,209 +33,52 @@ export const novatiqIdSubmodule = { }, /** - * performs action to obtain id and return a value in the callback's response argument - * @function - * @param {SubmoduleConfig} config - * @returns {id: string} - */ +* performs action to obtain id and return a value in the callback's response argument +* @function +* @param {SubmoduleConfig} config +* @returns {id: string} +*/ getId(config) { - const configParams = config.params || {}; - const urlParams = this.getUrlParams(configParams); - const srcId = this.getSrcId(configParams, urlParams); - const sharedId = this.getSharedId(configParams); - const useCallbacks = this.useCallbacks(configParams); - - logInfo('NOVATIQ config params: ' + JSON.stringify(configParams)); - logInfo('NOVATIQ Sync request used sourceid param: ' + srcId); - logInfo('NOVATIQ Sync request Shared ID: ' + sharedId); - - return this.sendSyncRequest(useCallbacks, sharedId, srcId, urlParams); - }, - - sendSyncRequest(useCallbacks, sharedId, sspid, urlParams) { - const syncUrl = this.getSyncUrl(sharedId, sspid, urlParams); - const url = syncUrl.url; - const novatiqId = syncUrl.novatiqId; - - // for testing - const sharedStatus = (sharedId != undefined && sharedId != false) ? 'Found' : 'Not Found'; - - if (useCallbacks) { - let res = this.sendAsyncSyncRequest(novatiqId, url); ; - res.sharedStatus = sharedStatus; - - return res; - } else { - this.sendSimpleSyncRequest(novatiqId, url); - - return { 'id': novatiqId, - 'sharedStatus': sharedStatus } - } - }, - - sendAsyncSyncRequest(novatiqId, url) { - logInfo('NOVATIQ Setting up ASYNC sync request'); - - const resp = function (callback) { - logInfo('NOVATIQ *** Calling ASYNC sync request'); - - function onSuccess(response, responseObj) { - let syncrc; - var novatiqIdJson = { syncResponse: 0 }; - syncrc = responseObj.status; - logInfo('NOVATIQ Sync Response Code:' + syncrc); - logInfo('NOVATIQ *** ASYNC request returned ' + syncrc); - if (syncrc === 200) { - novatiqIdJson = { 'id': novatiqId, syncResponse: 1 }; - } else { - if (syncrc === 204) { - novatiqIdJson = { 'id': novatiqId, syncResponse: 2 }; - } - } - callback(novatiqIdJson); - } - - ajax(url, - { success: onSuccess }, - undefined, { method: 'GET', withCredentials: false }); + function snowflakeId(placeholder) { + return placeholder + ? (placeholder ^ Math.random() * 16 >> placeholder / 4).toString(16) + : ([1e7] + -1e3 + -4e3 + -8e3 + -1e11 + 1e3).replace(/[018]/g, snowflakeId); } - return {callback: resp}; - }, + const configParams = config.params || {}; + const srcId = this.getSrcId(configParams); + utils.logInfo('NOVATIQ Sync request used sourceid param: ' + srcId); - sendSimpleSyncRequest(novatiqId, url) { - logInfo('NOVATIQ Sending SIMPLE sync request'); + let partnerhost; + partnerhost = window.location.hostname; + utils.logInfo('NOVATIQ partner hostname: ' + partnerhost); + const novatiqId = snowflakeId(); + const url = 'https://spadsync.com/sync?sptoken=' + novatiqId + '&sspid=' + srcId + '&ssphost=' + partnerhost; ajax(url, undefined, undefined, { method: 'GET', withCredentials: false }); - logInfo('NOVATIQ snowflake: ' + novatiqId); - }, - - getNovatiqId(urlParams) { - // standard uuid format - let uuidFormat = [1e7] + -1e3 + -4e3 + -8e3 + -1e11; - if (urlParams.useStandardUuid == false) { - // novatiq standard uuid(like) format - uuidFormat = uuidFormat + 1e3; - } - - return (uuidFormat).replace(/[018]/g, c => - (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) - ); - }, - - getSyncUrl(sharedId, sspid, urlParams) { - let novatiqId = this.getNovatiqId(urlParams); - - let url = 'https://spadsync.com/sync?' + urlParams.novatiqId + '=' + novatiqId; - - if (urlParams.useSspId) { - url = url + '&sspid=' + sspid; - } - - if (urlParams.useSspHost) { - let ssphost = getWindowLocation().hostname; - logInfo('NOVATIQ partner hostname: ' + ssphost); - - url = url + '&ssphost=' + ssphost; - } - - // append on the shared ID if we have one - if (sharedId != null) { - url = url + '&sharedId=' + sharedId; - } - - return { - url: url, - novatiqId: novatiqId - } - }, - - getUrlParams(configParams) { - let urlParams = { - novatiqId: 'snowflake', - useStandardUuid: false, - useSspId: true, - useSspHost: true - } - - if (typeof configParams.urlParams != 'undefined') { - if (configParams.urlParams.novatiqId != undefined) { - urlParams.novatiqId = configParams.urlParams.novatiqId; - } - if (configParams.urlParams.useStandardUuid != undefined) { - urlParams.useStandardUuid = configParams.urlParams.useStandardUuid; - } - if (configParams.urlParams.useSspId != undefined) { - urlParams.useSspId = configParams.urlParams.useSspId; - } - if (configParams.urlParams.useSspHost != undefined) { - urlParams.useSspHost = configParams.urlParams.useSspHost; - } - } - - return urlParams; - }, - - useCallbacks(configParams) { - return typeof configParams.useCallbacks != 'undefined' && configParams.useCallbacks === true; - }, - - useSharedId(configParams) { - return typeof configParams.useSharedId != 'undefined' && configParams.useSharedId === true; + utils.logInfo('NOVATIQ snowflake: ' + novatiqId); + return { 'id': novatiqId } }, - getCookieOrStorageID(configParams) { - let cookieOrStorageID = '_pubcid'; + getSrcId(configParams) { + utils.logInfo('NOVATIQ Configured sourceid param: ' + configParams.sourceid); - if (typeof configParams.sharedIdName != 'undefined' && configParams.sharedIdName != null && configParams.sharedIdName != '') { - cookieOrStorageID = configParams.sharedIdName; - logInfo('NOVATIQ sharedID name redefined: ' + cookieOrStorageID); + function isHex(str) { + var a = parseInt(str, 16); + return (a.toString(16) === str) } - return cookieOrStorageID; - }, - - // return null if we aren't supposed to use one or we are but there isn't one present - getSharedId(configParams) { - let sharedId = null; - if (this.useSharedId(configParams)) { - let cookieOrStorageID = this.getCookieOrStorageID(configParams); - const storage = getStorageManager({moduleName: 'pubCommonId'}); - - // first check local storage - if (storage.hasLocalStorage()) { - sharedId = storage.getDataFromLocalStorage(cookieOrStorageID); - logInfo('NOVATIQ sharedID retrieved from local storage:' + sharedId); - } - - // if nothing check the local cookies - if (sharedId == null) { - sharedId = storage.getCookie(cookieOrStorageID); - logInfo('NOVATIQ sharedID retrieved from cookies:' + sharedId); - } - } - - logInfo('NOVATIQ sharedID returning: ' + sharedId); - - return sharedId; - }, - - getSrcId(configParams, urlParams) { - if (urlParams.useSspId == false) { - logInfo('NOVATIQ Configured to NOT use sspid'); - return ''; - } - - logInfo('NOVATIQ Configured sourceid param: ' + configParams.sourceid); - let srcId; if (typeof configParams.sourceid === 'undefined' || configParams.sourceid === null || configParams.sourceid === '') { srcId = '000'; - logInfo('NOVATIQ sourceid param set to value 000 due to undefined parameter or missing value in config section'); + utils.logInfo('NOVATIQ sourceid param set to value 000 due to undefined parameter or missing value in config section'); } else if (configParams.sourceid.length < 3 || configParams.sourceid.length > 3) { srcId = '001'; - logInfo('NOVATIQ sourceid param set to value 001 due to wrong size in config section 3 chars max e.g. 1ab'); + utils.logInfo('NOVATIQ sourceid param set to value 001 due to wrong size in config section 3 chars max e.g. 1ab'); + } else if (isHex(configParams.sourceid) == false) { + srcId = '002'; + utils.logInfo('NOVATIQ sourceid param set to value 002 due to wrong format in config section expecting hex value only'); } else { srcId = configParams.sourceid; } diff --git a/modules/novatiqIdSystem.md b/modules/novatiqIdSystem.md index f33fc700311..ce561a696e3 100644 --- a/modules/novatiqIdSystem.md +++ b/modules/novatiqIdSystem.md @@ -1,8 +1,8 @@ -# Novatiq Hyper ID +# Novatiq Snowflake ID -The Novatiq proprietary dynamic Hyper ID is a unique, non sequential and single use identifier for marketing activation. Our in network solution matches verification requests to telco network IDs safely and securely inside telecom infrastructure. The Novatiq Hyper ID can be used for identity validation and as a secured 1st party data delivery mechanism. +Novatiq proprietary dynamic snowflake ID is a unique, non sequential and single use identifier for marketing activation. Our in network solution matches verification requests to telco network IDs, safely and securely inside telecom infrastructure. Novatiq snowflake ID can be used for identity validation and as a secured 1st party data delivery mechanism. -## Novatiq Hyper ID Configuration +## Novatiq Snowflake ID Configuration Enable by adding the Novatiq submodule to your Prebid.js package with: @@ -18,80 +18,19 @@ pbjs.setConfig({ userIds: [{ name: 'novatiq', params: { - // change to the Partner Number you received from Novatiq - sourceid '1a3' + sourceid '1a3', // change to the Partner Number you received from Novatiq } } }], - // 50ms maximum auction delay, applies to all userId modules - auctionDelay: 50 + auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules } }); ``` -### Parameters for the Novatiq Module -| Param | Scope | Type | Description | Example | +| Param under userSync.userIds[] | Scope | Type | Description | Example | | --- | --- | --- | --- | --- | | name | Required | String | Module identification: `"novatiq"` | `"novatiq"` | | params | Required | Object | Configuration specifications for the Novatiq module. | | -| params.sourceid | Required | String | The Novatiq Partner Number obtained via Novatiq | `1a3` | -| params.useSharedId | Optional | Boolean | Use the sharedID module if it's activated. | `true` | -| params.sharedIdName | Optional | String | Same as the SharedID "name" parameter
Defaults to "_pubcid" | `"demo_pubcid"` | -| params.useCallbacks | Optional | Boolean | Use callbacks for custom integrations | `false` | -| params.urlParams | Optional | Object | Sync URl configuration for custom integrations | | -| params.urlParams.novatiqId | Optional | String | The name of the parameter used to indicate the novatiq ID uuid | `snowflake` | -| params.urlParams.useStandardUuid | Optional | Boolean | Use a standard UUID format, or the Novatiq UUID format | `false` | -| params.urlParams.useSspId | Optional | Boolean | Send the sspid (sourceid) along with the sync request | `false` | -| params.urlParams.useSspHost | Optional | Boolean | Send the ssphost along with the sync request | `false` | - -# Novatiq Hyper ID with Prebid SharedID support -You can make use of the Prebid.js SharedId module as follows. - -## Novatiq Hyper ID Configuration - -Enable by adding the Novatiq and SharedId submodule to your Prebid.js package with: - -``` -gulp build --modules=novatiqIdSystem,userId,pubCommonId -``` - -Module activation and configuration: - -```javascript -pbjs.setConfig({ - userSync: { - userIds: [ - { - name: "pubCommonId", - storage: { - type: "cookie", - // optional: will default to _pubcid if left blank - name: "demo_pubcid", - - // expires in 1 years - expires: 365 - }, - bidders: [ 'adtarget' ] - }, - { - name: 'novatiq', - params: { - // change to the Partner Number you received from Novatiq - sourceid '1a3', - - // Use the sharedID module - useSharedId: true, - - // optional: will default to _pubcid if left blank. - // If not left blank must match "name" in the the module above - sharedIdName: 'demo_pubcid' - } - } - }], - // 50ms maximum auction delay, applies to all userId modules - auctionDelay: 50 - } -}); -``` +| params.sourceid | Required | String | This is the Novatiq Partner Number obtained via Novatiq registration. | `1a3` | If you have any questions, please reach out to us at prebid@novatiq.com. diff --git a/modules/oguryBidAdapter.js b/modules/oguryBidAdapter.js index 7d2989b2066..2e5342e6f9e 100644 --- a/modules/oguryBidAdapter.js +++ b/modules/oguryBidAdapter.js @@ -1,16 +1,14 @@ 'use strict'; import { BANNER } from '../src/mediaTypes.js'; -import { getAdUnitSizes, logWarn, isFn, getWindowTop, getWindowSelf } from '../src/utils.js'; +import { getAdUnitSizes, logWarn, isFn } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { ajax } from '../src/ajax.js' const BIDDER_CODE = 'ogury'; const DEFAULT_TIMEOUT = 1000; const BID_HOST = 'https://mweb-hb.presage.io/api/header-bidding-request'; -const TIMEOUT_MONITORING_HOST = 'https://ms-ads-monitoring-events.presage.io'; const MS_COOKIE_SYNC_DOMAIN = 'https://ms-cookie-sync.presage.io'; -const ADAPTER_VERSION = '1.2.10'; function isBidRequestValid(bid) { const adUnitSizes = getAdUnitSizes(bid); @@ -25,45 +23,41 @@ function isBidRequestValid(bid) { function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent) { if (!syncOptions.pixelEnabled) return []; - return [ - { - type: 'image', - url: `${MS_COOKIE_SYNC_DOMAIN}/v1/init-sync/bid-switch?iab_string=${(gdprConsent && gdprConsent.consentString) || ''}&source=prebid` - }, - { - type: 'image', - url: `${MS_COOKIE_SYNC_DOMAIN}/ttd/init-sync?iab_string=${(gdprConsent && gdprConsent.consentString) || ''}&source=prebid` - } - ] + return [{ + type: 'image', + url: `${MS_COOKIE_SYNC_DOMAIN}/v1/init-sync/bid-switch?iab_string=${gdprConsent.consentString}&source=prebid` + }] } function buildRequests(validBidRequests, bidderRequest) { const openRtbBidRequestBanner = { id: bidderRequest.auctionId, tmax: DEFAULT_TIMEOUT, - at: 1, + at: 2, regs: { ext: { - gdpr: bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies ? 1 : 0 + gdpr: 1 }, }, site: { - domain: location.hostname, - page: location.href + domain: location.hostname }, user: { ext: { consent: '' } }, - imp: [], - ext: { - adapterversion: ADAPTER_VERSION, - prebidversion: '$prebid.version$' - } + imp: [] }; - if (bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString) { + if (bidderRequest.hasOwnProperty('gdprConsent') && + bidderRequest.gdprConsent.hasOwnProperty('gdprApplies')) { + openRtbBidRequestBanner.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0 + } + + if (bidderRequest.hasOwnProperty('gdprConsent') && + bidderRequest.gdprConsent.hasOwnProperty('consentString') && + bidderRequest.gdprConsent.consentString.length > 0) { openRtbBidRequestBanner.user.ext.consent = bidderRequest.gdprConsent.consentString } @@ -71,7 +65,7 @@ function buildRequests(validBidRequests, bidderRequest) { const sizes = getAdUnitSizes(bidRequest) .map(size => ({ w: size[0], h: size[1] })); - if (bidRequest.mediaTypes && + if (bidRequest.hasOwnProperty('mediaTypes') && bidRequest.mediaTypes.hasOwnProperty('banner')) { openRtbBidRequestBanner.site.id = bidRequest.params.assetKey; @@ -81,8 +75,7 @@ function buildRequests(validBidRequests, bidderRequest) { bidfloor: getFloor(bidRequest), banner: { format: sizes - }, - ext: bidRequest.params + } }); } }); @@ -121,9 +114,7 @@ function interpretResponse(openRtbBidResponse) { meta: { advertiserDomains: bid.adomain }, - nurl: bid.nurl, - adapterVersion: ADAPTER_VERSION, - prebidVersion: '$prebid.version$' + nurl: bid.nurl }; bidResponse.ad = bid.adm; @@ -146,27 +137,8 @@ function getFloor(bid) { return floorResult.currency === 'USD' ? floorResult.floor : 0; } -function getWindowContext() { - try { - return getWindowTop() - } catch (e) { - return getWindowSelf() - } -} - function onBidWon(bid) { - const w = getWindowContext() - w.OG_PREBID_BID_OBJECT = { - ...(bid && { ...bid }), - } - if (bid && bid.nurl) ajax(bid.nurl, null); -} - -function onTimeout(timeoutData) { - ajax(`${TIMEOUT_MONITORING_HOST}/bid_timeout`, null, JSON.stringify({...timeoutData[0], location: window.location.href}), { - method: 'POST', - contentType: 'application/json' - }); + if (bid && bid.hasOwnProperty('nurl') && bid.nurl.length > 0) ajax(bid['nurl'], null); } export const spec = { @@ -177,9 +149,7 @@ export const spec = { buildRequests, interpretResponse, getFloor, - onBidWon, - getWindowContext, - onTimeout + onBidWon } registerBidder(spec); diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index aeb19e7c32c..880f4992614 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -1,4 +1,4 @@ -import { logError, logWarn, parseSizesInput, generateUUID, isFn, logMessage, isPlainObject, isStr, isNumber, isArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'oneVideo'; @@ -10,7 +10,6 @@ export const spec = { SYNC_ENDPOINT1: 'https://pixel.advertising.com/ups/57304/sync?gdpr=&gdpr_consent=&_origin=0&redir=true', SYNC_ENDPOINT2: 'https://match.adsrvr.org/track/cmf/generic?ttd_pid=adaptv&ttd_tpi=1', supportedMediaTypes: ['video', 'banner'], - gvlid: 25, /** * Determines whether or not the given bid request is valid. * @@ -29,7 +28,7 @@ export const spec = { } // MediaTypes Video / Banner validation if (typeof bid.mediaTypes.video === 'undefined' && typeof bid.mediaTypes.banner === 'undefined') { - logError('Failed validation: adUnit mediaTypes.video OR mediaTypes.banner not declared'); + utils.logError('Failed validation: adUnit mediaTypes.video OR mediaTypes.banner not declared'); return false; }; @@ -37,27 +36,27 @@ export const spec = { // Player size validation if (typeof bid.mediaTypes.video.playerSize === 'undefined') { if (bid.params.video && (typeof bid.params.video.playerWidth === 'undefined' || typeof bid.params.video.playerHeight === 'undefined')) { - logError('Failed validation: Player size not declared in either mediaTypes.playerSize OR bid.params.video.plauerWidth & bid.params.video.playerHeight.'); + utils.logError('Failed validation: Player size not declared in either mediaTypes.playerSize OR bid.params.video.plauerWidth & bid.params.video.playerHeight.'); return false; }; }; // Mimes validation if (typeof bid.mediaTypes.video.mimes === 'undefined') { if (!bid.params.video || typeof bid.params.video.mimes === 'undefined') { - logError('Failed validation: adUnit mediaTypes.mimes OR params.video.mimes not declared'); + utils.logError('Failed validation: adUnit mediaTypes.mimes OR params.video.mimes not declared'); return false; }; }; // Prevend DAP Outstream validation, Banner DAP validation & Multi-Format adUnit support if (bid.mediaTypes.video.context === 'outstream' && bid.params.video && bid.params.video.display === 1) { - logError('Failed validation: Dynamic Ad Placement cannot be used with context Outstream (params.video.display=1)'); + utils.logError('Failed validation: Dynamic Ad Placement cannot be used with context Outstream (params.video.display=1)'); return false; }; }; // Publisher Id (Exchange) validation if (typeof bid.params.pubId === 'undefined') { - logError('Failed validation: Adapter cannot send requests without bid.params.pubId'); + utils.logError('Failed validation: Adapter cannot send requests without bid.params.pubId'); return false; } @@ -107,7 +106,7 @@ export const spec = { response = null; } if (!response || !bid || (!bid.adm && !bid.nurl) || !bid.price) { - logWarn(`No valid bids from ${spec.code} bidder`); + utils.logWarn(`No valid bids from ${spec.code} bidder`); return []; } size = getSize(bidRequest.sizes); @@ -173,7 +172,7 @@ export const spec = { }; function getSize(sizes) { - let parsedSizes = parseSizesInput(sizes); + let parsedSizes = utils.parseSizesInput(sizes); let [ width, height ] = parsedSizes.length ? parsedSizes[0].split('x') : []; return { width: parseInt(width, 10) || undefined, @@ -195,7 +194,7 @@ function getRequestData(bid, consentData, bidRequest) { size: '*' }; let bidData = { - id: generateUUID(), + id: utils.generateUUID(), at: 2, imp: [{ id: '1', @@ -287,7 +286,7 @@ function getRequestData(bid, consentData, bidRequest) { } } - if (isFn(bid.getFloor)) { + if (utils.isFn(bid.getFloor)) { let floorData = bid.getFloor(getFloorRequestObject); bidData.imp[0].bidfloor = floorData.floor; bidData.cur = floorData.currency; @@ -345,7 +344,7 @@ function getRequestData(bid, consentData, bidRequest) { } } if (bid.params.video.e2etest) { - logMessage('E2E test mode enabled: \n The following parameters are being overridden by e2etest mode:\n* bidfloor:null\n* width:300\n* height:250\n* mimes: video/mp4, application/javascript\n* api:2\n* site.page/ref: verizonmedia.com\n* tmax:1000'); + utils.logMessage('E2E test mode enabled: \n The following parameters are being overridden by e2etest mode:\n* bidfloor:null\n* width:300\n* height:250\n* mimes: video/mp4, application/javascript\n* api:2\n* site.page/ref: verizonmedia.com\n* tmax:1000'); bidData.imp[0].bidfloor = null; bidData.imp[0].video.w = 300; bidData.imp[0].video.h = 250; @@ -355,15 +354,15 @@ function getRequestData(bid, consentData, bidRequest) { bidData.site.ref = 'https://verizonmedia.com'; bidData.tmax = 1000; } - if (bid.params.video.custom && isPlainObject(bid.params.video.custom)) { + if (bid.params.video.custom && utils.isPlainObject(bid.params.video.custom)) { bidData.imp[0].ext.custom = {}; for (const key in bid.params.video.custom) { - if (isStr(bid.params.video.custom[key]) || isNumber(bid.params.video.custom[key])) { + if (utils.isStr(bid.params.video.custom[key]) || utils.isNumber(bid.params.video.custom[key])) { bidData.imp[0].ext.custom[key] = bid.params.video.custom[key]; } } } - if (bid.params.video.content && isPlainObject(bid.params.video.content)) { + if (bid.params.video.content && utils.isPlainObject(bid.params.video.content)) { bidData.site.content = {}; const contentStringKeys = ['id', 'title', 'series', 'season', 'genre', 'contentrating', 'language']; const contentNumberkeys = ['episode', 'prodq', 'context', 'livestream', 'len']; @@ -371,14 +370,14 @@ function getRequestData(bid, consentData, bidRequest) { const contentObjectKeys = ['ext']; for (const contentKey in bid.params.video.content) { if ( - (contentStringKeys.indexOf(contentKey) > -1 && isStr(bid.params.video.content[contentKey])) || - (contentNumberkeys.indexOf(contentKey) > -1 && isNumber(bid.params.video.content[contentKey])) || - (contentObjectKeys.indexOf(contentKey) > -1 && isPlainObject(bid.params.video.content[contentKey])) || - (contentArrayKeys.indexOf(contentKey) > -1 && isArray(bid.params.video.content[contentKey]) && - bid.params.video.content[contentKey].every(catStr => isStr(catStr)))) { + (contentStringKeys.indexOf(contentKey) > -1 && utils.isStr(bid.params.video.content[contentKey])) || + (contentNumberkeys.indexOf(contentKey) > -1 && utils.isNumber(bid.params.video.content[contentKey])) || + (contentObjectKeys.indexOf(contentKey) > -1 && utils.isPlainObject(bid.params.video.content[contentKey])) || + (contentArrayKeys.indexOf(contentKey) > -1 && utils.isArray(bid.params.video.content[contentKey]) && + bid.params.video.content[contentKey].every(catStr => utils.isStr(catStr)))) { bidData.site.content[contentKey] = bid.params.video.content[contentKey]; } else { - logMessage('oneVideo bid adapter validation error: ', contentKey, ' is either not supported is OpenRTB V2.5 or value is undefined'); + utils.logMessage('oneVideo bid adapter validation error: ', contentKey, ' is either not supported is OpenRTB V2.5 or value is undefined'); } } } diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js index 89c614dba23..aab68176d87 100644 --- a/modules/onetagBidAdapter.js +++ b/modules/onetagBidAdapter.js @@ -1,20 +1,19 @@ 'use strict'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {INSTREAM, OUTSTREAM} from '../src/video.js'; -import {Renderer} from '../src/Renderer.js'; -import {find} from '../src/polyfill.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {createEidsArray} from './userId/eids.js'; -import {deepClone} from '../src/utils.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { INSTREAM, OUTSTREAM } from '../src/video.js'; +import { Renderer } from '../src/Renderer.js'; +import find from 'core-js-pure/features/array/find.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { createEidsArray } from './userId/eids.js'; const ENDPOINT = 'https://onetag-sys.com/prebid-request'; const USER_SYNC_ENDPOINT = 'https://onetag-sys.com/usync/'; const BIDDER_CODE = 'onetag'; const GVLID = 241; -const storage = getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE}); +const storage = getStorageManager(GVLID); /** * Determines whether or not the given bid request is valid. @@ -206,8 +205,8 @@ function getPageInfo() { ? topmostFrame.document.referrer : null, ancestorOrigin: - window.location.ancestorOrigins && window.location.ancestorOrigins.length > 0 - ? window.location.ancestorOrigins[window.location.ancestorOrigins.length - 1] + window.location.ancestorOrigins && window.location.ancestorOrigins[0] != null + ? window.location.ancestorOrigins[0] : null, masked: currentFrameNesting, wWidth: topmostFrame.innerWidth, @@ -240,10 +239,15 @@ function requestsToBids(bidRequests) { // Pass parameters // Context: instream - outstream - adpod videoObj['context'] = bidRequest.mediaTypes.video.context; + // MIME Video Types + videoObj['mimes'] = bidRequest.mediaTypes.video.mimes; // Sizes videoObj['playerSize'] = parseVideoSize(bidRequest); // Other params - videoObj['mediaTypeInfo'] = deepClone(bidRequest.mediaTypes.video); + videoObj['protocols'] = bidRequest.mediaTypes.video.protocols; + videoObj['maxDuration'] = bidRequest.mediaTypes.video.maxduration; + videoObj['api'] = bidRequest.mediaTypes.video.api; + videoObj['playbackmethod'] = bidRequest.mediaTypes.video.playbackmethod || []; videoObj['type'] = VIDEO; return videoObj; }); @@ -252,7 +256,6 @@ function requestsToBids(bidRequests) { setGeneralInfo.call(bannerObj, bidRequest); bannerObj['sizes'] = parseSizes(bidRequest); bannerObj['type'] = BANNER; - bannerObj['mediaTypeInfo'] = deepClone(bidRequest.mediaTypes.banner); return bannerObj; }); return videoBidRequests.concat(bannerBidRequests); @@ -347,13 +350,11 @@ function getSizes(sizes) { function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent) { let syncs = []; let params = ''; - if (gdprConsent) { + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + params += '&gdpr_consent=' + gdprConsent.consentString; if (typeof gdprConsent.gdprApplies === 'boolean') { params += '&gdpr=' + (gdprConsent.gdprApplies ? 1 : 0); } - if (typeof gdprConsent.consentString === 'string') { - params += '&gdpr_consent=' + gdprConsent.consentString; - } } if (uspConsent && typeof uspConsent === 'string') { params += '&us_privacy=' + uspConsent; diff --git a/modules/onomagicBidAdapter.js b/modules/onomagicBidAdapter.js index 25b0f1a5934..548c0170c05 100644 --- a/modules/onomagicBidAdapter.js +++ b/modules/onomagicBidAdapter.js @@ -1,4 +1,4 @@ -import { getBidIdParameter, _each, isArray, getWindowTop, getUniqueIdentifierStr, parseUrl, logError, logWarn, createTrackPixelHtml, getWindowSelf, isFn, isPlainObject } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; @@ -22,17 +22,17 @@ function buildRequests(bidReqs, bidderRequest) { referrer = bidderRequest.refererInfo.referer; } const onomagicImps = []; - const publisherId = getBidIdParameter('publisherId', bidReqs[0].params); - _each(bidReqs, function (bid) { + const publisherId = utils.getBidIdParameter('publisherId', bidReqs[0].params); + utils._each(bidReqs, function (bid) { let bidSizes = (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) || bid.sizes; - bidSizes = ((isArray(bidSizes) && isArray(bidSizes[0])) ? bidSizes : [bidSizes]); - bidSizes = bidSizes.filter(size => isArray(size)); + bidSizes = ((utils.isArray(bidSizes) && utils.isArray(bidSizes[0])) ? bidSizes : [bidSizes]); + bidSizes = bidSizes.filter(size => utils.isArray(size)); const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); const element = document.getElementById(bid.adUnitCode); const minSize = _getMinSize(processedSizes); const viewabilityAmount = _isViewabilityMeasurable(element) - ? _getViewability(element, getWindowTop(), minSize) + ? _getViewability(element, utils.getWindowTop(), minSize) : 'na'; const viewabilityAmountRounded = isNaN(viewabilityAmount) ? viewabilityAmount : Math.round(viewabilityAmount); @@ -53,10 +53,10 @@ function buildRequests(bidReqs, bidderRequest) { onomagicImps.push(imp); }); const onomagicBidReq = { - id: getUniqueIdentifierStr(), + id: utils.getUniqueIdentifierStr(), imp: onomagicImps, site: { - domain: parseUrl(referrer).host, + domain: utils.parseUrl(referrer).host, page: referrer, publisher: { id: publisherId @@ -77,7 +77,7 @@ function buildRequests(bidReqs, bidderRequest) { options: {contentType: 'text/plain', withCredentials: false} }; } catch (e) { - logError(e, {bidReqs, bidderRequest}); + utils.logError(e, {bidReqs, bidderRequest}); } } @@ -95,7 +95,7 @@ function isBidRequestValid(bid) { function interpretResponse(serverResponse) { if (!serverResponse.body || typeof serverResponse.body != 'object') { - logWarn('Onomagic server returned empty/non-json response: ' + JSON.stringify(serverResponse.body)); + utils.logWarn('Onomagic server returned empty/non-json response: ' + JSON.stringify(serverResponse.body)); return []; } const { body: {id, seatbid} } = serverResponse; @@ -126,7 +126,7 @@ function interpretResponse(serverResponse) { } return onomagicBidResponses; } catch (e) { - logError(e, {id, seatbid}); + utils.logError(e, {id, seatbid}); } } @@ -150,7 +150,7 @@ function _getDeviceType() { function _getAdMarkup(bid) { let adm = bid.adm; if ('nurl' in bid) { - adm += createTrackPixelHtml(bid.nurl); + adm += utils.createTrackPixelHtml(bid.nurl); } return adm; } @@ -160,14 +160,14 @@ function _isViewabilityMeasurable(element) { } function _getViewability(element, topWin, { w, h } = {}) { - return getWindowTop().document.visibilityState === 'visible' + return utils.getWindowTop().document.visibilityState === 'visible' ? _getPercentInView(element, topWin, { w, h }) : 0; } function _isIframe() { try { - return getWindowSelf() !== getWindowTop(); + return utils.getWindowSelf() !== utils.getWindowTop(); } catch (e) { return true; } @@ -247,7 +247,7 @@ function _getPercentInView(element, topWin, { w, h } = {}) { } function _getBidFloor(bid) { - if (!isFn(bid.getFloor)) { + if (!utils.isFn(bid.getFloor)) { return bid.params.bidFloor ? bid.params.bidFloor : null; } @@ -256,7 +256,7 @@ function _getBidFloor(bid) { mediaType: '*', size: '*' }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { + if (utils.isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { return floor.floor; } return null; diff --git a/modules/ooloAnalyticsAdapter.js b/modules/ooloAnalyticsAdapter.js index 398459d604d..7195d6ac177 100644 --- a/modules/ooloAnalyticsAdapter.js +++ b/modules/ooloAnalyticsAdapter.js @@ -1,7 +1,7 @@ -import { _each, deepClone, pick, deepSetValue, getOrigin, logError, logInfo } from '../src/utils.js'; import adapter from '../src/AnalyticsAdapter.js' import adapterManager from '../src/adapterManager.js' import CONSTANTS from '../src/constants.json' +import * as utils from '../src/utils.js' import { ajax } from '../src/ajax.js' import { config } from '../src/config.js' @@ -64,7 +64,7 @@ const onAuctionInit = (args) => { handleCustomFields(auction, AUCTION_INIT, args) - _each(adUnits, adUnit => { + utils._each(adUnits, adUnit => { auction.adUnits[adUnit.code] = { ...adUnit, auctionId, @@ -144,7 +144,7 @@ const onBidWon = (args) => { } const onBidTimeout = (args) => { - _each(args, bid => { + utils._each(args, bid => { const { auctionId, adUnitCode } = bid const bidId = parseBidId(bid) let bidCache = auctions[auctionId].adUnits[adUnitCode].bids[bidId] @@ -172,7 +172,7 @@ const onAuctionEnd = (args) => { } const onAdRenderFailed = (args) => { - const data = deepClone(args) + const data = utils.deepClone(args) data.timestamp = Date.now() if (data.bid) { @@ -232,7 +232,7 @@ function handleEvent(eventType, args) { } function sendEvent(eventType, args, isRaw) { - let data = deepClone(args) + let data = utils.deepClone(args) Object.assign(data, buildCommonDataProperties(), { eventType @@ -268,7 +268,7 @@ function checkEventsQueue() { } function buildAuctionData(auction) { - const auctionData = deepClone(auction) + const auctionData = utils.deepClone(auction) const keysToRemove = ['adUnitCodes', 'auctionStatus', 'bidderRequests', 'bidsReceived', 'noBids', 'winningBids', 'timestamp', 'config'] keysToRemove.forEach(key => { @@ -367,12 +367,12 @@ function handleCustomFields(obj, eventType, args) { const { pickFields, omitFields } = initOptions.serverConfig.events[eventType] if (pickFields && obj && args) { - Object.assign(obj, pick(args, pickFields)) + Object.assign(obj, utils.pick(args, pickFields)) } if (omitFields && obj && args) { omitFields.forEach(field => { - deepSetValue(obj, field, undefined) + utils.deepSetValue(obj, field, undefined) }) } } catch (e) { } @@ -382,7 +382,7 @@ function handleCustomRawFields(obj, omitRawFields) { try { if (omitRawFields && obj) { omitRawFields.forEach(field => { - deepSetValue(obj, field, undefined) + utils.deepSetValue(obj, field, undefined) }) } } catch (e) { } @@ -419,7 +419,7 @@ function sendPage() { screenHeight: window.screen.height, url: window.location.href, protocol: window.location.protocol, - origin: getOrigin(), + origin: utils.getOrigin(), referrer: getTopWindowReferrer(), pbVersion: prebidVersion, } @@ -507,7 +507,7 @@ ooloAdapter.enableAnalytics = function (config) { initOptions = config ? config.options : {} if (!initOptions.pid) { - logError(buildLogMessage('enableAnalytics missing config object with "pid"')) + utils.logError(buildLogMessage('enableAnalytics missing config object with "pid"')) return } @@ -520,9 +520,9 @@ ooloAdapter.enableAnalytics = function (config) { window.addEventListener('load', sendPage) } - logInfo(buildLogMessage('enabled analytics adapter'), config) + utils.logInfo(buildLogMessage('enabled analytics adapter'), config) ooloAdapter.enableAnalytics = function () { - logInfo(buildLogMessage('Analytics adapter already enabled..')) + utils.logInfo(buildLogMessage('Analytics adapter already enabled..')) } } diff --git a/modules/open8BidAdapter.js b/modules/open8BidAdapter.js deleted file mode 100644 index 7fa97235525..00000000000 --- a/modules/open8BidAdapter.js +++ /dev/null @@ -1,188 +0,0 @@ -import { Renderer } from '../src/Renderer.js'; -import {ajax} from '../src/ajax.js'; -import { createTrackPixelHtml, getBidIdParameter, logError, logWarn, tryAppendQueryString } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { VIDEO, BANNER } from '../src/mediaTypes.js'; - -const BIDDER_CODE = 'open8'; -const URL = 'https://as.vt.open8.com/v1/control/prebid'; -const AD_TYPE = { - VIDEO: 1, - BANNER: 2 -}; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [VIDEO, BANNER], - - isBidRequestValid: function(bid) { - return !!(bid.params.slotKey); - }, - - buildRequests: function(validBidRequests, bidderRequest) { - var requests = []; - for (var i = 0; i < validBidRequests.length; i++) { - var bid = validBidRequests[i]; - var queryString = ''; - var slotKey = getBidIdParameter('slotKey', bid.params); - queryString = tryAppendQueryString(queryString, 'slot_key', slotKey); - queryString = tryAppendQueryString(queryString, 'imp_id', generateImpId()); - queryString += ('bid_id=' + bid.bidId); - - requests.push({ - method: 'GET', - url: URL, - data: queryString - }); - } - return requests; - }, - - interpretResponse: function(serverResponse, request) { - var bidderResponse = serverResponse.body; - - if (!bidderResponse.isAdReturn) { - return []; - } - - var ad = bidderResponse.ad; - - const bid = { - slotKey: bidderResponse.slotKey, - userId: bidderResponse.userId, - impId: bidderResponse.impId, - media: bidderResponse.media, - ds: ad.ds, - spd: ad.spd, - fa: ad.fa, - pr: ad.pr, - mr: ad.mr, - nurl: ad.nurl, - requestId: ad.bidId, - cpm: ad.price, - creativeId: ad.creativeId, - dealId: ad.dealId, - currency: ad.currency || 'JPY', - netRevenue: true, - ttl: 360, // 6 minutes - meta: { - advertiserDomains: ad.adomain || [] - } - } - - if (ad.adType === AD_TYPE.VIDEO) { - const videoAd = bidderResponse.ad.video; - Object.assign(bid, { - vastXml: videoAd.vastXml, - width: videoAd.w, - height: videoAd.h, - renderer: newRenderer(bidderResponse), - adResponse: bidderResponse, - mediaType: VIDEO - }); - } else if (ad.adType === AD_TYPE.BANNER) { - const bannerAd = bidderResponse.ad.banner; - Object.assign(bid, { - width: bannerAd.w, - height: bannerAd.h, - ad: bannerAd.adm, - mediaType: BANNER - }); - if (bannerAd.imps) { - try { - bannerAd.imps.forEach(impTrackUrl => { - const tracker = createTrackPixelHtml(impTrackUrl); - bid.ad += tracker; - }); - } catch (error) { - logError('Error appending imp tracking pixel', error); - } - } - } - return [bid]; - }, - - getUserSyncs: function(syncOptions, serverResponses) { - const syncs = []; - if (syncOptions.iframeEnabled && serverResponses.length) { - const syncIFs = serverResponses[0].body.syncIFs; - if (syncIFs) { - syncIFs.forEach(sync => { - syncs.push({ - type: 'iframe', - url: sync - }); - }); - } - } - if (syncOptions.pixelEnabled && serverResponses.length) { - const syncPixs = serverResponses[0].body.syncPixels; - if (syncPixs) { - syncPixs.forEach(sync => { - syncs.push({ - type: 'image', - url: sync - }); - }); - } - } - return syncs; - }, - onBidWon: function(bid) { - if (!bid.nurl) { return; } - const winUrl = bid.nurl.replace( - /\$\{AUCTION_PRICE\}/, - bid.cpm - ); - ajax(winUrl, null); - } -} - -function generateImpId() { - var l = 16; - var c = 'abcdefghijklmnopqrstuvwsyz0123456789'; - var cl = c.length; - var r = ''; - for (var i = 0; i < l; i++) { - r += c[Math.floor(Math.random() * cl)]; - } - return r; -} - -function newRenderer(bidderResponse) { - const renderer = Renderer.install({ - id: bidderResponse.ad.bidId, - url: bidderResponse.ad.video.purl, - loaded: false, - }); - - try { - renderer.setRender(outstreamRender); - } catch (err) { - logWarn('Prebid Error calling setRender on newRenderer', err); - } - - return renderer; -} - -function outstreamRender(bid) { - bid.renderer.push(() => { - window.op8.renderPrebid({ - vastXml: bid.vastXml, - adUnitCode: bid.adUnitCode, - slotKey: bid.slotKey, - impId: bid.impId, - userId: bid.userId, - media: bid.media, - ds: bid.ds, - spd: bid.spd, - fa: bid.fa, - pr: bid.pr, - mr: bid.mr, - adResponse: bid.adResponse, - mediaType: bid.mediaType - }); - }); -} - -registerBidder(spec); diff --git a/modules/openwebBidAdapter.js b/modules/openwebBidAdapter.js index f515eb14011..ef776ea81f5 100644 --- a/modules/openwebBidAdapter.js +++ b/modules/openwebBidAdapter.js @@ -1,8 +1,8 @@ -import {convertTypes, deepAccess, flatten, isArray, isNumber, parseSizesInput} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {ADPOD, BANNER, VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {find} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { ADPOD, BANNER, VIDEO } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import find from 'core-js-pure/features/array/find.js'; const ENDPOINT = 'https://ghb.spotim.market/v2/auction'; const BIDDER_CODE = 'openweb'; @@ -14,7 +14,7 @@ export const spec = { gvlid: 280, supportedMediaTypes: [VIDEO, BANNER, ADPOD], isBidRequestValid: function (bid) { - return isNumber(deepAccess(bid, 'params.aid')); + return utils.isNumber(utils.deepAccess(bid, 'params.aid')); }, getUserSyncs: function (syncOptions, serverResponses) { const syncs = []; @@ -43,9 +43,9 @@ export const spec = { } if (syncOptions.pixelEnabled || syncOptions.iframeEnabled) { - isArray(serverResponses) && serverResponses.forEach((response) => { + utils.isArray(serverResponses) && serverResponses.forEach((response) => { if (response.body) { - if (isArray(response.body)) { + if (utils.isArray(response.body)) { response.body.forEach(b => { addSyncs(b); }) @@ -82,26 +82,26 @@ export const spec = { serverResponse = serverResponse.body; let bids = []; - if (!isArray(serverResponse)) { + if (!utils.isArray(serverResponse)) { return parseRTBResponse(serverResponse, adapterRequest); } serverResponse.forEach(serverBidResponse => { - bids = flatten(bids, parseRTBResponse(serverBidResponse, adapterRequest)); + bids = utils.flatten(bids, parseRTBResponse(serverBidResponse, adapterRequest)); }); return bids; }, transformBidParams(params) { - return convertTypes({ + return utils.convertTypes({ 'aid': 'number', }, params); } }; function parseRTBResponse(serverResponse, adapterRequest) { - const isEmptyResponse = !serverResponse || !isArray(serverResponse.bids); + const isEmptyResponse = !serverResponse || !utils.isArray(serverResponse.bids); const bids = []; if (isEmptyResponse) { @@ -126,26 +126,26 @@ function parseRTBResponse(serverResponse, adapterRequest) { function bidToTag(bidRequests, adapterRequest) { // start publisher env const tag = { - Domain: deepAccess(adapterRequest, 'refererInfo.referer') + Domain: utils.deepAccess(adapterRequest, 'refererInfo.referer') }; if (config.getConfig('coppa') === true) { tag.Coppa = 1; } - if (deepAccess(adapterRequest, 'gdprConsent.gdprApplies')) { + if (utils.deepAccess(adapterRequest, 'gdprConsent.gdprApplies')) { tag.GDPR = 1; - tag.GDPRConsent = deepAccess(adapterRequest, 'gdprConsent.consentString'); + tag.GDPRConsent = utils.deepAccess(adapterRequest, 'gdprConsent.consentString'); } - if (deepAccess(adapterRequest, 'uspConsent')) { - tag.USP = deepAccess(adapterRequest, 'uspConsent'); + if (utils.deepAccess(adapterRequest, 'uspConsent')) { + tag.USP = utils.deepAccess(adapterRequest, 'uspConsent'); } - if (deepAccess(bidRequests[0], 'schain')) { - tag.Schain = deepAccess(bidRequests[0], 'schain'); + if (utils.deepAccess(bidRequests[0], 'schain')) { + tag.Schain = utils.deepAccess(bidRequests[0], 'schain'); } - if (deepAccess(bidRequests[0], 'userId')) { - tag.UserIds = deepAccess(bidRequests[0], 'userId'); + if (utils.deepAccess(bidRequests[0], 'userId')) { + tag.UserIds = utils.deepAccess(bidRequests[0], 'userId'); } - if (deepAccess(bidRequests[0], 'userIdAsEids')) { - tag.UserEids = deepAccess(bidRequests[0], 'userIdAsEids'); + if (utils.deepAccess(bidRequests[0], 'userIdAsEids')) { + tag.UserEids = utils.deepAccess(bidRequests[0], 'userIdAsEids'); } // end publisher env const bids = [] @@ -164,13 +164,13 @@ function bidToTag(bidRequests, adapterRequest) { * @returns {object} */ function prepareBidRequests(bidReq) { - const mediaType = deepAccess(bidReq, 'mediaTypes.video') ? VIDEO : DISPLAY; - const sizes = mediaType === VIDEO ? deepAccess(bidReq, 'mediaTypes.video.playerSize') : deepAccess(bidReq, 'mediaTypes.banner.sizes'); + const mediaType = utils.deepAccess(bidReq, 'mediaTypes.video') ? VIDEO : DISPLAY; + const sizes = mediaType === VIDEO ? utils.deepAccess(bidReq, 'mediaTypes.video.playerSize') : utils.deepAccess(bidReq, 'mediaTypes.banner.sizes'); const bidReqParams = { 'CallbackId': bidReq.bidId, 'Aid': bidReq.params.aid, 'AdType': mediaType, - 'Sizes': parseSizesInput(sizes).join(',') + 'Sizes': utils.parseSizesInput(sizes).join(',') }; bidReqParams.PlacementId = bidReq.adUnitCode; @@ -178,9 +178,9 @@ function prepareBidRequests(bidReq) { bidReqParams.AdmType = 'iframe'; } if (mediaType === VIDEO) { - const context = deepAccess(bidReq, 'mediaTypes.video.context'); + const context = utils.deepAccess(bidReq, 'mediaTypes.video.context'); if (context === ADPOD) { - bidReqParams.Adpod = deepAccess(bidReq, 'mediaTypes.video'); + bidReqParams.Adpod = utils.deepAccess(bidReq, 'mediaTypes.video'); } } return bidReqParams; @@ -192,7 +192,7 @@ function prepareBidRequests(bidReq) { * @returns {object} */ function getMediaType(bidderRequest) { - return deepAccess(bidderRequest, 'mediaTypes.video') ? VIDEO : BANNER; + return utils.deepAccess(bidderRequest, 'mediaTypes.video') ? VIDEO : BANNER; } /** @@ -203,7 +203,7 @@ function getMediaType(bidderRequest) { */ function createBid(bidResponse, bidRequest) { const mediaType = getMediaType(bidRequest) - const context = deepAccess(bidRequest, 'mediaTypes.video.context'); + const context = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); const bid = { requestId: bidResponse.requestId, creativeId: bidResponse.cmpId, diff --git a/modules/openxAnalyticsAdapter.js b/modules/openxAnalyticsAdapter.js index 89140c0aacd..0c01d4b461e 100644 --- a/modules/openxAnalyticsAdapter.js +++ b/modules/openxAnalyticsAdapter.js @@ -1,23 +1,10 @@ -import { - _each, - _map, - deepAccess, - flatten, - getWindowLocation, - isEmpty, - logError, - logInfo, - logMessage, - logWarn, - parseQS, - parseSizesInput, - uniques -} from '../src/utils.js'; import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; -import {ajax} from '../src/ajax.js'; -import {find, includes} from '../src/polyfill.js'; +import { ajax } from '../src/ajax.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; +const utils = require('../src/utils.js'); export const AUCTION_STATES = { INIT: 'initialized', // auction has initialized @@ -105,7 +92,7 @@ openxAdapter.enableAnalytics = function(adapterConfig = {options: {}}) { // campaign properties defined by config will override utm query parameters analyticsConfig.campaign = {...buildCampaignFromUtmCodes(), ...analyticsConfig.campaign}; - logInfo('OpenX Analytics enabled with config', analyticsConfig); + utils.logInfo('OpenX Analytics enabled with config', analyticsConfig); // override track method with v2 handlers openxAdapter.track = prebidAnalyticsEventHandler; @@ -116,7 +103,7 @@ openxAdapter.enableAnalytics = function(adapterConfig = {options: {}}) { if (pubads.addEventListener) { pubads.addEventListener(SLOT_LOADED, args => { openxAdapter.track({eventType: SLOT_LOADED, args}); - logInfo('OX: SlotOnLoad event triggered'); + utils.logInfo('OX: SlotOnLoad event triggered'); }); } }); @@ -173,9 +160,9 @@ function isValidConfig({options: analyticsOptions}) { let [property, type, required] = failedValidation; if (required) { - logError(`OpenXAnalyticsAdapter: Expected '${property}' to exist and of type '${type}'`); + utils.logError(`OpenXAnalyticsAdapter: Expected '${property}' to exist and of type '${type}'`); } else { - logError(`OpenXAnalyticsAdapter: Expected '${property}' to be type '${type}'`); + utils.logError(`OpenXAnalyticsAdapter: Expected '${property}' to be type '${type}'`); } } @@ -183,8 +170,8 @@ function isValidConfig({options: analyticsOptions}) { } function buildCampaignFromUtmCodes() { - const location = getWindowLocation(); - const queryParams = parseQS(location && location.search); + const location = utils.getWindowLocation(); + const queryParams = utils.parseQS(location && location.search); let campaign = {}; UTM_TAGS.forEach(function(utmKey) { @@ -244,7 +231,7 @@ function detectBrowser() { } function prebidAnalyticsEventHandler({eventType, args}) { - logMessage(eventType, Object.assign({}, args)); + utils.logMessage(eventType, Object.assign({}, args)); switch (eventType) { case AUCTION_INIT: onAuctionInit(args); @@ -414,8 +401,8 @@ function onBidResponse(bidResponse) { } function onBidTimeout(args) { - _each(args, ({auctionId, adUnitCode, bidId: requestId}) => { - let timedOutRequest = deepAccess(auctionMap, + utils._each(args, ({auctionId, adUnitCode, bidId: requestId}) => { + let timedOutRequest = utils.deepAccess(auctionMap, `${auctionId}.adUnitCodeToAdUnitMap.${adUnitCode}.bidRequestsMap.${requestId}`); if (timedOutRequest) { @@ -446,7 +433,7 @@ function onAuctionEnd(endedAuction) { */ function onBidWon(bidResponse) { const { auctionId, adUnitCode, requestId, adId } = bidResponse; - let winningBid = deepAccess(auctionMap, + let winningBid = utils.deepAccess(auctionMap, `${auctionId}.adUnitCodeToAdUnitMap.${adUnitCode}.bidRequestsMap.${requestId}.bids.${adId}`); if (winningBid) { @@ -457,10 +444,10 @@ function onBidWon(bidResponse) { const bidder = auction.adUnitCodeToAdUnitMap[adUnitCode].bidRequestsMap[requestId].bidder; ajax(`${endpoint}?t=win&b=${adId}&a=${analyticsConfig.orgId}&bidder=${bidder}&ts=${auction.startTime}`, () => { - logInfo(`Openx Analytics - Sending complete impression event for ${adId} at ${Date.now()}`) + utils.logInfo(`Openx Analytics - Sending complete impression event for ${adId} at ${Date.now()}`) }); } else { - logInfo(`Openx Analytics - impression event for ${adId} will be sent with auction data`) + utils.logInfo(`Openx Analytics - impression event for ${adId} will be sent with auction data`) } } } @@ -535,7 +522,7 @@ function isAtf(elementId, scrollLeft = 0, scrollTop = 0) { } } } else { - logWarn('OX: DOM element not for id ' + elementId); + utils.logWarn('OX: DOM element not for id ' + elementId); } return isAtf; } @@ -565,7 +552,7 @@ function delayedSend(auction) { let payload = JSON.stringify([buildAuctionPayload(auction)]); ajax(analyticsConfig.endpoint || ENDPOINT, () => { - logInfo(`OpenX Analytics - Sending complete auction at ${Date.now()}`); + utils.logInfo(`OpenX Analytics - Sending complete auction at ${Date.now()}`); }, payload, { contentType: 'application/json' }); }, delayTime); } @@ -592,15 +579,15 @@ function getPathToBidResponseByBidId(bidId) { return []; } - _each(auctionMap, currentAuction => { + utils._each(auctionMap, currentAuction => { // skip completed auctions if (currentAuction.state === AUCTION_STATES.COMPLETED) { return; } - _each(currentAuction.adUnitCodeToAdUnitMap, (currentAdunit) => { - _each(currentAdunit.bidRequestsMap, currentBiddRequest => { - _each(currentBiddRequest.bids, (currentBidResponse, bidResponseId) => { + utils._each(currentAuction.adUnitCodeToAdUnitMap, (currentAdunit) => { + utils._each(currentAdunit.bidRequestsMap, currentBiddRequest => { + utils._each(currentBiddRequest.bids, (currentBidResponse, bidResponseId) => { if (bidId === bidResponseId) { auction = currentAuction; adUnit = currentAdunit; @@ -617,12 +604,12 @@ function getAuctionByGoogleTagSLot(slot) { let slotAdunitCodes = [slot.getSlotElementId(), slot.getAdUnitPath()]; let slotAuction; - _each(auctionMap, auction => { + utils._each(auctionMap, auction => { if (auction.state === AUCTION_STATES.COMPLETED) { return; } - _each(auction.adUnitCodeToAdUnitMap, (bidderRequestIdMap, adUnitCode) => { + utils._each(auction.adUnitCodeToAdUnitMap, (bidderRequestIdMap, adUnitCode) => { if (includes(slotAdunitCodes, adUnitCode)) { slotAuction = auction; } @@ -662,7 +649,7 @@ function buildAuctionPayload(auction) { }; function buildAdUnitsPayload(adUnitCodeToAdUnitMap) { - return _map(adUnitCodeToAdUnitMap, (adUnit) => { + return utils._map(adUnitCodeToAdUnitMap, (adUnit) => { let {code, adPosition} = adUnit; return { @@ -672,7 +659,7 @@ function buildAuctionPayload(auction) { }; function buildBidRequestPayload(bidRequestsMap) { - return _map(bidRequestsMap, (bidRequest) => { + return utils._map(bidRequestsMap, (bidRequest) => { let {bidder, source, bids, mediaTypes, timeLimit, timedOut} = bidRequest; return { bidder, @@ -682,7 +669,7 @@ function buildAuctionPayload(auction) { availableMediaTypes: getMediaTypes(mediaTypes), timeLimit, timedOut, - bidResponses: _map(bidRequest.bids, (bidderBidResponse) => { + bidResponses: utils._map(bidRequest.bids, (bidderBidResponse) => { let { adId, cpm, @@ -729,11 +716,11 @@ function buildAuctionPayload(auction) { } function buildUserIdProviders(userIds) { - return _map(userIds, (userId) => { - return _map(userId, (id, module) => { + return utils._map(userIds, (userId) => { + return utils._map(userId, (id, module) => { return hasUserData(module, id) ? module : false }).filter(module => module); - }).reduce(flatten, []).filter(uniques).sort(); + }).reduce(utils.flatten, []).filter(utils.uniques).sort(); } function hasUserData(module, idOrIdObject) { @@ -741,7 +728,7 @@ function buildAuctionPayload(auction) { switch (module) { case 'digitrustid': - normalizedId = deepAccess(idOrIdObject, 'data.id'); + normalizedId = utils.deepAccess(idOrIdObject, 'data.id'); break; case 'lipb': normalizedId = idOrIdObject.lipbid; @@ -750,17 +737,17 @@ function buildAuctionPayload(auction) { normalizedId = idOrIdObject; } - return !isEmpty(normalizedId); + return !utils.isEmpty(normalizedId); } function getMediaTypeSizes(mediaTypes) { - return _map(mediaTypes, (mediaTypeConfig, mediaType) => { - return parseSizesInput(mediaTypeConfig.sizes) + return utils._map(mediaTypes, (mediaTypeConfig, mediaType) => { + return utils.parseSizesInput(mediaTypeConfig.sizes) .map(size => `${mediaType}_${size}`); - }).reduce(flatten, []); + }).reduce(utils.flatten, []); } function getMediaTypes(mediaTypes) { - return _map(mediaTypes, (mediaTypeConfig, mediaType) => mediaType); + return utils._map(mediaTypes, (mediaTypeConfig, mediaType) => mediaType); } } diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 85dcfbb3b47..c3f3a7ddf42 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -1,18 +1,8 @@ -import { - _each, - _map, - convertTypes, - deepAccess, - deepSetValue, - inIframe, - isArray, - parseSizesInput, - parseUrl -} from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {includes} from '../src/polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js' const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const VIDEO_TARGETING = ['startdelay', 'mimes', 'minduration', 'maxduration', @@ -52,12 +42,7 @@ export const USER_ID_CODE_TO_QUERY_ARG = { novatiq: 'novatiqid', // Novatiq ID mwOpenLinkId: 'mwopenlinkid', // MediaWallah OpenLink ID dapId: 'dapid', // Akamai DAP ID - amxId: 'amxid', // AMX RTB ID - kpuid: 'kpuid', // Kinesso ID - publinkId: 'publinkid', // Publisher Link - naveggId: 'naveggid', // Navegg ID - imuid: 'imuid', // IM-UID by Intimate Merger - adtelligentId: 'adtelligentid' // Adtelligent ID + amxId: 'amxid' // AMX RTB ID }; export const spec = { @@ -66,8 +51,8 @@ export const spec = { supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { const hasDelDomainOrPlatform = bidRequest.params.delDomain || bidRequest.params.platform; - if (deepAccess(bidRequest, 'mediaTypes.banner') && hasDelDomainOrPlatform) { - return !!bidRequest.params.unit || deepAccess(bidRequest, 'mediaTypes.banner.sizes.length') > 0; + if (utils.deepAccess(bidRequest, 'mediaTypes.banner') && hasDelDomainOrPlatform) { + return !!bidRequest.params.unit || utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes.length') > 0; } return !!(bidRequest.params.unit && hasDelDomainOrPlatform); @@ -102,8 +87,8 @@ export const spec = { getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent) { if (syncOptions.iframeEnabled || syncOptions.pixelEnabled) { let pixelType = syncOptions.iframeEnabled ? 'iframe' : 'image'; - let url = deepAccess(responses, '0.body.ads.pixels') || - deepAccess(responses, '0.body.pixels') || + let url = utils.deepAccess(responses, '0.body.ads.pixels') || + utils.deepAccess(responses, '0.body.pixels') || generateDefaultSyncUrl(gdprConsent, uspConsent); return [{ @@ -113,7 +98,7 @@ export const spec = { } }, transformBidParams: function(params, isOpenRtb) { - return convertTypes({ + return utils.convertTypes({ 'unit': 'string', 'customFloor': 'number' }, params); @@ -138,7 +123,7 @@ function generateDefaultSyncUrl(gdprConsent, uspConsent) { } function isVideoRequest(bidRequest) { - return (deepAccess(bidRequest, 'mediaTypes.video') && !deepAccess(bidRequest, 'mediaTypes.banner')) || bidRequest.mediaType === VIDEO; + return (utils.deepAccess(bidRequest, 'mediaTypes.video') && !utils.deepAccess(bidRequest, 'mediaTypes.banner')) || bidRequest.mediaType === VIDEO; } function createBannerBidResponses(oxResponseObj, {bids, startTime}) { @@ -230,7 +215,7 @@ function getViewportDimensions(isIfr) { function formatCustomParms(customKey, customParams) { let value = customParams[customKey]; - if (isArray(value)) { + if (utils.isArray(value)) { // if value is an array, join them with commas first value = value.join(','); } @@ -255,7 +240,7 @@ function getMediaTypeFromRequest(serverRequest) { } function buildCommonQueryParamsFromBids(bids, bidderRequest) { - const isInIframe = inIframe(); + const isInIframe = utils.inIframe(); let defaultParams; defaultParams = { @@ -267,18 +252,31 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { tws: getViewportDimensions(isInIframe), be: 1, bc: bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, - dddid: _map(bids, bid => bid.transactionId).join(','), + dddid: utils._map(bids, bid => bid.transactionId).join(','), nocache: new Date().getTime() }; - const userDataSegments = buildFpdQueryParams('ortb2.user.data'); - if (userDataSegments.length > 0) { - defaultParams.sm = userDataSegments; - } - - const siteContentDataSegments = buildFpdQueryParams('ortb2.site.content.data'); - if (siteContentDataSegments.length > 0) { - defaultParams.scsm = siteContentDataSegments; + const firstPartyData = config.getConfig('ortb2.user.data') + if (Array.isArray(firstPartyData) && firstPartyData.length > 0) { + // extract and merge valid segments by provider/taxonomy + const fpd = firstPartyData + .filter( + data => (Array.isArray(data.segment) && + data.segment.length > 0 && + data.name !== undefined && + data.name.length > 0) + ) + .reduce((acc, data) => { + const name = typeof data.ext === 'object' && data.ext.segtax ? `${data.name}/${data.ext.segtax}` : data.name; + acc[name] = (acc[name] || []).concat(data.segment.map(seg => seg.id)); + return acc; + }, {}) + const sm = Object.keys(fpd) + .map((name, _) => name + ':' + fpd[name].join('|')) + .join(',') + if (sm.length > 0) { + defaultParams.sm = encodeURIComponent(sm); + } } if (bids[0].params.platform) { @@ -306,8 +304,8 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { } // normalize publisher common id - if (deepAccess(bids[0], 'crumbs.pubcid')) { - deepSetValue(bids[0], 'userId.pubcid', deepAccess(bids[0], 'crumbs.pubcid')); + if (utils.deepAccess(bids[0], 'crumbs.pubcid')) { + utils.deepSetValue(bids[0], 'userId.pubcid', utils.deepAccess(bids[0], 'crumbs.pubcid')); } defaultParams = appendUserIdsToQueryParams(defaultParams, bids[0].userId); @@ -319,37 +317,12 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { return defaultParams; } -function buildFpdQueryParams(fpdPath) { - const firstPartyData = config.getConfig(fpdPath); - if (!Array.isArray(firstPartyData) || !firstPartyData.length) { - return ''; - } - const fpd = firstPartyData - .filter( - data => (Array.isArray(data.segment) && - data.segment.length > 0 && - data.name !== undefined && - data.name.length > 0) - ) - .reduce((acc, data) => { - const name = typeof data.ext === 'object' && data.ext.segtax ? `${data.name}/${data.ext.segtax}` : data.name; - acc[name] = (acc[name] || []).concat(data.segment.map(seg => seg.id)); - return acc; - }, {}) - return Object.keys(fpd) - .map((name, _) => name + ':' + fpd[name].join('|')) - .join(',') -} - function appendUserIdsToQueryParams(queryParams, userIds) { - _each(userIds, (userIdObjectOrValue, userIdProviderKey) => { + utils._each(userIds, (userIdObjectOrValue, userIdProviderKey) => { const key = USER_ID_CODE_TO_QUERY_ARG[userIdProviderKey]; if (USER_ID_CODE_TO_QUERY_ARG.hasOwnProperty(userIdProviderKey)) { switch (userIdProviderKey) { - case 'merkleId': - queryParams[key] = userIdObjectOrValue.id; - break; case 'flocId': queryParams[key] = userIdObjectOrValue.id; break; @@ -360,7 +333,7 @@ function appendUserIdsToQueryParams(queryParams, userIds) { queryParams[key] = userIdObjectOrValue.lipbid; if (Array.isArray(userIdObjectOrValue.segments) && userIdObjectOrValue.segments.length > 0) { const liveIntentSegments = 'liveintent:' + userIdObjectOrValue.segments.join('|') - queryParams.sm = `${queryParams.sm ? queryParams.sm + ',' : ''}${liveIntentSegments}`; + queryParams.sm = `${queryParams.sm ? queryParams.sm + encodeURIComponent(',') : ''}${encodeURIComponent(liveIntentSegments)}`; } break; case 'parrableId': @@ -398,13 +371,13 @@ function buildOXBannerRequest(bids, bidderRequest) { let customParamsForAllBids = []; let hasCustomParam = false; let queryParams = buildCommonQueryParamsFromBids(bids, bidderRequest); - let auids = _map(bids, bid => bid.params.unit); + let auids = utils._map(bids, bid => bid.params.unit); - queryParams.aus = _map(bids, bid => parseSizesInput(bid.mediaTypes.banner.sizes).join(',')).join('|'); - queryParams.divids = _map(bids, bid => encodeURIComponent(bid.adUnitCode)).join(','); + queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.mediaTypes.banner.sizes).join(',')).join('|'); + queryParams.divids = utils._map(bids, bid => encodeURIComponent(bid.adUnitCode)).join(','); // gpid - queryParams.aucs = _map(bids, function (bid) { - let gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); + queryParams.aucs = utils._map(bids, function (bid) { + let gpid = utils.deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); return encodeURIComponent(gpid || '') }).join(','); @@ -422,7 +395,7 @@ function buildOXBannerRequest(bids, bidderRequest) { bids.forEach(function (bid) { if (bid.params.customParams) { - let customParamsForBid = _map(Object.keys(bid.params.customParams), customKey => formatCustomParms(customKey, bid.params.customParams)); + let customParamsForBid = utils._map(Object.keys(bid.params.customParams), customKey => formatCustomParms(customKey, bid.params.customParams)); let formattedCustomParams = window.btoa(customParamsForBid.join('&')); hasCustomParam = true; customParamsForAllBids.push(formattedCustomParams); @@ -462,22 +435,22 @@ function buildOXVideoRequest(bid, bidderRequest) { } function generateVideoParameters(bid, bidderRequest) { - const videoMediaType = deepAccess(bid, `mediaTypes.video`); + const videoMediaType = utils.deepAccess(bid, `mediaTypes.video`); let queryParams = buildCommonQueryParamsFromBids([bid], bidderRequest); - let oxVideoConfig = deepAccess(bid, 'params.video') || {}; - let context = deepAccess(bid, 'mediaTypes.video.context'); - let playerSize = deepAccess(bid, 'mediaTypes.video.playerSize'); + let oxVideoConfig = utils.deepAccess(bid, 'params.video') || {}; + let context = utils.deepAccess(bid, 'mediaTypes.video.context'); + let playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); let width; let height; // normalize config for video size - if (isArray(bid.sizes) && bid.sizes.length === 2 && !isArray(bid.sizes[0])) { + if (utils.isArray(bid.sizes) && bid.sizes.length === 2 && !utils.isArray(bid.sizes[0])) { width = parseInt(bid.sizes[0], 10); height = parseInt(bid.sizes[1], 10); - } else if (isArray(bid.sizes) && isArray(bid.sizes[0]) && bid.sizes[0].length === 2) { + } else if (utils.isArray(bid.sizes) && utils.isArray(bid.sizes[0]) && bid.sizes[0].length === 2) { width = parseInt(bid.sizes[0][0], 10); height = parseInt(bid.sizes[0][1], 10); - } else if (isArray(playerSize) && playerSize.length === 2) { + } else if (utils.isArray(playerSize) && playerSize.length === 2) { width = parseInt(playerSize[0], 10); height = parseInt(playerSize[1], 10); } @@ -490,7 +463,7 @@ function generateVideoParameters(bid, bidderRequest) { legacyParams = legacyParams.openrtb; } // support for video object or full openrtb object - if (isArray(legacyParams.imp)) { + if (utils.isArray(legacyParams.imp)) { legacyParams = legacyParams.imp[0].video; } Object.keys(legacyParams) @@ -529,7 +502,7 @@ function generateVideoParameters(bid, bidderRequest) { queryParams.vtest = 1; } - let gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); + let gpid = utils.deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); if (gpid) { queryParams.aucs = encodeURIComponent(gpid) } @@ -544,7 +517,7 @@ function createVideoBidResponses(response, {bid, startTime}) { let bidResponses = []; if (response !== undefined && response.vastUrl !== '' && response.pub_rev > 0) { - let vastQueryParams = parseUrl(response.vastUrl).search || {}; + let vastQueryParams = utils.parseUrl(response.vastUrl).search || {}; let bidResponse = {}; bidResponse.requestId = bid.bidId; if (response.deal_id) { diff --git a/modules/operaadsBidAdapter.js b/modules/operaadsBidAdapter.js index 61ea8cdcb76..85ba25c1404 100644 --- a/modules/operaadsBidAdapter.js +++ b/modules/operaadsBidAdapter.js @@ -1,4 +1,4 @@ -import { logWarn, isArray, isStr, triggerPixel, deepAccess, deepSetValue, isPlainObject, generateUUID, parseUrl, isFn, getDNT, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js'; @@ -8,7 +8,6 @@ import { OUTSTREAM } from '../src/video.js'; const BIDDER_CODE = 'operaads'; const ENDPOINT = 'https://s.adx.opera.com/ortb/v2/'; -const USER_SYNC_ENDPOINT = 'https://s.adx.opera.com/usersync/page'; const OUTSTREAM_RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; @@ -71,27 +70,27 @@ export const spec = { */ isBidRequestValid: function (bid) { if (!bid) { - logWarn(BIDDER_CODE, 'Invalid bid,', bid); + utils.logWarn(BIDDER_CODE, 'Invalid bid,', bid); return false; } if (!bid.params) { - logWarn(BIDDER_CODE, 'bid.params is required.') + utils.logWarn(BIDDER_CODE, 'bid.params is required.') return false; } if (!bid.params.placementId) { - logWarn(BIDDER_CODE, 'bid.params.placementId is required.') + utils.logWarn(BIDDER_CODE, 'bid.params.placementId is required.') return false; } if (!bid.params.endpointId) { - logWarn(BIDDER_CODE, 'bid.params.endpointId is required.') + utils.logWarn(BIDDER_CODE, 'bid.params.endpointId is required.') return false; } if (!bid.params.publisherId) { - logWarn(BIDDER_CODE, 'bid.params.publisherId is required.') + utils.logWarn(BIDDER_CODE, 'bid.params.publisherId is required.') return false; } @@ -119,9 +118,9 @@ export const spec = { let bidResponses = []; let serverBody; - if ((serverBody = serverResponse.body) && serverBody.seatbid && isArray(serverBody.seatbid)) { + if ((serverBody = serverResponse.body) && serverBody.seatbid && utils.isArray(serverBody.seatbid)) { serverBody.seatbid.forEach((seatbidder) => { - if (seatbidder.bid && isArray(seatbidder.bid)) { + if (seatbidder.bid && utils.isArray(seatbidder.bid)) { bidResponses = seatbidder.bid.map((bid) => buildBidResponse(bid, bidRequest.originalBidRequest, serverBody)); } }); @@ -138,25 +137,6 @@ export const spec = { * @return {UserSync[]} The user syncs which should be dropped. */ getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) { - if ('iframeEnabled' in syncOptions && syncOptions.iframeEnabled) { - return [{ - type: 'iframe', - url: USER_SYNC_ENDPOINT - }]; - } - if ('pixelEnabled' in syncOptions && syncOptions.pixelEnabled) { - const pixels = deepAccess(serverResponses, '0.body.pixels') - if (Array.isArray(pixels)) { - const userSyncPixels = [] - for (const pixel of pixels) { - userSyncPixels.push({ - type: 'image', - url: pixel - }) - } - return userSyncPixels; - } - } return []; }, @@ -173,7 +153,7 @@ export const spec = { * @param {Bid} bid The bid that won the auction */ onBidWon: function (bid) { - if (!bid || !isStr(bid.nurl)) { + if (!bid || !utils.isStr(bid.nurl)) { return; } @@ -186,7 +166,7 @@ export const spec = { winCurr = bid.currency; } - triggerPixel( + utils.triggerPixel( bid.nurl .replace(/\$\{AUCTION_PRICE\}/g, winCpm) .replace(/\$\{AUCTION_CURRENCY\}/g, winCurr) @@ -209,53 +189,55 @@ export const spec = { * @returns {Request} */ function buildOpenRtbBidRequest(bidRequest, bidderRequest) { - const pageReferrer = deepAccess(bidderRequest, 'refererInfo.referer'); + const currencies = getCurrencies(bidRequest); + + const pageReferrer = utils.deepAccess(bidderRequest, 'refererInfo.referer'); // build OpenRTB request body const payload = { id: bidderRequest.auctionId, tmax: bidderRequest.timeout || config.getConfig('bidderTimeout'), test: config.getConfig('debug') ? 1 : 0, - imp: createImp(bidRequest), + imp: createImp(bidRequest, currencies[0]), device: getDevice(), site: { - id: String(deepAccess(bidRequest, 'params.publisherId')), + id: String(utils.deepAccess(bidRequest, 'params.publisherId')), domain: getDomain(pageReferrer), page: pageReferrer, ref: window.self === window.top ? document.referrer : '', }, at: 1, bcat: getBcat(bidRequest), - cur: [DEFAULT_CURRENCY], + cur: currencies, regs: { coppa: config.getConfig('coppa') ? 1 : 0, ext: {} }, user: { - buyeruid: getUserId(bidRequest) + id: getUserId(bidRequest) } } - const gdprConsent = deepAccess(bidderRequest, 'gdprConsent'); + const gdprConsent = utils.deepAccess(bidderRequest, 'gdprConsent'); if (!!gdprConsent && gdprConsent.gdprApplies) { - deepSetValue(payload, 'regs.ext.gdpr', 1); - deepSetValue(payload, 'user.ext.consent', gdprConsent.consentString); + utils.deepSetValue(payload, 'regs.ext.gdpr', 1); + utils.deepSetValue(payload, 'user.ext.consent', gdprConsent.consentString); } - const uspConsent = deepAccess(bidderRequest, 'uspConsent'); + const uspConsent = utils.deepAccess(bidderRequest, 'uspConsent'); if (uspConsent) { - deepSetValue(payload, 'regs.ext.us_privacy', uspConsent); + utils.deepSetValue(payload, 'regs.ext.us_privacy', uspConsent); } - const eids = deepAccess(bidRequest, 'userIdAsEids', []); + const eids = utils.deepAccess(bidRequest, 'userIdAsEids', []); if (eids.length > 0) { - deepSetValue(payload, 'user.eids', eids); + utils.deepSetValue(payload, 'user.eids', eids); } return { method: 'POST', - url: ENDPOINT + String(deepAccess(bidRequest, 'params.publisherId')) + - '?ep=' + String(deepAccess(bidRequest, 'params.endpointId')), + url: ENDPOINT + String(utils.deepAccess(bidRequest, 'params.publisherId')) + + '?ep=' + String(utils.deepAccess(bidRequest, 'params.endpointId')), data: JSON.stringify(payload), options: { contentType: 'application/json', @@ -292,7 +274,7 @@ function buildBidResponse(bid, bidRequest, responseBody) { // OpenRtb Markup Response Object // https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-Native-Ads-Specification-1-1_2016.pdf#5.1 - if (markup && isPlainObject(markup.native)) { + if (markup && utils.isPlainObject(markup.native)) { mediaType = NATIVE; nativeResponse = markup.native; } @@ -301,7 +283,7 @@ function buildBidResponse(bid, bidRequest, responseBody) { const currency = responseBody.cur || DEFAULT_CURRENCY; const cpm = (parseFloat(bid.price) || 0).toFixed(2); - const categories = deepAccess(bid, 'cat', []); + const categories = utils.deepAccess(bid, 'cat', []); const bidResponse = { requestId: bid.impid, @@ -320,14 +302,14 @@ function buildBidResponse(bid, bidRequest, responseBody) { } }; - if (bid.adomain && isArray(bid.adomain) && bid.adomain.length > 0) { + if (bid.adomain && utils.isArray(bid.adomain) && bid.adomain.length > 0) { bidResponse.meta.advertiserDomains = bid.adomain; bidResponse.meta.clickUrl = bid.adomain[0]; } switch (mediaType) { case VIDEO: { - const playerSize = deepAccess(bidRequest, 'mediaTypes.video.playerSize', VIDEO_DEFAULTS.SIZE); + const playerSize = utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize', VIDEO_DEFAULTS.SIZE); const size = canonicalizeSizesArray(playerSize)[0]; bidResponse.vastXml = bid.adm; @@ -335,7 +317,7 @@ function buildBidResponse(bid, bidRequest, responseBody) { bidResponse.width = bid.w || size[0]; bidResponse.height = bid.h || size[1]; - const context = deepAccess(bidRequest, 'mediaTypes.video.context'); + const context = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); // if outstream video, add a default render for it. if (context === OUTSTREAM) { @@ -378,13 +360,13 @@ function interpretNativeAd(nativeResponse, currency, cpm) { // OpenRtb Link Object // https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-Native-Ads-Specification-1-1_2016.pdf#5.7 - const clickUrl = deepAccess(nativeResponse, 'link.url'); - if (clickUrl && isStr(clickUrl)) { + const clickUrl = utils.deepAccess(nativeResponse, 'link.url'); + if (clickUrl && utils.isStr(clickUrl)) { native.clickUrl = decodeURIComponent(clickUrl); } - const clickTrackers = deepAccess(nativeResponse, 'link.clicktrackers'); - if (clickTrackers && isArray(clickTrackers)) { + const clickTrackers = utils.deepAccess(nativeResponse, 'link.clicktrackers'); + if (clickTrackers && utils.isArray(clickTrackers)) { native.clickTrackers = clickTrackers .filter(Boolean) .map( @@ -394,7 +376,7 @@ function interpretNativeAd(nativeResponse, currency, cpm) { ); } - if (nativeResponse.imptrackers && isArray(nativeResponse.imptrackers)) { + if (nativeResponse.imptrackers && utils.isArray(nativeResponse.imptrackers)) { native.impressionTrackers = nativeResponse.imptrackers .filter(Boolean) .map( @@ -404,16 +386,16 @@ function interpretNativeAd(nativeResponse, currency, cpm) { ); } - if (nativeResponse.jstracker && isStr(nativeResponse.jstracker)) { + if (nativeResponse.jstracker && utils.isStr(nativeResponse.jstracker)) { native.javascriptTrackers = [nativeResponse.jstracker]; } let assets; - if ((assets = nativeResponse.assets) && isArray(assets)) { + if ((assets = nativeResponse.assets) && utils.isArray(assets)) { assets.forEach((asset) => { switch (asset.id) { case NATIVE_DEFAULTS.ASSET_ID.TITLE: { - const title = deepAccess(asset, 'title.text'); + const title = utils.deepAccess(asset, 'title.text'); if (title) { native.title = title; } @@ -440,21 +422,21 @@ function interpretNativeAd(nativeResponse, currency, cpm) { break; } case NATIVE_DEFAULTS.ASSET_ID.BODY: { - const body = deepAccess(asset, 'data.value'); + const body = utils.deepAccess(asset, 'data.value'); if (body) { native.body = body; } break; } case NATIVE_DEFAULTS.ASSET_ID.SPONSORED: { - const sponsoredBy = deepAccess(asset, 'data.value'); + const sponsoredBy = utils.deepAccess(asset, 'data.value'); if (sponsoredBy) { native.sponsoredBy = sponsoredBy; } break; } case NATIVE_DEFAULTS.ASSET_ID.CTA: { - const cta = deepAccess(asset, 'data.value'); + const cta = utils.deepAccess(asset, 'data.value'); if (cta) { native.cta = cta; } @@ -474,19 +456,22 @@ function interpretNativeAd(nativeResponse, currency, cpm) { * @param {Currency} cur * @returns {Imp[]} */ -function createImp(bidRequest) { +function createImp(bidRequest, cur) { const imp = []; + const floor = getBidFloor(bidRequest, cur); + const impItem = { id: bidRequest.bidId, - tagid: String(deepAccess(bidRequest, 'params.placementId')), + tagid: String(utils.deepAccess(bidRequest, 'params.placementId')), + bidfloor: floor, }; - let mediaType, size; + let mediaType; let bannerReq, videoReq, nativeReq; - if ((bannerReq = deepAccess(bidRequest, 'mediaTypes.banner'))) { - size = canonicalizeSizesArray(bannerReq.sizes || BANNER_DEFAULTS.SIZE)[0]; + if ((bannerReq = utils.deepAccess(bidRequest, 'mediaTypes.banner'))) { + const size = canonicalizeSizesArray(bannerReq.sizes || BANNER_DEFAULTS.SIZE)[0]; impItem.banner = { w: size[0], @@ -495,8 +480,8 @@ function createImp(bidRequest) { }; mediaType = BANNER; - } else if ((videoReq = deepAccess(bidRequest, 'mediaTypes.video'))) { - size = canonicalizeSizesArray(videoReq.playerSize || VIDEO_DEFAULTS.SIZE)[0]; + } else if ((videoReq = utils.deepAccess(bidRequest, 'mediaTypes.video'))) { + const size = canonicalizeSizesArray(videoReq.playerSize || VIDEO_DEFAULTS.SIZE)[0]; impItem.video = { w: size[0], @@ -513,7 +498,7 @@ function createImp(bidRequest) { }; mediaType = VIDEO; - } else if ((nativeReq = deepAccess(bidRequest, 'mediaTypes.native'))) { + } else if ((nativeReq = utils.deepAccess(bidRequest, 'mediaTypes.native'))) { const params = bidRequest.nativeParams || nativeReq; const request = { @@ -531,14 +516,6 @@ function createImp(bidRequest) { mediaType = NATIVE; } - const floorDetail = getBidFloor(bidRequest, { - mediaType: mediaType || '*', - size: size || '*' - }) - - impItem.bidfloor = floorDetail.floor; - impItem.bidfloorcur = floorDetail.currency; - if (mediaType) { imp.push(impItem); } @@ -553,7 +530,7 @@ function createImp(bidRequest) { * @returns {Size[][]} */ function canonicalizeSizesArray(sizes) { - if (sizes.length === 2 && !isArray(sizes[0])) { + if (sizes.length === 2 && !utils.isArray(sizes[0])) { return [sizes]; } return sizes; @@ -665,19 +642,19 @@ function mapNativeImage(image, type) { * @returns {String} userId */ function getUserId(bidRequest) { - let sharedId = deepAccess(bidRequest, 'userId.sharedid.id'); + let sharedId = utils.deepAccess(bidRequest, 'userId.sharedid.id'); if (sharedId) { return sharedId; } for (const idModule of ['pubcid', 'tdid']) { - let userId = deepAccess(bidRequest, `userId.${idModule}`); + let userId = utils.deepAccess(bidRequest, `userId.${idModule}`); if (userId) { return userId; } } - return generateUUID(); + return utils.generateUUID(); } /** @@ -690,7 +667,7 @@ function getDomain(referer) { let domain; if (!(domain = config.getConfig('publisherDomain'))) { - const u = parseUrl(referer); + const u = utils.parseUrl(referer); domain = u.hostname; } @@ -701,29 +678,47 @@ function getDomain(referer) { * Get bid floor price * * @param {BidRequest} bid - * @param {Params} params - * @returns {Floor} floor price + * @param {String} cur + * @returns {Number} floor price */ -function getBidFloor(bid, {mediaType = '*', size = '*'}) { - if (isFn(bid.getFloor)) { - const floorInfo = bid.getFloor({ - currency: DEFAULT_CURRENCY, - mediaType, - size +function getBidFloor(bid, cur) { + let floorInfo = {}; + + if (typeof bid.getFloor === 'function') { + floorInfo = bid.getFloor({ + currency: cur, + mediaType: '*', + size: '*' }); + } - if (isPlainObject(floorInfo) && !isNaN(floorInfo.floor)) { - return { - currency: floorInfo.currency || DEFAULT_CURRENCY, - floor: floorInfo.floor - }; - } + return floorInfo.floor || 0.0; +} + +/** + * Get currencies from bid request + * + * @param {BidRequest} bidRequest + * @returns {String[]} currencies + */ +function getCurrencies(bidRequest) { + let currencies = []; + + const pCur = utils.deepAccess(bidRequest, 'params.currency'); + if (pCur) { + currencies = currencies.concat(pCur); } - return { - currency: DEFAULT_CURRENCY, - floor: 0.0 + if (!currencies.length) { + let currency; + if ((currency = config.getConfig('currency')) && currency.adServerCurrency) { + currencies.push(currency.adServerCurrency); + } else { + currencies.push(DEFAULT_CURRENCY); + } } + + return currencies; } /** @@ -735,7 +730,7 @@ function getBidFloor(bid, {mediaType = '*', size = '*'}) { function getBcat(bidRequest) { let bcat = []; - const pBcat = deepAccess(bidRequest, 'params.bcat'); + const pBcat = utils.deepAccess(bidRequest, 'params.bcat'); if (pBcat) { bcat = bcat.concat(pBcat); } @@ -756,7 +751,7 @@ function getDevice() { device.ua = device.ua || navigator.userAgent; device.language = device.language || getLanguage(); device.dnt = typeof device.dnt === 'number' - ? device.dnt : (getDNT() ? 1 : 0); + ? device.dnt : (utils.getDNT() ? 1 : 0); return device; } @@ -779,8 +774,8 @@ function getLanguage() { * @returns */ function createRenderer(bidRequest) { - const globalRenderer = deepAccess(bidRequest, 'renderer'); - const currentRenderer = deepAccess(bidRequest, 'mediaTypes.video.renderer'); + const globalRenderer = utils.deepAccess(bidRequest, 'renderer'); + const currentRenderer = utils.deepAccess(bidRequest, 'mediaTypes.video.renderer'); let url = OUTSTREAM_RENDERER_URL; let config = {}; @@ -815,7 +810,7 @@ function createRenderer(bidRequest) { try { renderer.setRender(render); } catch (e) { - logError(BIDDER_CODE, 'Error calling setRender on renderer', e); + utils.logError(BIDDER_CODE, 'Error calling setRender on renderer', e); } return renderer; } diff --git a/modules/operaadsBidAdapter.md b/modules/operaadsBidAdapter.md index 709c67a04a7..9bfe3e76b88 100644 --- a/modules/operaadsBidAdapter.md +++ b/modules/operaadsBidAdapter.md @@ -16,9 +16,10 @@ Module that connects to OperaAds's demand sources | Name | Scope | Type | Description | Example | ---- | ----- | ---- | ----------- | ------- -| `placementId` | required | String | The Placement Id provided by Opera Ads. | `s5340077725248` -| `endpointId` | required | String | The Endpoint Id provided by Opera Ads. | `ep3425464070464` -| `publisherId` | required | String | The Publisher Id provided by Opera Ads. | `pub3054952966336` +| `placementId` | required | String | The Placement Id provided by Opera Ads. | `s12345678` +| `endpointId` | required | String | The Endpoint Id provided by Opera Ads. | `ep12345678` +| `publisherId` | required | String | The Publisher Id provided by Opera Ads. | `pub12345678` +| `currency` | optional | String or String[] | Currency. | `USD` | `bcat` | optional | String or String[] | The bcat value. | `IAB9-31` ### Bid Video Parameters @@ -65,9 +66,9 @@ var adUnits = [{ bids: [{ bidder: 'operaads', params: { - placementId: 's5340077725248', - endpointId: 'ep3425464070464', - publisherId: 'pub3054952966336' + placementId: 's12345678', + endpointId: 's12345678', + publisherId: 's12345678' } }] }]; @@ -91,9 +92,9 @@ var adUnits = [{ bids: [{ bidder: 'operaads', params: { - placementId: 's5340077725248', - endpointId: 'ep3425464070464', - publisherId: 'pub3054952966336' + placementId: 's12345678', + endpointId: 's12345678', + publisherId: 's12345678' } }] }]; @@ -125,9 +126,9 @@ var adUnits = [{ bids: [{ bidder: 'operaads', params: { - placementId: 's5340077725248', - endpointId: 'ep3425464070464', - publisherId: 'pub3054952966336' + placementId: 's12345678', + endpointId: 's12345678', + publisherId: 's12345678' } }] }]; diff --git a/modules/optimeraRtdProvider.js b/modules/optimeraRtdProvider.js index dfe8f1bfcf2..1e439b28c94 100644 --- a/modules/optimeraRtdProvider.js +++ b/modules/optimeraRtdProvider.js @@ -18,7 +18,7 @@ * @property {string} device */ -import { logInfo, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { submodule } from '../src/hook.js'; import { ajaxBuilder } from '../src/ajax.js'; @@ -74,7 +74,7 @@ export let fetchScoreFile = true; * Make the request for the Score File. */ export function scoreFileRequest() { - logInfo('Fetch Optimera score file.'); + utils.logInfo('Fetch Optimera score file.'); const ajax = ajaxBuilder(); ajax(scoresURL, { @@ -83,14 +83,14 @@ export function scoreFileRequest() { try { setScores(res); } catch (err) { - logError('Unable to parse Optimera Score File.', err); + utils.logError('Unable to parse Optimera Score File.', err); } } else if (req.status === 403) { - logError('Unable to fetch the Optimera Score File - 403'); + utils.logError('Unable to fetch the Optimera Score File - 403'); } }, error: () => { - logError('Unable to fetch the Optimera Score File.'); + utils.logError('Unable to fetch the Optimera Score File.'); } }); } @@ -101,16 +101,16 @@ export function scoreFileRequest() { export function returnTargetingData(adUnits, config) { const targeting = {}; try { - adUnits.forEach((adUnit) => { + adUnits.forEach(function(adUnit) { if (optimeraTargeting[adUnit]) { targeting[adUnit] = {}; targeting[adUnit][optimeraKeyName] = [optimeraTargeting[adUnit]]; } }); } catch (err) { - logError('error', err); + utils.logError('error', err); } - logInfo('Apply Optimera targeting'); + utils.logInfo('Apply Optimera targeting'); return targeting; } @@ -141,11 +141,12 @@ export function init(moduleConfig) { setScoresURL(); scoreFileRequest(); return true; + } else { + if (!_moduleParams.clientID) { + utils.logError('Optimera clientID is missing in the Optimera RTD configuration.'); + } + return false; } - if (!_moduleParams.clientID) { - logError('Optimera clientID is missing in the Optimera RTD configuration.'); - } - return false; } /** @@ -162,7 +163,7 @@ export function init(moduleConfig) { export function setScoresURL() { const optimeraHost = window.location.host; const optimeraPathName = window.location.pathname; - const newScoresURL = `${scoresBaseURL}${clientID}/${optimeraHost}${optimeraPathName}.js`; + let newScoresURL = `${scoresBaseURL}${clientID}/${optimeraHost}${optimeraPathName}.js`; if (scoresURL !== newScoresURL) { scoresURL = newScoresURL; fetchScoreFile = true; @@ -172,9 +173,7 @@ export function setScoresURL() { } /** - * Set the scores for the device if given. - * Add data and insights to the winddow.optimera object. - * + * Set the scores for the divice if given. * @param {*} result * @returns {string} JSON string of Optimera Scores. */ @@ -185,20 +184,8 @@ export function setScores(result) { if (device !== 'default' && scores.device[device]) { scores = scores.device[device]; } - logInfo(scores); - window.optimera = window.optimera || {}; - window.optimera.data = window.optimera.data || {}; - window.optimera.insights = window.optimera.insights || {}; - Object.keys(scores).map((key) => { - if (key !== 'insights') { - window.optimera.data[key] = scores[key]; - } - }); - if (scores.insights) { - window.optimera.insights = scores.insights; - } } catch (e) { - logError('Optimera score file could not be parsed.'); + utils.logError('Optimera score file could not be parsed.'); } optimeraTargeting = scores; } diff --git a/modules/optoutBidAdapter.js b/modules/optoutBidAdapter.js index d218a65bf90..3a2e672013c 100644 --- a/modules/optoutBidAdapter.js +++ b/modules/optoutBidAdapter.js @@ -1,11 +1,11 @@ -import { deepAccess } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'optout'; function getDomain(bidderRequest) { - return deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || deepAccess(window, 'location.href'); + return utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || utils.deepAccess(window, 'location.href'); } function getCurrency() { @@ -23,7 +23,7 @@ function hasPurpose1Consent(bidderRequest) { let result = false; if (bidderRequest && bidderRequest.gdprConsent) { if (bidderRequest.gdprConsent.apiVersion === 2) { - result = !!(deepAccess(bidderRequest.gdprConsent, 'vendorData.purpose.consents.1') === true); + result = !!(utils.deepAccess(bidderRequest.gdprConsent, 'vendorData.purpose.consents.1') === true); } } return result; diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index 38af3a8d1d6..edd44385d52 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -1,9 +1,9 @@ -import { isFn, isPlainObject } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { getStorageManager } from '../src/storageManager.js'; import { BANNER, NATIVE } from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; -const storageManager = getStorageManager({bidderCode: 'orbidder'}); +const storageManager = getStorageManager(); /** * Determines whether or not the given bid response is valid. @@ -146,7 +146,7 @@ export const spec = { * @returns {float||undefined} */ function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { + if (!utils.isFn(bid.getFloor)) { return bid.params.bidfloor; } @@ -155,7 +155,7 @@ function getBidFloor(bid) { mediaType: '*', size: '*' }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'EUR') { + if (utils.isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'EUR') { return floor.floor; } return undefined; diff --git a/modules/otmBidAdapter.js b/modules/otmBidAdapter.js deleted file mode 100644 index e81bdfa9e6a..00000000000 --- a/modules/otmBidAdapter.js +++ /dev/null @@ -1,154 +0,0 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { - logInfo, - logError, - getBidIdParameter, - _each, - getValue, - isFn, - isPlainObject, - isArray, - isStr, - isNumber, -} from '../src/utils.js'; -import { BANNER } from '../src/mediaTypes.js'; - -const BIDDER_CODE = 'otm'; -const OTM_BID_URL = 'https://ssp.otm-r.com/adjson'; -const DEFAULT_CURRENCY = 'RUB' - -export const spec = { - - code: BIDDER_CODE, - url: OTM_BID_URL, - supportedMediaTypes: [ BANNER ], - - /** - * Determines whether or not the given bid request is valid. - * - * @param {object} bid The bid to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function (bid) { - return Boolean(bid.params.tid); - }, - - /** - * Build bidder requests. - * - * @param validBidRequests - * @param bidderRequest - * @returns {[]} - */ - buildRequests: function (validBidRequests, bidderRequest) { - logInfo('validBidRequests', validBidRequests); - - const bidRequests = []; - const tz = new Date().getTimezoneOffset() - const referrer = bidderRequest && bidderRequest.refererInfo ? bidderRequest.refererInfo.referer : ''; - - _each(validBidRequests, (bid) => { - let topOrigin = '' - try { - if (isStr(referrer)) topOrigin = new URL(referrer).host - } catch (e) { /* do nothing */ } - const domain = isStr(bid.params.domain) ? bid.params.domain : topOrigin - const cur = getValue(bid.params, 'currency') || DEFAULT_CURRENCY - const bidid = getBidIdParameter('bidId', bid) - const transactionid = getBidIdParameter('transactionId', bid) - const auctionid = getBidIdParameter('auctionId', bid) - const bidfloor = _getBidFloor(bid) - - _each(bid.sizes, size => { - const hasSizes = isArray(size) && isNumber(size[0]) && isNumber(size[1]) - const width = hasSizes ? size[0] : 0; - const height = hasSizes ? size[1] : 0; - - bidRequests.push({ - method: 'GET', - url: OTM_BID_URL, - data: { - tz, - w: width, - h: height, - domain, - l: referrer, - s: bid.params.tid, - cur, - bidid, - transactionid, - auctionid, - bidfloor, - }, - }) - }) - }) - return bidRequests; - }, - - /** - * Generate response. - * - * @param serverResponse - * @returns {[]|*[]} - */ - interpretResponse: function (serverResponse) { - logInfo('serverResponse', serverResponse.body); - - const responsesBody = serverResponse ? serverResponse.body : {}; - const bidResponses = []; - try { - if (responsesBody.length === 0) { - return []; - } - - _each(responsesBody, (bid) => { - if (bid.ad) { - bidResponses.push({ - requestId: bid.bidid, - cpm: bid.cpm, - width: bid.w, - height: bid.h, - creativeId: bid.creativeid, - currency: bid.currency || DEFAULT_CURRENCY, - netRevenue: true, - ad: bid.ad, - ttl: bid.ttl, - transactionId: bid.transactionid, - meta: { - advertiserDomains: bid.adDomain ? [bid.adDomain] : [] - } - }); - } - }); - } catch (error) { - logError(error); - } - - return bidResponses; - } -}; - -/** - * Get floor value - * @param bid - * @returns {null|*} - * @private - */ -function _getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return bid.params.bidfloor ? bid.params.bidfloor : 0; - } - - const floor = bid.getFloor({ - currency: DEFAULT_CURRENCY, - mediaType: '*', - size: '*' - }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === DEFAULT_CURRENCY) { - return floor.floor; - } - return 0; -} - -registerBidder(spec); diff --git a/modules/otmBidAdapter.md b/modules/otmBidAdapter.md index e5834da5729..4962d3a8052 100644 --- a/modules/otmBidAdapter.md +++ b/modules/otmBidAdapter.md @@ -1,37 +1,36 @@ # Overview -**Module Name**: OTM Bidder Adapter -**Module Type**: Bidder Adapter -**Maintainer**: e.kretsu@otm-r.com +Module Name: OTM Bidder Adapter +Module Type: Bidder Adapter +Maintainer: ? # Description -OTM Bidder Adapter for Prebid.js. About: https://otm-r.com +You can use this adapter to get a bid from otm-r.com. -Use `otm` as bidder: +About us : http://otm-r.com -# Params -- `tid` required, specific id AdUnit slot. -- `domain` optional, specific custom domain. -- `bidfloor` optional. -## AdUnits configuration example -``` - var adUnits = [{ - code: 'your-slot', //use exactly the same code as your slot div id. - mediaTypes: { - banner: { - sizes: [[320, 480]] - } - }, - bids: [{ - bidder: 'otm', - params: { - tid: 'XXXXX', - domain: 'specific custom domain, if needed', - bidfloor: 20 +# Test Parameters +```javascript + var adUnits = [ + { + code: 'div-otm-example', + sizes: [[320, 480]], + bids: [ + { + bidder: "otm", + params: { + tid: "99", + bidfloor: 20 + } + } + ] } - }] - }]; - + ]; ``` + +Where: + +* tid - A tag id (should have low cardinality) +* bidfloor - Floor price diff --git a/modules/outbrainBidAdapter.js b/modules/outbrainBidAdapter.js index e903f053c7e..052122e95f1 100644 --- a/modules/outbrainBidAdapter.js +++ b/modules/outbrainBidAdapter.js @@ -5,7 +5,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { NATIVE, BANNER } from '../src/mediaTypes.js'; -import { deepAccess, deepSetValue, replaceAuctionPrice, _map, isArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { ajax } from '../src/ajax.js'; import { config } from '../src/config.js'; @@ -27,28 +27,9 @@ export const spec = { gvlid: GVLID, supportedMediaTypes: [ NATIVE, BANNER ], isBidRequestValid: (bid) => { - if (typeof bid.params !== 'object') { - return false; - } - - if (typeof deepAccess(bid, 'params.publisher.id') !== 'string') { - return false; - } - - if (!!bid.params.tagid && typeof bid.params.tagid !== 'string') { - return false; - } - - if (!!bid.params.bcat && (typeof bid.params.bcat !== 'object' || !bid.params.bcat.every(item => typeof item === 'string'))) { - return false; - } - - if (!!bid.params.badv && (typeof bid.params.badv !== 'object' || !bid.params.badv.every(item => typeof item === 'string'))) { - return false; - } - return ( !!config.getConfig('outbrain.bidderUrl') && + !!utils.deepAccess(bid, 'params.publisher.id') && !!(bid.nativeParams || bid.sizes) ); }, @@ -59,7 +40,6 @@ export const spec = { const publisher = setOnAny(validBidRequests, 'params.publisher'); const bcat = setOnAny(validBidRequests, 'params.bcat'); const badv = setOnAny(validBidRequests, 'params.badv'); - const eids = setOnAny(validBidRequests, 'userIdAsEids') const cur = CURRENCY; const endpointUrl = config.getConfig('outbrain.bidderUrl'); const timeout = bidderRequest.timeout; @@ -86,13 +66,6 @@ export const spec = { } } - if (typeof bid.getFloor === 'function') { - const floor = _getFloor(bid, bid.nativeParams ? NATIVE : BANNER); - if (floor) { - imp.bidfloor = floor; - } - } - return imp; }); @@ -121,19 +94,15 @@ export const spec = { request.test = 1; } - if (deepAccess(bidderRequest, 'gdprConsent.gdprApplies')) { - deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString) - deepSetValue(request, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies & 1) + if (utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies')) { + utils.deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString) + utils.deepSetValue(request, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies & 1) } if (bidderRequest.uspConsent) { - deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent) + utils.deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent) } if (config.getConfig('coppa') === true) { - deepSetValue(request, 'regs.coppa', config.getConfig('coppa') & 1) - } - - if (eids) { - deepSetValue(request, 'user.ext.eids', eids); + utils.deepSetValue(request, 'regs.coppa', config.getConfig('coppa') & 1) } return { @@ -208,7 +177,7 @@ export const spec = { // for native requests we put the nurl as an imp tracker, otherwise if the auction takes place on prebid server // the server JS adapter puts the nurl in the adm as a tracking pixel and removes the attribute if (bid.nurl) { - ajax(replaceAuctionPrice(bid.nurl, bid.originalCpm)) + ajax(utils.replaceAuctionPrice(bid.nurl, bid.originalCpm)) } } }; @@ -216,7 +185,7 @@ export const spec = { registerBidder(spec); function parseNative(bid) { - const { assets, link, privacy, eventtrackers } = JSON.parse(bid.adm); + const { assets, link, eventtrackers } = JSON.parse(bid.adm); const result = { clickUrl: link.url, clickTrackers: link.clicktrackers || undefined @@ -228,9 +197,6 @@ function parseNative(bid) { result[kind] = content.text || content.value || { url: content.url, width: content.w, height: content.h }; } }); - if (privacy) { - result.privacyLink = privacy; - } if (eventtrackers) { result.impressionTrackers = []; eventtrackers.forEach(tracker => { @@ -250,7 +216,7 @@ function parseNative(bid) { function setOnAny(collection, key) { for (let i = 0, result; i < collection.length; i++) { - result = deepAccess(collection[i], key); + result = utils.deepAccess(collection[i], key); if (result) { return result; } @@ -262,7 +228,7 @@ function flatten(arr) { } function getNativeAssets(bid) { - return _map(bid.nativeParams, (bidParams, key) => { + return utils._map(bid.nativeParams, (bidParams, key) => { const props = NATIVE_PARAMS[key]; const asset = { required: bidParams.required & 1, @@ -280,8 +246,8 @@ function getNativeAssets(bid) { if (bidParams.sizes) { const sizes = flatten(bidParams.sizes); - w = parseInt(sizes[0], 10); - h = parseInt(sizes[1], 10); + w = sizes[0]; + h = sizes[1]; } asset[props.name] = { @@ -300,16 +266,16 @@ function getNativeAssets(bid) { /* Turn bid request sizes into ut-compatible format */ function transformSizes(requestSizes) { - if (!isArray(requestSizes)) { + if (!utils.isArray(requestSizes)) { return []; } - if (requestSizes.length === 2 && !isArray(requestSizes[0])) { + if (requestSizes.length === 2 && !utils.isArray(requestSizes[0])) { return [{ w: parseInt(requestSizes[0], 10), h: parseInt(requestSizes[1], 10) }]; - } else if (isArray(requestSizes[0])) { + } else if (utils.isArray(requestSizes[0])) { return requestSizes.map(item => ({ w: parseInt(item[0], 10), @@ -320,15 +286,3 @@ function transformSizes(requestSizes) { return []; } - -function _getFloor(bid, type) { - const floorInfo = bid.getFloor({ - currency: CURRENCY, - mediaType: type, - size: '*' - }); - if (typeof floorInfo === 'object' && floorInfo.currency === CURRENCY && !isNaN(parseFloat(floorInfo.floor))) { - return parseFloat(floorInfo.floor); - } - return null; -} diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index 3b5147907eb..974fe3a4304 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -1,19 +1,19 @@ -import { logInfo, logError, deepAccess, logWarn, deepSetValue, isArray, contains, isStr, mergeDeep } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import {config} from '../src/config.js'; import {getPriceBucketString} from '../src/cpmBucketManager.js'; import { Renderer } from '../src/Renderer.js'; - const BIDDER_CODE = 'ozone'; +// *** PROD *** const ORIGIN = 'https://elb.the-ozone-project.com' // applies only to auction & cookie const AUCTIONURI = '/openrtb2/auction'; const OZONECOOKIESYNC = '/static/load-cookie.html'; const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js'; const ORIGIN_DEV = 'https://test.ozpr.net'; -const OZONEVERSION = '2.7.0'; +const OZONEVERSION = '2.6.0'; export const spec = { gvlid: 524, aliases: [{code: 'lmc', gvlid: 524}, {code: 'newspassid', gvlid: 524}], @@ -41,7 +41,7 @@ export const spec = { this.propertyBag.whitelabel.logId = bidder.toUpperCase(); this.propertyBag.whitelabel.bidder = bidder; let bidderConfig = config.getConfig(bidder) || {}; - logInfo('got bidderConfig: ', JSON.parse(JSON.stringify(bidderConfig))); + utils.logInfo('got bidderConfig: ', JSON.parse(JSON.stringify(bidderConfig))); if (bidderConfig.kvpPrefix) { this.propertyBag.whitelabel.keyPrefix = bidderConfig.kvpPrefix; } @@ -52,7 +52,6 @@ export const spec = { this.propertyBag.whitelabel.auctionUrl = bidderConfig.endpointOverride.origin + AUCTIONURI; this.propertyBag.whitelabel.cookieSyncUrl = bidderConfig.endpointOverride.origin + OZONECOOKIESYNC; } - if (arr.hasOwnProperty('renderer')) { if (arr.renderer.match('%3A%2F%2F')) { this.propertyBag.whitelabel.rendererUrl = decodeURIComponent(arr['renderer']); @@ -72,15 +71,15 @@ export const spec = { } try { if (arr.hasOwnProperty('auction') && arr.auction === 'dev') { - logInfo('GET: auction=dev'); + utils.logInfo('GET: auction=dev'); this.propertyBag.whitelabel.auctionUrl = ORIGIN_DEV + AUCTIONURI; } if (arr.hasOwnProperty('cookiesync') && arr.cookiesync === 'dev') { - logInfo('GET: cookiesync=dev'); + utils.logInfo('GET: cookiesync=dev'); this.propertyBag.whitelabel.cookieSyncUrl = ORIGIN_DEV + OZONECOOKIESYNC; } } catch (e) {} - logInfo('set propertyBag.whitelabel to', this.propertyBag.whitelabel); + utils.logInfo('set propertyBag.whitelabel to', this.propertyBag.whitelabel); }, getAuctionUrl() { return this.propertyBag.whitelabel.auctionUrl; @@ -98,62 +97,62 @@ export const spec = { */ isBidRequestValid(bid) { this.loadWhitelabelData(bid); - logInfo('isBidRequestValid : ', config.getConfig(), bid); + utils.logInfo('isBidRequestValid : ', config.getConfig(), bid); let adUnitCode = bid.adUnitCode; // adunit[n].code - let err1 = 'VALIDATION FAILED : missing {param} : siteId, placementId and publisherId are REQUIRED' + if (!(bid.params.hasOwnProperty('placementId'))) { - logError(err1.replace('{param}', 'placementId'), adUnitCode); + utils.logError('VALIDATION FAILED : missing placementId : siteId, placementId and publisherId are REQUIRED', adUnitCode); return false; } if (!this.isValidPlacementId(bid.params.placementId)) { - logError('VALIDATION FAILED : placementId must be exactly 10 numeric characters', adUnitCode); + utils.logError('VALIDATION FAILED : placementId must be exactly 10 numeric characters', adUnitCode); return false; } if (!(bid.params.hasOwnProperty('publisherId'))) { - logError(err1.replace('{param}', 'publisherId'), adUnitCode); + utils.logError('VALIDATION FAILED : missing publisherId : siteId, placementId and publisherId are REQUIRED', adUnitCode); return false; } if (!(bid.params.publisherId).toString().match(/^[a-zA-Z0-9\-]{12}$/)) { - logError('VALIDATION FAILED : publisherId must be exactly 12 alphanumieric characters including hyphens', adUnitCode); + utils.logError('VALIDATION FAILED : publisherId must be exactly 12 alphanumieric characters including hyphens', adUnitCode); return false; } if (!(bid.params.hasOwnProperty('siteId'))) { - logError(err1.replace('{param}', 'siteId'), adUnitCode); + utils.logError('VALIDATION FAILED : missing siteId : siteId, placementId and publisherId are REQUIRED', adUnitCode); return false; } if (!(bid.params.siteId).toString().match(/^[0-9]{10}$/)) { - logError('VALIDATION FAILED : siteId must be exactly 10 numeric characters', adUnitCode); + utils.logError('VALIDATION FAILED : siteId must be exactly 10 numeric characters', adUnitCode); return false; } if (bid.params.hasOwnProperty('customParams')) { - logError('VALIDATION FAILED : customParams should be renamed to customData', adUnitCode); + utils.logError('VALIDATION FAILED : customParams should be renamed to customData', adUnitCode); return false; } if (bid.params.hasOwnProperty('customData')) { if (!Array.isArray(bid.params.customData)) { - logError('VALIDATION FAILED : customData is not an Array', adUnitCode); + utils.logError('VALIDATION FAILED : customData is not an Array', adUnitCode); return false; } if (bid.params.customData.length < 1) { - logError('VALIDATION FAILED : customData is an array but does not contain any elements', adUnitCode); + utils.logError('VALIDATION FAILED : customData is an array but does not contain any elements', adUnitCode); return false; } if (!(bid.params.customData[0]).hasOwnProperty('targeting')) { - logError('VALIDATION FAILED : customData[0] does not contain "targeting"', adUnitCode); + utils.logError('VALIDATION FAILED : customData[0] does not contain "targeting"', adUnitCode); return false; } if (typeof bid.params.customData[0]['targeting'] != 'object') { - logError('VALIDATION FAILED : customData[0] targeting is not an object', adUnitCode); + utils.logError('VALIDATION FAILED : customData[0] targeting is not an object', adUnitCode); return false; } } if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(VIDEO)) { if (!bid.mediaTypes[VIDEO].hasOwnProperty('context')) { - logError('No video context key/value in bid. Rejecting bid: ', bid); + utils.logError('No video context key/value in bid. Rejecting bid: ', bid); return false; } if (bid.mediaTypes[VIDEO].context !== 'instream' && bid.mediaTypes[VIDEO].context !== 'outstream') { - logError('video.context is invalid. Only instream/outstream video is supported. Rejecting bid: ', bid); + utils.logError('video.context is invalid. Only instream/outstream video is supported. Rejecting bid: ', bid); return false; } } @@ -173,27 +172,29 @@ export const spec = { this.propertyBag.buildRequestsStart = new Date().getTime(); let whitelabelBidder = this.propertyBag.whitelabel.bidder; // by default = ozone let whitelabelPrefix = this.propertyBag.whitelabel.keyPrefix; - logInfo(`buildRequests time: ${this.propertyBag.buildRequestsStart} v ${OZONEVERSION} validBidRequests`, JSON.parse(JSON.stringify(validBidRequests)), 'bidderRequest', JSON.parse(JSON.stringify(bidderRequest))); + utils.logInfo(`buildRequests time: ${this.propertyBag.buildRequestsStart} v ${OZONEVERSION} validBidRequests`, JSON.parse(JSON.stringify(validBidRequests)), 'bidderRequest', JSON.parse(JSON.stringify(bidderRequest))); + // First check - is there any config to block this request? if (this.blockTheRequest()) { return []; } let htmlParams = {'publisherId': '', 'siteId': ''}; if (validBidRequests.length > 0) { this.cookieSyncBag.userIdObject = Object.assign(this.cookieSyncBag.userIdObject, this.findAllUserIds(validBidRequests[0])); - this.cookieSyncBag.siteId = deepAccess(validBidRequests[0], 'params.siteId'); - this.cookieSyncBag.publisherId = deepAccess(validBidRequests[0], 'params.publisherId'); + this.cookieSyncBag.siteId = utils.deepAccess(validBidRequests[0], 'params.siteId'); + this.cookieSyncBag.publisherId = utils.deepAccess(validBidRequests[0], 'params.publisherId'); htmlParams = validBidRequests[0].params; } - logInfo('cookie sync bag', this.cookieSyncBag); + utils.logInfo('cookie sync bag', this.cookieSyncBag); let singleRequest = this.getWhitelabelConfigItem('ozone.singleRequest'); singleRequest = singleRequest !== false; // undefined & true will be true - logInfo(`config ${whitelabelBidder}.singleRequest : `, singleRequest); + utils.logInfo(`config ${whitelabelBidder}.singleRequest : `, singleRequest); let ozoneRequest = {}; // we only want to set specific properties on this, not validBidRequests[0].params delete ozoneRequest.test; // don't allow test to be set in the config - ONLY use $_GET['pbjs_debug'] + // First party data module : look for ortb2 in setconfig & set the User object. NOTE THAT this should happen before we set the consentString let fpd = config.getConfig('ortb2'); - if (fpd && deepAccess(fpd, 'user')) { - logInfo('added FPD user object'); + if (fpd && utils.deepAccess(fpd, 'user')) { + utils.logInfo('added FPD user object'); ozoneRequest.user = fpd.user; } @@ -202,62 +203,68 @@ export const spec = { const isTestMode = getParams[wlOztestmodeKey] || null; // this can be any string, it's used for testing ads ozoneRequest.device = {'w': window.innerWidth, 'h': window.innerHeight}; let placementIdOverrideFromGetParam = this.getPlacementIdOverrideFromGetParam(); // null or string - let schain = null; + // build the array of params to attach to `imp` let tosendtags = validBidRequests.map(ozoneBidRequest => { var obj = {}; let placementId = placementIdOverrideFromGetParam || this.getPlacementId(ozoneBidRequest); // prefer to use a valid override param, else the bidRequest placement Id obj.id = ozoneBidRequest.bidId; // this causes an error if we change it to something else, even if you update the bidRequest object: "WARNING: Bidder ozone made bid for unknown request ID: mb7953.859498327448. Ignoring." obj.tagid = placementId; obj.secure = window.location.protocol === 'https:' ? 1 : 0; + // is there a banner (or nothing declared, so banner is the default)? let arrBannerSizes = []; if (!ozoneBidRequest.hasOwnProperty('mediaTypes')) { if (ozoneBidRequest.hasOwnProperty('sizes')) { - logInfo('no mediaTypes detected - will use the sizes array in the config root'); + utils.logInfo('no mediaTypes detected - will use the sizes array in the config root'); arrBannerSizes = ozoneBidRequest.sizes; } else { - logInfo('no mediaTypes detected, no sizes array in the config root either. Cannot set sizes for banner type'); + utils.logInfo('no mediaTypes detected, no sizes array in the config root either. Cannot set sizes for banner type'); } } else { if (ozoneBidRequest.mediaTypes.hasOwnProperty(BANNER)) { arrBannerSizes = ozoneBidRequest.mediaTypes[BANNER].sizes; /* Note - if there is a sizes element in the config root it will be pushed into here */ - logInfo('setting banner size from the mediaTypes.banner element for bidId ' + obj.id + ': ', arrBannerSizes); + utils.logInfo('setting banner size from the mediaTypes.banner element for bidId ' + obj.id + ': ', arrBannerSizes); } if (ozoneBidRequest.mediaTypes.hasOwnProperty(VIDEO)) { - logInfo('openrtb 2.5 compliant video'); + utils.logInfo('openrtb 2.5 compliant video'); + // examine all the video attributes in the config, and either put them into obj.video if allowed by IAB2.5 or else in to obj.video.ext if (typeof ozoneBidRequest.mediaTypes[VIDEO] == 'object') { - let childConfig = deepAccess(ozoneBidRequest, 'params.video', {}); + let childConfig = utils.deepAccess(ozoneBidRequest, 'params.video', {}); obj.video = this.unpackVideoConfigIntoIABformat(ozoneBidRequest.mediaTypes[VIDEO], childConfig); obj.video = this.addVideoDefaults(obj.video, ozoneBidRequest.mediaTypes[VIDEO], childConfig); } + // we need to duplicate some of the video values let wh = getWidthAndHeightFromVideoObject(obj.video); - logInfo('setting video object from the mediaTypes.video element: ' + obj.id + ':', obj.video, 'wh=', wh); + utils.logInfo('setting video object from the mediaTypes.video element: ' + obj.id + ':', obj.video, 'wh=', wh); if (wh && typeof wh === 'object') { obj.video.w = wh['w']; obj.video.h = wh['h']; if (playerSizeIsNestedArray(obj.video)) { // this should never happen; it was in the original spec for this change though. - logInfo('setting obj.video.format to be an array of objects'); + utils.logInfo('setting obj.video.format to be an array of objects'); obj.video.ext.format = [wh]; } else { - logInfo('setting obj.video.format to be an object'); + utils.logInfo('setting obj.video.format to be an object'); obj.video.ext.format = wh; } } else { - logWarn('cannot set w, h & format values for video; the config is not right'); + utils.logWarn('cannot set w, h & format values for video; the config is not right'); } } + // Native integration is not complete yet if (ozoneBidRequest.mediaTypes.hasOwnProperty(NATIVE)) { obj.native = ozoneBidRequest.mediaTypes[NATIVE]; - logInfo('setting native object from the mediaTypes.native element: ' + obj.id + ':', obj.native); + utils.logInfo('setting native object from the mediaTypes.native element: ' + obj.id + ':', obj.native); } + // is the publisher specifying floors, and is the floors module enabled? if (ozoneBidRequest.hasOwnProperty('getFloor')) { - logInfo('This bidRequest object has property: getFloor'); + utils.logInfo('This bidRequest object has property: getFloor'); obj.floor = this.getFloorObjectForAuction(ozoneBidRequest); - logInfo('obj.floor is : ', obj.floor); + utils.logInfo('obj.floor is : ', obj.floor); } else { - logInfo('This bidRequest object DOES NOT have property: getFloor'); + utils.logInfo('This bidRequest object DOES NOT have property: getFloor'); } } if (arrBannerSizes.length > 0) { + // build the banner request using banner sizes we found in either possible location: obj.banner = { topframe: 1, w: arrBannerSizes[0][0] || 0, @@ -267,17 +274,20 @@ export const spec = { }) }; } + // these 3 MUST exist - we check them in the validation method obj.placementId = placementId; - deepSetValue(obj, 'ext.prebid', {'storedrequest': {'id': placementId}}); + // build the imp['ext'] object - NOTE - Dont obliterate anything that' already in obj.ext + utils.deepSetValue(obj, 'ext.prebid', {'storedrequest': {'id': placementId}}); + // obj.ext = {'prebid': {'storedrequest': {'id': placementId}}}; obj.ext[whitelabelBidder] = {}; obj.ext[whitelabelBidder].adUnitCode = ozoneBidRequest.adUnitCode; // eg. 'mpu' obj.ext[whitelabelBidder].transactionId = ozoneBidRequest.transactionId; // this is the transactionId PER adUnit, common across bidders for this unit if (ozoneBidRequest.params.hasOwnProperty('customData')) { obj.ext[whitelabelBidder].customData = ozoneBidRequest.params.customData; } - logInfo(`obj.ext.${whitelabelBidder} is `, obj.ext[whitelabelBidder]); + utils.logInfo(`obj.ext.${whitelabelBidder} is `, obj.ext[whitelabelBidder]); if (isTestMode != null) { - logInfo('setting isTestMode to ', isTestMode); + utils.logInfo('setting isTestMode to ', isTestMode); if (obj.ext[whitelabelBidder].hasOwnProperty('customData')) { for (let i = 0; i < obj.ext[whitelabelBidder].customData.length; i++) { obj.ext[whitelabelBidder].customData[i]['targeting'][wlOztestmodeKey] = isTestMode; @@ -287,52 +297,57 @@ export const spec = { obj.ext[whitelabelBidder].customData[0].targeting[wlOztestmodeKey] = isTestMode; } } - if (fpd && deepAccess(fpd, 'site')) { - logInfo('added fpd.site'); - if (deepAccess(obj, 'ext.' + whitelabelBidder + '.customData.0.targeting', false)) { + if (fpd && utils.deepAccess(fpd, 'site')) { + // attach the site fpd into exactly : imp[n].ext.[whitelabel].customData.0.targeting + utils.logInfo('added FPD site object'); + if (utils.deepAccess(obj, 'ext.' + whitelabelBidder + '.customData.0.targeting', false)) { obj.ext[whitelabelBidder].customData[0].targeting = Object.assign(obj.ext[whitelabelBidder].customData[0].targeting, fpd.site); + // let keys = utils.getKeys(fpd.site); + // for (let i = 0; i < keys.length; i++) { + // obj.ext[whitelabelBidder].customData[0].targeting[keys[i]] = fpd.site[keys[i]]; + // } } else { - deepSetValue(obj, 'ext.' + whitelabelBidder + '.customData.0.targeting', fpd.site); + utils.deepSetValue(obj, 'ext.' + whitelabelBidder + '.customData.0.targeting', fpd.site); } } - if (!schain && deepAccess(ozoneBidRequest, 'schain')) { - schain = ozoneBidRequest.schain; - } return obj; }); + // in v 2.0.0 we moved these outside of the individual ad slots let extObj = {}; extObj[whitelabelBidder] = {}; extObj[whitelabelBidder][whitelabelPrefix + '_pb_v'] = OZONEVERSION; extObj[whitelabelBidder][whitelabelPrefix + '_rw'] = placementIdOverrideFromGetParam ? 1 : 0; if (validBidRequests.length > 0) { let userIds = this.cookieSyncBag.userIdObject; // 2021-01-06 - slight optimisation - we've already found this info + // let userIds = this.findAllUserIds(validBidRequests[0]); if (userIds.hasOwnProperty('pubcid')) { extObj[whitelabelBidder].pubcid = userIds.pubcid; } } - extObj[whitelabelBidder].pv = this.getPageId(); // attach the page ID that will be common to all auciton calls for this page if refresh() is called let ozOmpFloorDollars = this.getWhitelabelConfigItem('ozone.oz_omp_floor'); // valid only if a dollar value (typeof == 'number') - logInfo(`${whitelabelPrefix}_omp_floor dollar value = `, ozOmpFloorDollars); + utils.logInfo(`${whitelabelPrefix}_omp_floor dollar value = `, ozOmpFloorDollars); if (typeof ozOmpFloorDollars === 'number') { extObj[whitelabelBidder][whitelabelPrefix + '_omp_floor'] = ozOmpFloorDollars; } else if (typeof ozOmpFloorDollars !== 'undefined') { - logError(`${whitelabelPrefix}_omp_floor is invalid - IF SET then this must be a number, representing dollar value eg. ${whitelabelPrefix}_omp_floor: 1.55. You have it set as a ` + (typeof ozOmpFloorDollars)); + utils.logError(`${whitelabelPrefix}_omp_floor is invalid - IF SET then this must be a number, representing dollar value eg. ${whitelabelPrefix}_omp_floor: 1.55. You have it set as a ` + (typeof ozOmpFloorDollars)); } let ozWhitelistAdserverKeys = this.getWhitelabelConfigItem('ozone.oz_whitelist_adserver_keys'); - let useOzWhitelistAdserverKeys = isArray(ozWhitelistAdserverKeys) && ozWhitelistAdserverKeys.length > 0; + let useOzWhitelistAdserverKeys = utils.isArray(ozWhitelistAdserverKeys) && ozWhitelistAdserverKeys.length > 0; extObj[whitelabelBidder][whitelabelPrefix + '_kvp_rw'] = useOzWhitelistAdserverKeys ? 1 : 0; if (whitelabelBidder != 'ozone') { - logInfo('setting aliases object'); + utils.logInfo('setting aliases object'); extObj.prebid = {aliases: {'ozone': whitelabelBidder}}; } + // 20210413 - adding a set of GET params to pass to auction if (getParams.hasOwnProperty('ozf')) { extObj[whitelabelBidder]['ozf'] = getParams.ozf == 'true' || getParams.ozf == 1 ? 1 : 0; } if (getParams.hasOwnProperty('ozpf')) { extObj[whitelabelBidder]['ozpf'] = getParams.ozpf == 'true' || getParams.ozpf == 1 ? 1 : 0; } if (getParams.hasOwnProperty('ozrp') && getParams.ozrp.match(/^[0-3]$/)) { extObj[whitelabelBidder]['ozrp'] = parseInt(getParams.ozrp); } if (getParams.hasOwnProperty('ozip') && getParams.ozip.match(/^\d+$/)) { extObj[whitelabelBidder]['ozip'] = parseInt(getParams.ozip); } if (this.propertyBag.endpointOverride != null) { extObj[whitelabelBidder]['origin'] = this.propertyBag.endpointOverride; } + // extObj.ortb2 = config.getConfig('ortb2'); // original test location var userExtEids = this.generateEids(validBidRequests); // generate the UserIDs in the correct format for UserId module ozoneRequest.site = { @@ -342,63 +357,64 @@ export const spec = { }; ozoneRequest.test = (getParams.hasOwnProperty('pbjs_debug') && getParams['pbjs_debug'] === 'true') ? 1 : 0; + // this should come as late as possible so it overrides any user.ext.consent value if (bidderRequest && bidderRequest.gdprConsent) { - logInfo('ADDING GDPR info'); - let apiVersion = deepAccess(bidderRequest, 'gdprConsent.apiVersion', 1); + utils.logInfo('ADDING GDPR info'); + let apiVersion = utils.deepAccess(bidderRequest, 'gdprConsent.apiVersion', 1); ozoneRequest.regs = {ext: {gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0, apiVersion: apiVersion}}; - if (deepAccess(ozoneRequest, 'regs.ext.gdpr')) { - deepSetValue(ozoneRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + if (utils.deepAccess(ozoneRequest, 'regs.ext.gdpr')) { + utils.deepSetValue(ozoneRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); } else { - logInfo('**** Strange CMP info: bidderRequest.gdprConsent exists BUT bidderRequest.gdprConsent.gdprApplies is false. See bidderRequest logged above. ****'); + utils.logInfo('**** Strange CMP info: bidderRequest.gdprConsent exists BUT bidderRequest.gdprConsent.gdprApplies is false. See bidderRequest logged above. ****'); } } else { - logInfo('WILL NOT ADD GDPR info; no bidderRequest.gdprConsent object'); + utils.logInfo('WILL NOT ADD GDPR info; no bidderRequest.gdprConsent object'); } if (bidderRequest && bidderRequest.uspConsent) { - logInfo('ADDING CCPA info'); - deepSetValue(ozoneRequest, 'user.ext.uspConsent', bidderRequest.uspConsent); + utils.logInfo('ADDING CCPA info'); + utils.deepSetValue(ozoneRequest, 'user.ext.uspConsent', bidderRequest.uspConsent); } else { - logInfo('WILL NOT ADD CCPA info; no bidderRequest.uspConsent.'); - } - if (schain) { // we set this while iterating over the bids - logInfo('schain found'); - deepSetValue(ozoneRequest, 'source.ext.schain', schain); + utils.logInfo('WILL NOT ADD CCPA info; no bidderRequest.uspConsent.'); } + // this is for 2.2.1 + // coppa compliance if (config.getConfig('coppa') === true) { - deepSetValue(ozoneRequest, 'regs.coppa', 1); + utils.deepSetValue(ozoneRequest, 'regs.coppa', 1); } + // return the single request object OR the array: if (singleRequest) { - logInfo('buildRequests starting to generate response for a single request'); + utils.logInfo('buildRequests starting to generate response for a single request'); ozoneRequest.id = bidderRequest.auctionId; // Unique ID of the bid request, provided by the exchange. ozoneRequest.auctionId = bidderRequest.auctionId; // not sure if this should be here? ozoneRequest.imp = tosendtags; ozoneRequest.ext = extObj; - deepSetValue(ozoneRequest, 'source.tid', bidderRequest.auctionId);// RTB 2.5 : tid is Transaction ID that must be common across all participants in this bid request (e.g., potentially multiple exchanges). - deepSetValue(ozoneRequest, 'user.ext.eids', userExtEids); + ozoneRequest.source = {'tid': bidderRequest.auctionId}; // RTB 2.5 : tid is Transaction ID that must be common across all participants in this bid request (e.g., potentially multiple exchanges). + utils.deepSetValue(ozoneRequest, 'user.ext.eids', userExtEids); var ret = { method: 'POST', url: this.getAuctionUrl(), data: JSON.stringify(ozoneRequest), bidderRequest: bidderRequest }; - logInfo('buildRequests request data for single = ', JSON.parse(JSON.stringify(ozoneRequest))); + utils.logInfo('buildRequests request data for single = ', JSON.parse(JSON.stringify(ozoneRequest))); this.propertyBag.buildRequestsEnd = new Date().getTime(); - logInfo(`buildRequests going to return for single at time ${this.propertyBag.buildRequestsEnd} (took ${this.propertyBag.buildRequestsEnd - this.propertyBag.buildRequestsStart}ms): `, ret); + utils.logInfo(`buildRequests going to return for single at time ${this.propertyBag.buildRequestsEnd} (took ${this.propertyBag.buildRequestsEnd - this.propertyBag.buildRequestsStart}ms): `, ret); return ret; } + // not single request - pull apart the tosendtags array & return an array of objects each containing one element in the imp array. let arrRet = tosendtags.map(imp => { - logInfo('buildRequests starting to generate non-single response, working on imp : ', imp); + utils.logInfo('buildRequests starting to generate non-single response, working on imp : ', imp); let ozoneRequestSingle = Object.assign({}, ozoneRequest); imp.ext[whitelabelBidder].pageAuctionId = bidderRequest['auctionId']; // make a note in the ext object of what the original auctionId was, in the bidderRequest object ozoneRequestSingle.id = imp.ext[whitelabelBidder].transactionId; // Unique ID of the bid request, provided by the exchange. ozoneRequestSingle.auctionId = imp.ext[whitelabelBidder].transactionId; // not sure if this should be here? ozoneRequestSingle.imp = [imp]; ozoneRequestSingle.ext = extObj; - deepSetValue(ozoneRequestSingle, 'source.tid', imp.ext[whitelabelBidder].transactionId);// RTB 2.5 : tid is Transaction ID that must be common across all participants in this bid request (e.g., potentially multiple exchanges). - deepSetValue(ozoneRequestSingle, 'user.ext.eids', userExtEids); - logInfo('buildRequests RequestSingle (for non-single) = ', ozoneRequestSingle); + ozoneRequestSingle.source = {'tid': imp.ext[whitelabelBidder].transactionId}; + utils.deepSetValue(ozoneRequestSingle, 'user.ext.eids', userExtEids); + utils.logInfo('buildRequests RequestSingle (for non-single) = ', ozoneRequestSingle); return { method: 'POST', url: this.getAuctionUrl(), @@ -407,7 +423,7 @@ export const spec = { }; }); this.propertyBag.buildRequestsEnd = new Date().getTime(); - logInfo(`buildRequests going to return for non-single at time ${this.propertyBag.buildRequestsEnd} (took ${this.propertyBag.buildRequestsEnd - this.propertyBag.buildRequestsStart}ms): `, arrRet); + utils.logInfo(`buildRequests going to return for non-single at time ${this.propertyBag.buildRequestsEnd} (took ${this.propertyBag.buildRequestsEnd - this.propertyBag.buildRequestsStart}ms): `, arrRet); return arrRet; }, /** @@ -425,11 +441,11 @@ export const spec = { */ getFloorObjectForAuction(bidRequestRef) { const mediaTypesSizes = { - banner: deepAccess(bidRequestRef, 'mediaTypes.banner.sizes', null), - video: deepAccess(bidRequestRef, 'mediaTypes.video.playerSize', null), - native: deepAccess(bidRequestRef, 'mediaTypes.native.image.sizes', null) + banner: utils.deepAccess(bidRequestRef, 'mediaTypes.banner.sizes', null), + video: utils.deepAccess(bidRequestRef, 'mediaTypes.video.playerSize', null), + native: utils.deepAccess(bidRequestRef, 'mediaTypes.native.image.sizes', null) } - logInfo('getFloorObjectForAuction mediaTypesSizes : ', mediaTypesSizes); + utils.logInfo('getFloorObjectForAuction mediaTypesSizes : ', mediaTypesSizes); let ret = {}; if (mediaTypesSizes.banner) { ret.banner = bidRequestRef.getFloor({mediaType: 'banner', currency: 'USD', size: mediaTypesSizes.banner}); @@ -440,7 +456,7 @@ export const spec = { if (mediaTypesSizes.native) { ret.native = bidRequestRef.getFloor({mediaType: 'native', currency: 'USD', size: mediaTypesSizes.native}); } - logInfo('getFloorObjectForAuction returning : ', JSON.parse(JSON.stringify(ret))); + utils.logInfo('getFloorObjectForAuction returning : ', JSON.parse(JSON.stringify(ret))); return ret; }, /** @@ -458,9 +474,10 @@ export const spec = { let startTime = new Date().getTime(); let whitelabelBidder = this.propertyBag.whitelabel.bidder; // by default = ozone let whitelabelPrefix = this.propertyBag.whitelabel.keyPrefix; - logInfo(`interpretResponse time: ${startTime} . Time between buildRequests done and interpretResponse start was ${startTime - this.propertyBag.buildRequestsEnd}ms`); - logInfo(`serverResponse, request`, JSON.parse(JSON.stringify(serverResponse)), JSON.parse(JSON.stringify(request))); + utils.logInfo(`interpretResponse time: ${startTime} . Time between buildRequests done and interpretResponse start was ${startTime - this.propertyBag.buildRequestsEnd}ms`); + utils.logInfo(`serverResponse, request`, JSON.parse(JSON.stringify(serverResponse)), JSON.parse(JSON.stringify(request))); serverResponse = serverResponse.body || {}; + // note that serverResponse.id value is the auction_id we might want to use for reporting reasons. if (!serverResponse.hasOwnProperty('seatbid')) { return []; } @@ -469,48 +486,52 @@ export const spec = { } let arrAllBids = []; let enhancedAdserverTargeting = this.getWhitelabelConfigItem('ozone.enhancedAdserverTargeting'); - logInfo('enhancedAdserverTargeting', enhancedAdserverTargeting); + utils.logInfo('enhancedAdserverTargeting', enhancedAdserverTargeting); if (typeof enhancedAdserverTargeting == 'undefined') { enhancedAdserverTargeting = true; } - logInfo('enhancedAdserverTargeting', enhancedAdserverTargeting); + utils.logInfo('enhancedAdserverTargeting', enhancedAdserverTargeting); + // 2021-03-05 - comment this out for a build without adding adid to the response serverResponse.seatbid = injectAdIdsIntoAllBidResponses(serverResponse.seatbid); // we now make sure that each bid in the bidresponse has a unique (within page) adId attribute. serverResponse.seatbid = this.removeSingleBidderMultipleBids(serverResponse.seatbid); let ozOmpFloorDollars = this.getWhitelabelConfigItem('ozone.oz_omp_floor'); // valid only if a dollar value (typeof == 'number') let addOzOmpFloorDollars = typeof ozOmpFloorDollars === 'number'; let ozWhitelistAdserverKeys = this.getWhitelabelConfigItem('ozone.oz_whitelist_adserver_keys'); - let useOzWhitelistAdserverKeys = isArray(ozWhitelistAdserverKeys) && ozWhitelistAdserverKeys.length > 0; + let useOzWhitelistAdserverKeys = utils.isArray(ozWhitelistAdserverKeys) && ozWhitelistAdserverKeys.length > 0; for (let i = 0; i < serverResponse.seatbid.length; i++) { let sb = serverResponse.seatbid[i]; for (let j = 0; j < sb.bid.length; j++) { let thisRequestBid = this.getBidRequestForBidId(sb.bid[j].impid, request.bidderRequest.bids); - logInfo(`seatbid:${i}, bid:${j} Going to set default w h for seatbid/bidRequest`, sb.bid[j], thisRequestBid); + utils.logInfo(`seatbid:${i}, bid:${j} Going to set default w h for seatbid/bidRequest`, sb.bid[j], thisRequestBid); const {defaultWidth, defaultHeight} = defaultSize(thisRequestBid); let thisBid = ozoneAddStandardProperties(sb.bid[j], defaultWidth, defaultHeight); + // prebid 4.0 compliance thisBid.meta = {advertiserDomains: thisBid.adomain || []}; let videoContext = null; let isVideo = false; - let bidType = deepAccess(thisBid, 'ext.prebid.type'); - logInfo(`this bid type is : ${bidType}`, j); + let bidType = utils.deepAccess(thisBid, 'ext.prebid.type'); + utils.logInfo(`this bid type is : ${bidType}`, j); if (bidType === VIDEO) { isVideo = true; videoContext = this.getVideoContextForBidId(thisBid.bidId, request.bidderRequest.bids); // should be instream or outstream (or null if error) if (videoContext === 'outstream') { - logInfo('going to attach a renderer to OUTSTREAM video : ', j); + utils.logInfo('going to attach a renderer to OUTSTREAM video : ', j); thisBid.renderer = newRenderer(thisBid.bidId); } else { - logInfo('bid is not an outstream video, will not attach a renderer: ', j); + utils.logInfo('bid is not an outstream video, will not attach a renderer: ', j); } } let adserverTargeting = {}; if (enhancedAdserverTargeting) { let allBidsForThisBidid = ozoneGetAllBidsForBidId(thisBid.bidId, serverResponse.seatbid); - logInfo('Going to iterate allBidsForThisBidId', allBidsForThisBidid); + // add all the winning & non-winning bids for this bidId: + utils.logInfo('Going to iterate allBidsForThisBidId', allBidsForThisBidid); Object.keys(allBidsForThisBidid).forEach((bidderName, index, ar2) => { - logInfo(`adding adserverTargeting for ${bidderName} for bidId ${thisBid.bidId}`); + utils.logInfo(`adding adserverTargeting for ${bidderName} for bidId ${thisBid.bidId}`); + // let bidderName = bidderNameWH.split('_')[0]; adserverTargeting[whitelabelPrefix + '_' + bidderName] = bidderName; adserverTargeting[whitelabelPrefix + '_' + bidderName + '_crid'] = String(allBidsForThisBidid[bidderName].crid); adserverTargeting[whitelabelPrefix + '_' + bidderName + '_adv'] = String(allBidsForThisBidid[bidderName].adomain); @@ -525,11 +546,11 @@ export const spec = { if (isVideo) { adserverTargeting[whitelabelPrefix + '_' + bidderName + '_vid'] = videoContext; // outstream or instream } - let flr = deepAccess(allBidsForThisBidid[bidderName], `ext.bidder.${whitelabelBidder}.floor`, null); + let flr = utils.deepAccess(allBidsForThisBidid[bidderName], `ext.bidder.${whitelabelBidder}.floor`, null); if (flr != null) { adserverTargeting[whitelabelPrefix + '_' + bidderName + '_flr'] = flr; } - let rid = deepAccess(allBidsForThisBidid[bidderName], `ext.bidder.${whitelabelBidder}.ruleId`, null); + let rid = utils.deepAccess(allBidsForThisBidid[bidderName], `ext.bidder.${whitelabelBidder}.ruleId`, null); if (rid != null) { adserverTargeting[whitelabelPrefix + '_' + bidderName + '_rid'] = rid; } @@ -539,11 +560,12 @@ export const spec = { }); } else { if (useOzWhitelistAdserverKeys) { - logWarn(`You have set a whitelist of adserver keys but this will be ignored because ${whitelabelBidder}.enhancedAdserverTargeting is set to false. No per-bid keys will be sent to adserver.`); + utils.logWarn(`You have set a whitelist of adserver keys but this will be ignored because ${whitelabelBidder}.enhancedAdserverTargeting is set to false. No per-bid keys will be sent to adserver.`); } else { - logInfo(`${whitelabelBidder}.enhancedAdserverTargeting is set to false, so no per-bid keys will be sent to adserver.`); + utils.logInfo(`${whitelabelBidder}.enhancedAdserverTargeting is set to false, so no per-bid keys will be sent to adserver.`); } } + // also add in the winning bid, to be sent to dfp let {seat: winningSeat, bid: winningBid} = ozoneGetWinnerForRequestBid(thisBid.bidId, serverResponse.seatbid); adserverTargeting[whitelabelPrefix + '_auc_id'] = String(request.bidderRequest.auctionId); adserverTargeting[whitelabelPrefix + '_winner'] = String(winningSeat); @@ -558,7 +580,7 @@ export const spec = { adserverTargeting[whitelabelPrefix + '_size'] = `${winningBid.width}x${winningBid.height}`; } if (useOzWhitelistAdserverKeys) { // delete any un-whitelisted keys - logInfo('Going to filter out adserver targeting keys not in the whitelist: ', ozWhitelistAdserverKeys); + utils.logInfo('Going to filter out adserver targeting keys not in the whitelist: ', ozWhitelistAdserverKeys); Object.keys(adserverTargeting).forEach(function(key) { if (ozWhitelistAdserverKeys.indexOf(key) === -1) { delete adserverTargeting[key]; } }); } thisBid.adserverTargeting = adserverTargeting; @@ -566,20 +588,20 @@ export const spec = { } } let endTime = new Date().getTime(); - logInfo(`interpretResponse going to return at time ${endTime} (took ${endTime - startTime}ms) Time from buildRequests Start -> interpretRequests End = ${endTime - this.propertyBag.buildRequestsStart}ms`, arrAllBids); + utils.logInfo(`interpretResponse going to return at time ${endTime} (took ${endTime - startTime}ms) Time from buildRequests Start -> interpretRequests End = ${endTime - this.propertyBag.buildRequestsStart}ms`, arrAllBids); return arrAllBids; }, /** * Use this to get all config values * Now it's getting complicated with whitelabeling, this simplifies the code for getting config values. - * eg. to get whitelabelled version you just sent the ozone default string like ozone.oz_omp_floor + * eg. to get ozone.oz_omp_floor you just send '_omp_floor' * @param ozoneVersion string like 'ozone.oz_omp_floor' * @return {string|object} */ getWhitelabelConfigItem(ozoneVersion) { if (this.propertyBag.whitelabel.bidder == 'ozone') { return config.getConfig(ozoneVersion); } let whitelabelledSearch = ozoneVersion.replace('ozone', this.propertyBag.whitelabel.bidder); - whitelabelledSearch = whitelabelledSearch.replace('oz_', this.propertyBag.whitelabel.keyPrefix + '_'); + whitelabelledSearch = ozoneVersion.replace('oz_', this.propertyBag.whitelabel.keyPrefix + '_'); return config.getConfig(whitelabelledSearch); }, /** @@ -594,7 +616,7 @@ export const spec = { var bidIds = []; for (let j = 0; j < sb.bid.length; j++) { var candidate = sb.bid[j]; - if (contains(bidIds, candidate.impid)) { + if (utils.contains(bidIds, candidate.impid)) { continue; // we've already fully assessed this impid, found the highest bid from this seat for it } bidIds.push(candidate.impid); @@ -609,8 +631,10 @@ export const spec = { } return ret; }, + // see http://prebid.org/dev-docs/bidder-adaptor.html#registering-user-syncs + // us privacy: https://docs.prebid.org/dev-docs/modules/consentManagementUsp.html getUserSyncs(optionsType, serverResponse, gdprConsent, usPrivacy) { - logInfo('getUserSyncs optionsType', optionsType, 'serverResponse', serverResponse, 'gdprConsent', gdprConsent, 'usPrivacy', usPrivacy, 'cookieSyncBag', this.cookieSyncBag); + utils.logInfo('getUserSyncs optionsType', optionsType, 'serverResponse', serverResponse, 'gdprConsent', gdprConsent, 'usPrivacy', usPrivacy, 'cookieSyncBag', this.cookieSyncBag); if (!serverResponse || serverResponse.length === 0) { return []; } @@ -619,9 +643,14 @@ export const spec = { if (document.location.search.match(/pbjs_debug=true/)) { arrQueryString.push('pbjs_debug=true'); } - arrQueryString.push('gdpr=' + (deepAccess(gdprConsent, 'gdprApplies', false) ? '1' : '0')); - arrQueryString.push('gdpr_consent=' + deepAccess(gdprConsent, 'consentString', '')); + arrQueryString.push('gdpr=' + (utils.deepAccess(gdprConsent, 'gdprApplies', false) ? '1' : '0')); + arrQueryString.push('gdpr_consent=' + utils.deepAccess(gdprConsent, 'consentString', '')); arrQueryString.push('usp_consent=' + (usPrivacy || '')); + // var objKeys = Object.getOwnPropertyNames(this.cookieSyncBag.userIdObject); + // for (let idx in objKeys) { + // let keyname = objKeys[idx]; + // arrQueryString.push(keyname + '=' + this.cookieSyncBag.userIdObject[keyname]); + // } for (let keyname in this.cookieSyncBag.userIdObject) { arrQueryString.push(keyname + '=' + this.cookieSyncBag.userIdObject[keyname]); } @@ -634,7 +663,7 @@ export const spec = { if (strQueryString.length > 0) { strQueryString = '?' + strQueryString; } - logInfo('getUserSyncs going to return cookie sync url : ' + this.getCookieSyncUrl() + strQueryString); + utils.logInfo('getUserSyncs going to return cookie sync url : ' + this.getCookieSyncUrl() + strQueryString); return [{ type: 'iframe', url: this.getCookieSyncUrl() + strQueryString @@ -664,7 +693,7 @@ export const spec = { getVideoContextForBidId(bidId, arrBids) { let requestBid = this.getBidRequestForBidId(bidId, arrBids); if (requestBid != null) { - return deepAccess(requestBid, 'mediaTypes.video.context', 'unknown') + return utils.deepAccess(requestBid, 'mediaTypes.video.context', 'unknown') } return null; }, @@ -675,7 +704,10 @@ export const spec = { */ findAllUserIds(bidRequest) { var ret = {}; + // @todo - what is Neustar fabrick called & where to look for it? If it's a simple value then it will automatically be ok + // it is not in the table 'Bidder Adapter Implementation' on https://docs.prebid.org/dev-docs/modules/userId.html#prebidjs-adapters let searchKeysSingle = ['pubcid', 'tdid', 'idl_env', 'criteoId', 'lotamePanoramaId', 'fabrickId']; + if (bidRequest.hasOwnProperty('userId')) { for (let arrayId in searchKeysSingle) { let key = searchKeysSingle[arrayId]; @@ -683,36 +715,37 @@ export const spec = { if (typeof (bidRequest.userId[key]) == 'string') { ret[key] = bidRequest.userId[key]; } else if (typeof (bidRequest.userId[key]) == 'object') { - logError(`WARNING: findAllUserIds had to use first key in user object to get value for bid.userId key: ${key}. Prebid adapter should be updated.`); + utils.logError(`WARNING: findAllUserIds had to use first key in user object to get value for bid.userId key: ${key}. Prebid adapter should be updated.`); + // fallback - get the value of the first key in the object; this is NOT desirable behaviour ret[key] = bidRequest.userId[key][Object.keys(bidRequest.userId[key])[0]]; // cannot use Object.values } else { - logError(`failed to get string key value for userId : ${key}`); + utils.logError(`failed to get string key value for userId : ${key}`); } } } - let lipbid = deepAccess(bidRequest.userId, 'lipb.lipbid'); + let lipbid = utils.deepAccess(bidRequest.userId, 'lipb.lipbid'); if (lipbid) { ret['lipb'] = {'lipbid': lipbid}; } - let id5id = deepAccess(bidRequest.userId, 'id5id.uid'); + let id5id = utils.deepAccess(bidRequest.userId, 'id5id.uid'); if (id5id) { ret['id5id'] = id5id; } - let parrableId = deepAccess(bidRequest.userId, 'parrableId.eid'); + let parrableId = utils.deepAccess(bidRequest.userId, 'parrableId.eid'); if (parrableId) { ret['parrableId'] = parrableId; } - let sharedid = deepAccess(bidRequest.userId, 'sharedid.id'); + let sharedid = utils.deepAccess(bidRequest.userId, 'sharedid.id'); if (sharedid) { ret['sharedid'] = sharedid; } - let sharedidthird = deepAccess(bidRequest.userId, 'sharedid.third'); + let sharedidthird = utils.deepAccess(bidRequest.userId, 'sharedid.third'); if (sharedidthird) { ret['sharedidthird'] = sharedidthird; } } if (!ret.hasOwnProperty('pubcid')) { - let pubcid = deepAccess(bidRequest, 'crumbs.pubcid'); + let pubcid = utils.deepAccess(bidRequest, 'crumbs.pubcid'); if (pubcid) { ret['pubcid'] = pubcid; // if built with old pubCommonId module } @@ -738,10 +771,10 @@ export const spec = { let arr = this.getGetParametersAsObject(); if (arr.hasOwnProperty(whitelabelPrefix + 'storedrequest')) { if (this.isValidPlacementId(arr[whitelabelPrefix + 'storedrequest'])) { - logInfo(`using GET ${whitelabelPrefix}storedrequest ` + arr[whitelabelPrefix + 'storedrequest'] + ' to replace placementId'); + utils.logInfo(`using GET ${whitelabelPrefix}storedrequest ` + arr[whitelabelPrefix + 'storedrequest'] + ' to replace placementId'); return arr[whitelabelPrefix + 'storedrequest']; } else { - logError(`GET ${whitelabelPrefix}storedrequest FAILED VALIDATION - will not use it`); + utils.logError(`GET ${whitelabelPrefix}storedrequest FAILED VALIDATION - will not use it`); } } return null; @@ -764,9 +797,9 @@ export const spec = { handleTTDId(eids, validBidRequests) { let ttdId = null; let adsrvrOrgId = config.getConfig('adsrvrOrgId'); - if (isStr(deepAccess(validBidRequests, '0.userId.tdid'))) { + if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.tdid'))) { ttdId = validBidRequests[0].userId.tdid; - } else if (adsrvrOrgId && isStr(adsrvrOrgId.TDID)) { + } else if (adsrvrOrgId && utils.isStr(adsrvrOrgId.TDID)) { ttdId = adsrvrOrgId.TDID; } if (ttdId !== null) { @@ -782,6 +815,7 @@ export const spec = { }); } }, + // Try to use this as the mechanism for reading GET params because it's easy to mock it for tests getGetParametersAsObject() { let items = location.search.substr(1).split('&'); let ret = {}; @@ -797,9 +831,10 @@ export const spec = { * @return {boolean|*[]} true = block the request, else false */ blockTheRequest() { + // if there is an ozone.oz_request = false then quit now. let ozRequest = this.getWhitelabelConfigItem('ozone.oz_request'); if (typeof ozRequest == 'boolean' && !ozRequest) { - logWarn(`Will not allow auction : ${this.propertyBag.whitelabel.keyPrefix}one.${this.propertyBag.whitelabel.keyPrefix}_request is set to false`); + utils.logWarn(`Will not allow auction : ${this.propertyBag.whitelabel.keyPrefix}one.${this.propertyBag.whitelabel.keyPrefix}_request is set to false`); return true; } return false; @@ -847,9 +882,10 @@ export const spec = { ret.ext[key] = objConfig[key]; } } + // handle ext separately, if it exists; we have probably built up an ext object already if (objConfig.hasOwnProperty('ext') && typeof objConfig.ext === 'object') { if (objConfig.hasOwnProperty('ext')) { - ret.ext = mergeDeep(ret.ext, objConfig.ext); + ret.ext = utils.mergeDeep(ret.ext, objConfig.ext); } else { ret.ext = objConfig.ext; } @@ -870,13 +906,14 @@ export const spec = { * @private */ _addVideoDefaults(objRet, objConfig, addIfMissing) { - let context = deepAccess(objConfig, 'context'); + // add inferred values & any default values we want. + let context = utils.deepAccess(objConfig, 'context'); if (context === 'outstream') { objRet.placement = 3; } else if (context === 'instream') { objRet.placement = 1; } - let skippable = deepAccess(objConfig, 'skippable', null); + let skippable = utils.deepAccess(objConfig, 'skippable', null); if (skippable == null) { if (addIfMissing && !objRet.hasOwnProperty('skip')) { objRet.skip = skippable ? 1 : 0; @@ -895,10 +932,12 @@ export const spec = { * @returns seatbid object */ export function injectAdIdsIntoAllBidResponses(seatbid) { - logInfo('injectAdIdsIntoAllBidResponses', seatbid); + utils.logInfo('injectAdIdsIntoAllBidResponses', seatbid); for (let i = 0; i < seatbid.length; i++) { let sb = seatbid[i]; for (let j = 0; j < sb.bid.length; j++) { + // modify the bidId per-bid, so each bid has a unique adId within this response, and dfp can select one. + // 2020-06 we now need a second level of ID because there might be multiple identical impid's within a seatbid! sb.bid[j]['adId'] = `${sb.bid[j]['impid']}-${i}-${spec.propertyBag.whitelabel.keyPrefix}-${j}`; } } @@ -919,7 +958,7 @@ export function checkDeepArray(Arr) { export function defaultSize(thebidObj) { if (!thebidObj) { - logInfo('defaultSize received empty bid obj! going to return fixed default size'); + utils.logInfo('defaultSize received empty bid obj! going to return fixed default size'); return { 'defaultHeight': 250, 'defaultWidth': 300 @@ -946,6 +985,7 @@ export function ozoneGetWinnerForRequestBid(requestBidId, serverResponseSeatBid) let thisSeat = serverResponseSeatBid[j].seat; for (let k = 0; k < theseBids.length; k++) { if (theseBids[k].impid === requestBidId) { + // we've found a matching server response bid for this request bid if ((thisBidWinner == null) || (thisBidWinner.price < theseBids[k].price)) { thisBidWinner = theseBids[k]; winningSeat = thisSeat; @@ -971,6 +1011,7 @@ export function ozoneGetAllBidsForBidId(matchBidId, serverResponseSeatBid) { for (let k = 0; k < theseBids.length; k++) { if (theseBids[k].impid === matchBidId) { if (objBids.hasOwnProperty(thisSeat)) { // > 1 bid for an adunit from a bidder - only use the one with the highest bid + // objBids[`${thisSeat}${theseBids[k].w}x${theseBids[k].h}`] = theseBids[k]; if (objBids[thisSeat]['price'] < theseBids[k].price) { objBids[thisSeat] = theseBids[k]; } @@ -995,14 +1036,15 @@ export function getRoundedBid(price, mediaType) { let theConfigObject = getGranularityObject(mediaType, mediaTypeGranularity, strBuckets, objBuckets); let theConfigKey = getGranularityKeyName(mediaType, mediaTypeGranularity, strBuckets); - logInfo('getRoundedBid. price:', price, 'mediaType:', mediaType, 'configkey:', theConfigKey, 'configObject:', theConfigObject, 'mediaTypeGranularity:', mediaTypeGranularity, 'strBuckets:', strBuckets); + utils.logInfo('getRoundedBid. price:', price, 'mediaType:', mediaType, 'configkey:', theConfigKey, 'configObject:', theConfigObject, 'mediaTypeGranularity:', mediaTypeGranularity, 'strBuckets:', strBuckets); let priceStringsObj = getPriceBucketString( price, theConfigObject, config.getConfig('currency.granularityMultiplier') ); - logInfo('priceStringsObj', priceStringsObj); + utils.logInfo('priceStringsObj', priceStringsObj); + // by default, without any custom granularity set, you get granularity name : 'medium' let granularityNamePriceStringsKeyMapping = { 'medium': 'med', 'custom': 'custom', @@ -1012,7 +1054,7 @@ export function getRoundedBid(price, mediaType) { }; if (granularityNamePriceStringsKeyMapping.hasOwnProperty(theConfigKey)) { let priceStringsKey = granularityNamePriceStringsKeyMapping[theConfigKey]; - logInfo('getRoundedBid: looking for priceStringsKey:', priceStringsKey); + utils.logInfo('getRoundedBid: looking for priceStringsKey:', priceStringsKey); return priceStringsObj[priceStringsKey]; } return priceStringsObj['auto']; @@ -1081,15 +1123,15 @@ export function getWidthAndHeightFromVideoObject(objVideo) { return null; } if (playerSize[0] && typeof playerSize[0] === 'object') { - logInfo('getWidthAndHeightFromVideoObject found nested array inside playerSize.', playerSize[0]); + utils.logInfo('getWidthAndHeightFromVideoObject found nested array inside playerSize.', playerSize[0]); playerSize = playerSize[0]; if (typeof playerSize[0] !== 'number' && typeof playerSize[0] !== 'string') { - logInfo('getWidthAndHeightFromVideoObject found non-number/string type inside the INNER array in playerSize. This is totally wrong - cannot continue.', playerSize[0]); + utils.logInfo('getWidthAndHeightFromVideoObject found non-number/string type inside the INNER array in playerSize. This is totally wrong - cannot continue.', playerSize[0]); return null; } } if (playerSize.length !== 2) { - logInfo('getWidthAndHeightFromVideoObject found playerSize with length of ' + playerSize.length + '. This is totally wrong - cannot continue.'); + utils.logInfo('getWidthAndHeightFromVideoObject found playerSize with length of ' + playerSize.length + '. This is totally wrong - cannot continue.'); return null; } return ({'w': playerSize[0], 'h': playerSize[1]}); @@ -1116,17 +1158,17 @@ export function playerSizeIsNestedArray(objVideo) { * @returns {*} */ function getPlayerSizeFromObject(objVideo) { - logInfo('getPlayerSizeFromObject received object', objVideo); - let playerSize = deepAccess(objVideo, 'playerSize'); + utils.logInfo('getPlayerSizeFromObject received object', objVideo); + let playerSize = utils.deepAccess(objVideo, 'playerSize'); if (!playerSize) { - playerSize = deepAccess(objVideo, 'ext.playerSize'); + playerSize = utils.deepAccess(objVideo, 'ext.playerSize'); } if (!playerSize) { - logError('getPlayerSizeFromObject FAILED: no playerSize in video object or ext', objVideo); + utils.logError('getPlayerSizeFromObject FAILED: no playerSize in video object or ext', objVideo); return null; } if (typeof playerSize !== 'object') { - logError('getPlayerSizeFromObject FAILED: playerSize is not an object/array', objVideo); + utils.logError('getPlayerSizeFromObject FAILED: playerSize is not an object/array', objVideo); return null; } return playerSize; @@ -1137,7 +1179,7 @@ function getPlayerSizeFromObject(objVideo) { */ function newRenderer(adUnitCode, rendererOptions = {}) { let isLoaded = window.ozoneVideo; - logInfo(`newRenderer going to set loaded to ${isLoaded ? 'true' : 'false'}`); + utils.logInfo(`newRenderer going to set loaded to ${isLoaded ? 'true' : 'false'}`); const renderer = Renderer.install({ url: spec.getRendererUrl(), config: rendererOptions, @@ -1147,16 +1189,17 @@ function newRenderer(adUnitCode, rendererOptions = {}) { try { renderer.setRender(outstreamRender); } catch (err) { - logError('Prebid Error when calling setRender on renderer', JSON.parse(JSON.stringify(renderer)), err); + utils.logError('Prebid Error when calling setRender on renderer', JSON.parse(JSON.stringify(renderer)), err); } return renderer; } function outstreamRender(bid) { - logInfo('outstreamRender called. Going to push the call to window.ozoneVideo.outstreamRender(bid) bid =', JSON.parse(JSON.stringify(bid))); + utils.logInfo('outstreamRender called. Going to push the call to window.ozoneVideo.outstreamRender(bid) bid =', JSON.parse(JSON.stringify(bid))); + // push to render queue because ozoneVideo may not be loaded yet bid.renderer.push(() => { window.ozoneVideo.outstreamRender(bid); }); } registerBidder(spec); -logInfo(`*BidAdapter ${OZONEVERSION} was loaded`); +utils.logInfo(`*BidAdapter ${OZONEVERSION} was loaded`); diff --git a/modules/padsquadBidAdapter.js b/modules/padsquadBidAdapter.js index 72449cf28be..24b1d5be3be 100644 --- a/modules/padsquadBidAdapter.js +++ b/modules/padsquadBidAdapter.js @@ -1,5 +1,5 @@ -import { logInfo, deepAccess } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import {BANNER} from '../src/mediaTypes.js'; const ENDPOINT_URL = 'https://x.padsquad.com/auction'; @@ -89,12 +89,12 @@ export const spec = { }) }) } else { - logInfo('padsquad.interpretResponse :: no valid responses to interpret'); + utils.logInfo('padsquad.interpretResponse :: no valid responses to interpret'); } return bidResponses; }, getUserSyncs: function (syncOptions, serverResponses) { - logInfo('padsquad.getUserSyncs', 'syncOptions', syncOptions, 'serverResponses', serverResponses); + utils.logInfo('padsquad.getUserSyncs', 'syncOptions', syncOptions, 'serverResponses', serverResponses); let syncs = []; if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) { @@ -102,7 +102,7 @@ export const spec = { } serverResponses.forEach(resp => { - const userSync = deepAccess(resp, 'body.ext.usersync'); + const userSync = utils.deepAccess(resp, 'body.ext.usersync'); if (userSync) { let syncDetails = []; Object.keys(userSync).forEach(key => { diff --git a/modules/parrableIdSystem.js b/modules/parrableIdSystem.js index 04f36d0cb63..1d74061e544 100644 --- a/modules/parrableIdSystem.js +++ b/modules/parrableIdSystem.js @@ -7,13 +7,13 @@ // ci trigger: 1 -import {contains, deepClone, inIframe, isEmpty, isPlainObject, logError, logWarn, timestamp} from '../src/utils.js'; -import {find} from '../src/polyfill.js'; -import {ajax} from '../src/ajax.js'; -import {submodule} from '../src/hook.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import {uspDataHandler} from '../src/adapterManager.js'; -import {getStorageManager} from '../src/storageManager.js'; +import * as utils from '../src/utils.js' +import find from 'core-js-pure/features/array/find.js'; +import { ajax } from '../src/ajax.js'; +import { submodule } from '../src/hook.js'; +import { getRefererInfo } from '../src/refererDetection.js'; +import { uspDataHandler } from '../src/adapterManager.js'; +import { getStorageManager } from '../src/storageManager.js'; const PARRABLE_URL = 'https://h.parrable.com/prebid'; const PARRABLE_COOKIE_NAME = '_parrable_id'; @@ -23,10 +23,10 @@ const LEGACY_OPTOUT_COOKIE_NAME = '_parrable_optout'; const ONE_YEAR_MS = 364 * 24 * 60 * 60 * 1000; const EXPIRE_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:00 GMT'; -const storage = getStorageManager({gvlid: PARRABLE_GVLID}); +const storage = getStorageManager(PARRABLE_GVLID); function getExpirationDate() { - const oneYearFromNow = new Date(timestamp() + ONE_YEAR_MS); + const oneYearFromNow = new Date(utils.timestamp() + ONE_YEAR_MS); return oneYearFromNow.toGMTString(); } @@ -76,15 +76,15 @@ function serializeParrableId(parrableIdAndParams) { function isValidConfig(configParams) { if (!configParams) { - logError('User ID - parrableId submodule requires configParams'); + utils.logError('User ID - parrableId submodule requires configParams'); return false; } if (!configParams.partners && !configParams.partner) { - logError('User ID - parrableId submodule requires partner list'); + utils.logError('User ID - parrableId submodule requires partner list'); return false; } if (configParams.storage) { - logWarn('User ID - parrableId submodule does not require a storage config'); + utils.logWarn('User ID - parrableId submodule does not require a storage config'); } return true; } @@ -177,28 +177,28 @@ function shouldFilterImpression(configParams, parrableId) { } function isAllowed() { - if (isEmpty(config.allowedZones) && - isEmpty(config.allowedOffsets)) { + if (utils.isEmpty(config.allowedZones) && + utils.isEmpty(config.allowedOffsets)) { return true; } if (isZoneListed(config.allowedZones, zone)) { return true; } - if (contains(config.allowedOffsets, offset)) { + if (utils.contains(config.allowedOffsets, offset)) { return true; } return false; } function isBlocked() { - if (isEmpty(config.blockedZones) && - isEmpty(config.blockedOffsets)) { + if (utils.isEmpty(config.blockedZones) && + utils.isEmpty(config.blockedOffsets)) { return false; } if (isZoneListed(config.blockedZones, zone)) { return true; } - if (contains(config.blockedOffsets, offset)) { + if (utils.contains(config.blockedOffsets, offset)) { return true; } return false; @@ -246,7 +246,7 @@ function fetchId(configParams, gdprConsentData) { trackers, url: refererInfo.referer, prebidVersion: '$prebid.version$', - isIframe: inIframe(), + isIframe: utils.inIframe(), tpcSupport }; @@ -276,7 +276,7 @@ function fetchId(configParams, gdprConsentData) { const callback = function (cb) { const callbacks = { success: response => { - let newParrableId = parrableId ? deepClone(parrableId) : {}; + let newParrableId = parrableId ? utils.deepClone(parrableId) : {}; let newParams = {}; if (response) { try { @@ -301,18 +301,18 @@ function fetchId(configParams, gdprConsentData) { } } } catch (error) { - logError(error); + utils.logError(error); cb(); } writeCookie({ ...newParrableId, ...newParams }); cb(newParrableId); } else { - logError('parrableId: ID fetch returned an empty result'); + utils.logError('parrableId: ID fetch returned an empty result'); cb(); } }, error: error => { - logError(`parrableId: ID fetch encountered an error`, error); + utils.logError(`parrableId: ID fetch encountered an error`, error); cb(); } }; @@ -350,7 +350,7 @@ export const parrableIdSubmodule = { * @return {(Object|undefined} */ decode(parrableId) { - if (parrableId && isPlainObject(parrableId)) { + if (parrableId && utils.isPlainObject(parrableId)) { return { parrableId }; } return undefined; diff --git a/modules/permutiveRtdProvider.js b/modules/permutiveRtdProvider.js index c4674132416..40282567506 100644 --- a/modules/permutiveRtdProvider.js +++ b/modules/permutiveRtdProvider.js @@ -5,16 +5,15 @@ * @module modules/permutiveRtdProvider * @requires module:modules/realTimeData */ -import {getGlobal} from '../src/prebidGlobal.js'; -import {submodule} from '../src/hook.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {deepAccess, deepSetValue, isFn, logError, mergeDeep} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {includes} from '../src/polyfill.js'; - +import { getGlobal } from '../src/prebidGlobal.js' +import { submodule } from '../src/hook.js' +import { getStorageManager } from '../src/storageManager.js' +import { deepSetValue, deepAccess, isFn, mergeDeep, logError } from '../src/utils.js' +import { config } from '../src/config.js' +import includes from 'core-js-pure/features/array/includes.js' const MODULE_NAME = 'permutive' -export const storage = getStorageManager({gvlid: null, moduleName: MODULE_NAME}) +export const storage = getStorageManager(null, MODULE_NAME) function init (moduleConfig, userConsent) { return true @@ -70,12 +69,11 @@ export function setBidderRtb (auctionDetails, customModuleConfig) { const moduleConfig = getModuleConfig(customModuleConfig) const acBidders = deepAccess(moduleConfig, 'params.acBidders') const maxSegs = deepAccess(moduleConfig, 'params.maxSegs') - const transformationConfigs = deepAccess(moduleConfig, 'params.transformations') || [] const segmentData = getSegments(maxSegs) acBidders.forEach(function (bidder) { const currConfig = bidderConfig[bidder] || {} - const nextConfig = updateOrtbConfig(currConfig, segmentData.ac, transformationConfigs) // ORTB2 uses the `ac` segment IDs + const nextConfig = mergeOrtbConfig(currConfig, segmentData) config.setBidderConfig({ bidders: [bidder], @@ -85,33 +83,23 @@ export function setBidderRtb (auctionDetails, customModuleConfig) { } /** - * Updates `user.data` object in existing bidder config with Permutive segments + * Merges segments into existing bidder config * @param {Object} currConfig - Current bidder config - * @param {Object[]} transformationConfigs - array of objects with `id` and `config` properties, used to determine - * the transformations on user data to include the ORTB2 object - * @param {string[]} segmentIDs - Permutive segment IDs + * @param {Object} segmentData - Segment data * @return {Object} Merged ortb2 object */ -function updateOrtbConfig (currConfig, segmentIDs, transformationConfigs) { +function mergeOrtbConfig (currConfig, segmentData) { + const segment = segmentData.ac.map(seg => { + return { id: seg } + }) const name = 'permutive.com' - - const permutiveUserData = { - name, - segment: segmentIDs.map(segmentId => ({ id: segmentId })), - } - - const transformedUserData = transformationConfigs - .filter(({ id }) => ortb2UserDataTransformations.hasOwnProperty(id)) - .map(({ id, config }) => ortb2UserDataTransformations[id](permutiveUserData, config)) - const ortbConfig = mergeDeep({}, currConfig) - const currentUserData = deepAccess(ortbConfig, 'ortb2.user.data') || [] - - const updatedUserData = currentUserData + const currSegments = deepAccess(ortbConfig, 'ortb2.user.data') || [] + const userSegment = currSegments .filter(el => el.name !== name) - .concat(permutiveUserData, transformedUserData) + .concat({ name, segment }) - deepSetValue(ortbConfig, 'ortb2.user.data', updatedUserData) + deepSetValue(ortbConfig, 'ortb2.user.data', userSegment) return ortbConfig } @@ -247,11 +235,11 @@ export function getSegments (maxSegs) { ac: [..._pcrprs, ..._ppam, ...legacySegs], rubicon: readSegments('_prubicons'), appnexus: readSegments('_papns'), - gam: readSegments('_pdfps'), + gam: readSegments('_pdfps') } - for (const bidder in segments) { - segments[bidder] = segments[bidder].slice(0, maxSegs) + for (const type in segments) { + segments[type] = segments[type].slice(0, maxSegs) } return segments @@ -271,34 +259,6 @@ function readSegments (key) { } } -const unknownIabSegmentId = '_unknown_' - -/** - * Functions to apply to ORT2B2 `user.data` objects. - * Each function should return an a new object containing a `name`, (optional) `ext` and `segment` - * properties. The result of the each transformation defined here will be appended to the array - * under `user.data` in the bid request. - */ -const ortb2UserDataTransformations = { - iab: (userData, config) => ({ - name: userData.name, - ext: { segtax: config.segtax }, - segment: (userData.segment || []) - .map(segment => ({ id: iabSegmentId(segment.id, config.iabIds) })) - .filter(segment => segment.id !== unknownIabSegmentId) - }) -} - -/** - * Transform a Permutive segment ID into an IAB audience taxonomy ID. - * @param {string} permutiveSegmentId - * @param {Object} iabIds object of mappings between Permutive and IAB segment IDs (key: permutive ID, value: IAB ID) - * @return {string} IAB audience taxonomy ID associated with the Permutive segment ID - */ -function iabSegmentId(permutiveSegmentId, iabIds) { - return iabIds[permutiveSegmentId] || unknownIabSegmentId -} - /** @type {RtdSubmodule} */ export const permutiveSubmodule = { name: MODULE_NAME, diff --git a/modules/permutiveRtdProvider.md b/modules/permutiveRtdProvider.md index 5fa6e14a474..0acd42405d1 100644 --- a/modules/permutiveRtdProvider.md +++ b/modules/permutiveRtdProvider.md @@ -1,11 +1,8 @@ # Permutive Real-time Data Submodule - This submodule reads cohorts from Permutive and attaches them as targeting keys to bid requests. Using this module will deliver best targeting results, leveraging Permutive's real-time segmentation and modelling capabilities. ## Usage - Compile the Permutive RTD module into your Prebid build: - ``` gulp build --modules=rtdModule,permutiveRtdProvider ``` @@ -32,38 +29,25 @@ pbjs.setConfig({ ``` ## Supported Bidders - The Permutive RTD module sets Audience Connector cohorts as bidder-specific `ortb2.user.data` first-party data, following the Prebid `ortb2` convention, for any bidder included in `acBidders`. The module also supports bidder-specific data locations per ad unit (custom parameters) for the below bidders: -| Bidder | ID | Custom Cohorts | Audience Connector | -| ------- | ---------- | -------------- | ------------------ | -| Xandr | `appnexus` | Yes | Yes | -| Magnite | `rubicon` | Yes | No | -| Ozone | `ozone` | No | Yes | +| Bidder | ID | Custom Cohorts | Audience Connector | +| ----------- | ---------- | -------------------- | ------------------ | +| Xandr | `appnexus` | Yes | Yes | +| Magnite | `rubicon` | Yes | No | +| Ozone | `ozone` | No | Yes | Key-values details for custom parameters: +* **Custom Cohorts:** When enabling the respective Activation for a cohort in Permutive, this module will automatically attach that cohort ID to the bid request. There is no need to enable individual bidders in the module configuration, it will automatically reflect which SSP integrations you have enabled in your Permutive dashboard. Permutive cohorts will be sent in the `permutive` key-value. -- **Custom Cohorts:** When enabling the respective Activation for a cohort in Permutive, this module will automatically attach that cohort ID to the bid request. There is no need to enable individual bidders in the module configuration, it will automatically reflect which SSP integrations you have enabled in your Permutive dashboard. Permutive cohorts will be sent in the `permutive` key-value. +* **Audience Connector:** You'll need to define which bidders should receive Audience Connector cohorts. You need to include the `ID` of any bidder in the `acBidders` array. Audience Connector cohorts will be sent in the `p_standard` key-value. -- **Audience Connector:** You'll need to define which bidders should receive Audience Connector cohorts. You need to include the `ID` of any bidder in the `acBidders` array. Audience Connector cohorts will be sent in the `p_standard` key-value. ## Parameters - -| Name | Type | Description | Default | -| ---------------------- | -------- | --------------------------------------------------------------------------------------------- | ------- | -| name | String | This should always be `permutive` | - | -| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (optional) | `false` | -| params | Object | | - | -| params.acBidders | String[] | An array of bidders which should receive AC cohorts. | `[]` | -| params.maxSegs | Integer | Maximum number of cohorts to be included in either the `permutive` or `p_standard` key-value. | `500` | -| params.transformations | Object[] | An array of configurations for ORTB2 user data transformations | | - -### The `transformations` parameter - -This array contains configurations for transformations we'll apply to the Permutive object in the ORTB2 `user.data` array. The results of these transformations will be appended to the `user.data` array that's attached to ORTB2 bid requests. - -#### Supported transformations - -| Name | ID | Config structure | Description | -| -------------- | --- | ------------------------------------------------- | ------------------------------------------------------------------------------------ | -| IAB taxonomies | iab | { segtax: number, iabIds: Object} | Transform segment IDs from Permutive to IAB (note: alpha version, subject to change) | +| Name | Type | Description | Default | +| ----------------- | -------------------- | ------------------ | ------------------ | +| name | String | This should always be `permutive` | - | +| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (optional) | `false` | +| params | Object | | - | +| params.acBidders | String[] | An array of bidders which should receive AC cohorts. | `[]` | +| params.maxSegs | Integer | Maximum number of cohorts to be included in either the `permutive` or `p_standard` key-value. | `500` | diff --git a/modules/pilotxBidAdapter.js b/modules/pilotxBidAdapter.js deleted file mode 100644 index 335c461e3d9..00000000000 --- a/modules/pilotxBidAdapter.js +++ /dev/null @@ -1,147 +0,0 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -const BIDDER_CODE = 'pilotx'; -const ENDPOINT_URL = '//adn.pilotx.tv/hb' -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: ['banner', 'video'], - aliases: ['pilotx'], // short code - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function (bid) { - let sizesCheck = !!bid.sizes - let paramSizesCheck = !!bid.params.sizes - var sizeConfirmed = false - if (sizesCheck) { - if (bid.sizes.length < 1) { - return false - } else { - sizeConfirmed = true - } - } - if (paramSizesCheck) { - if (bid.params.sizes.length < 1 && !sizeConfirmed) { - return false - } else { - sizeConfirmed = true - } - } - if (!sizeConfirmed) { - return false - } - return !!(bid.params.placementId); - }, - /** - * Make a server request from the list of BidRequests. - * - * @param {validBidRequests[]} - an array of bids - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function (validBidRequests, bidderRequest) { - let payloadItems = {}; - validBidRequests.forEach(bidRequest => { - let sizes = []; - let placementId = this.setPlacementID(bidRequest.params.placementId) - payloadItems[placementId] = {} - if (bidRequest.sizes.length > 0) { - if (Array.isArray(bidRequest.sizes[0])) { - for (let i = 0; i < bidRequest.sizes.length; i++) { - sizes[i] = [(bidRequest.sizes[i])[0], (bidRequest.sizes[i])[1]] - } - } else { - sizes[0] = [bidRequest.sizes[0], bidRequest.sizes[1]] - } - payloadItems[placementId]['sizes'] = sizes - } - if (bidRequest.mediaTypes != null) { - for (let i in bidRequest.mediaTypes) { - payloadItems[placementId][i] = { - ...bidRequest.mediaTypes[i] - } - } - } - let consentTemp = '' - let consentRequiredTemp = false - if (bidderRequest && bidderRequest.gdprConsent) { - consentTemp = bidderRequest.gdprConsent.consentString - // will check if the gdprApplies field was populated with a boolean value (ie from page config). If it's undefined, then default to true - consentRequiredTemp = (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true - } - - payloadItems[placementId]['gdprConsentString'] = consentTemp - payloadItems[placementId]['gdprConsentRequired'] = consentRequiredTemp - payloadItems[placementId]['bidId'] = bidRequest.bidId - }); - const payload = payloadItems; - const payloadString = JSON.stringify(payload); - return { - method: 'POST', - url: ENDPOINT_URL, - data: payloadString, - }; - }, - /** - * Unpack the response from the server into a list of bids. - * - * @param {ServerResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function (serverResponse, bidRequest) { - const serverBody = serverResponse.body; - const bidResponses = []; - if (serverBody.mediaType == 'banner') { - const bidResponse = { - requestId: serverBody.requestId, - cpm: serverBody.cpm, - width: serverBody.width, - height: serverBody.height, - creativeId: serverBody.creativeId, - currency: serverBody.currency, - netRevenue: false, - ttl: serverBody.ttl, - ad: serverBody.ad, - mediaType: 'banner', - meta: { - mediaType: 'banner', - advertiserDomains: serverBody.advertiserDomains - } - } - bidResponses.push(bidResponse) - } else if (serverBody.mediaType == 'video') { - const bidResponse = { - requestId: serverBody.requestId, - cpm: serverBody.cpm, - width: serverBody.width, - height: serverBody.height, - creativeId: serverBody.creativeId, - currency: serverBody.currency, - netRevenue: false, - ttl: serverBody.ttl, - vastUrl: serverBody.vastUrl, - mediaType: 'video', - meta: { - mediaType: 'video', - advertiserDomains: serverBody.advertiserDomains - } - } - bidResponses.push(bidResponse) - } - - return bidResponses; - }, - - /** - * Formats placement ids for adserver ingestion purposes - * @param {string[]} The placement ID/s in an array - */ - setPlacementID: function (placementId) { - if (Array.isArray(placementId)) { - return placementId.join('#') - } - return placementId - }, -} -registerBidder(spec); diff --git a/modules/pilotxBidAdapter.md b/modules/pilotxBidAdapter.md deleted file mode 100644 index 37489bda4a0..00000000000 --- a/modules/pilotxBidAdapter.md +++ /dev/null @@ -1,50 +0,0 @@ -# Overview - -``` -Module Name: Pilotx Prebid Adapter -Module Type: Bidder Adapter -Maintainer: tony@pilotx.tv -``` - -# Description - -Connects to Pilotx - -Pilotx's bid adapter supports banner and video. - -# Test Parameters -``` -// Banner adUnit -var adUnits = [{ - code: 'div-gpt-ad-1460505748561-0', - mediaTypes: { - banner: { - sizes: [[300, 250], [300,600]], - } - }, - bids: [{ - bidder: 'pilotx', - params: { - placementId: ["1423"] - } - }] - -}]; - -// Video adUnit -var videoAdUnit = { - code: 'video1', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - } - }, - bids: [{ - bidder: 'pilotx', - params: { - placementId: '1422', - } - }] -}; -``` \ No newline at end of file diff --git a/modules/pixfutureBidAdapter.js b/modules/pixfutureBidAdapter.js index 29552ec796d..e5422f36358 100644 --- a/modules/pixfutureBidAdapter.js +++ b/modules/pixfutureBidAdapter.js @@ -1,26 +1,18 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {BANNER} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {find, includes} from '../src/polyfill.js'; -import { - convertCamelToUnderscore, - deepAccess, - isArray, - isEmpty, - isFn, - isNumber, - isPlainObject, - transformBidderParamKeywords -} from '../src/utils.js'; -import {auctionManager} from '../src/auctionManager.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { BANNER } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import * as utils from '../src/utils.js'; +import { auctionManager } from '../src/auctionManager.js'; +import find from 'core-js-pure/features/array/find.js'; const SOURCE = 'pbjs'; -const storageManager = getStorageManager({bidderCode: 'pixfuture'}); +const storageManager = getStorageManager(); const USER_PARAMS = ['age', 'externalUid', 'segments', 'gender', 'dnt', 'language']; export const spec = { code: 'pixfuture', - hostname: 'https://gosrv.pixfuture.com', + hostname: 'https://prebid-js.pixfuture.com', getHostname() { let ret = this.hostname; @@ -55,13 +47,13 @@ export const spec = { Object.keys(userObjBid.params.user) .filter(param => includes(USER_PARAMS, param)) .forEach((param) => { - let uparam = convertCamelToUnderscore(param); - if (param === 'segments' && isArray(userObjBid.params.user[param])) { + let uparam = utils.convertCamelToUnderscore(param); + if (param === 'segments' && utils.isArray(userObjBid.params.user[param])) { let segs = []; userObjBid.params.user[param].forEach(val => { - if (isNumber(val)) { + if (utils.isNumber(val)) { segs.push({'id': val}); - } else if (isPlainObject(val)) { + } else if (utils.isPlainObject(val)) { segs.push(val); } }); @@ -85,7 +77,7 @@ export const spec = { }; if (bidderRequest && bidderRequest.uspConsent) { - payload.us_privacy = bidderRequest.uspConsent; + payload.us_privacy = bidderRequest.uspConsent } if (bidderRequest && bidderRequest.refererInfo) { @@ -101,14 +93,14 @@ export const spec = { if (validBidRequests[0].userId) { let eids = []; - addUserId(eids, deepAccess(validBidRequests[0], `userId.flocId.id`), 'chrome.com', null); - addUserId(eids, deepAccess(validBidRequests[0], `userId.criteoId`), 'criteo.com', null); - addUserId(eids, deepAccess(validBidRequests[0], `userId.unifiedId`), 'thetradedesk.com', null); - addUserId(eids, deepAccess(validBidRequests[0], `userId.id5Id`), 'id5.io', null); - addUserId(eids, deepAccess(validBidRequests[0], `userId.sharedId`), 'thetradedesk.com', null); - addUserId(eids, deepAccess(validBidRequests[0], `userId.identityLink`), 'liveramp.com', null); - addUserId(eids, deepAccess(validBidRequests[0], `userId.liveIntentId`), 'liveintent.com', null); - addUserId(eids, deepAccess(validBidRequests[0], `userId.fabrickId`), 'home.neustar', null); + addUserId(eids, utils.deepAccess(validBidRequests[0], `userId.flocId.id`), 'chrome.com', null); + addUserId(eids, utils.deepAccess(validBidRequests[0], `userId.criteoId`), 'criteo.com', null); + addUserId(eids, utils.deepAccess(validBidRequests[0], `userId.unifiedId`), 'thetradedesk.com', null); + addUserId(eids, utils.deepAccess(validBidRequests[0], `userId.id5Id`), 'id5.io', null); + addUserId(eids, utils.deepAccess(validBidRequests[0], `userId.sharedId`), 'thetradedesk.com', null); + addUserId(eids, utils.deepAccess(validBidRequests[0], `userId.identityLink`), 'liveramp.com', null); + addUserId(eids, utils.deepAccess(validBidRequests[0], `userId.liveIntentId`), 'liveintent.com', null); + addUserId(eids, utils.deepAccess(validBidRequests[0], `userId.fabrickId`), 'home.neustar', null); if (eids.length) { payload.eids = eids; @@ -120,7 +112,7 @@ export const spec = { } const ret = { - url: `${hostname}/pixservices`, + url: `${hostname}/`, method: 'POST', options: {withCredentials: false}, data: { @@ -161,16 +153,6 @@ export const spec = { return bids; }, - getUserSyncs: function (syncOptions, bid, gdprConsent) { - var pixid = ''; - if (typeof bid[0] === 'undefined' || bid[0] === null) { pixid = '0'; } else { pixid = bid[0].body.pix_id; } - if (syncOptions.iframeEnabled && hasPurpose1Consent({gdprConsent})) { - return [{ - type: 'iframe', - url: 'https://gosrv.pixfuture.com/cookiesync?adsync=' + gdprConsent.consentString + '&pixid=' + pixid + '&gdprconcent=' + gdprConsent.gdprApplies - }]; - } - } }; function newBid(serverBid, rtbBid, placementId, uuid) { @@ -197,16 +179,6 @@ function newBid(serverBid, rtbBid, placementId, uuid) { return bid; } -function hasPurpose1Consent(bidderRequest) { - let result = true; - if (bidderRequest && bidderRequest.gdprConsent) { - if (bidderRequest.gdprConsent.gdprApplies && bidderRequest.gdprConsent.apiVersion === 2) { - result = !!(deepAccess(bidderRequest.gdprConsent, 'vendorData.purpose.consents.1') === true); - } - } - return result; -} - // Functions related optional parameters function bidToTag(bid) { const tag = {}; @@ -251,8 +223,8 @@ function bidToTag(bid) { if (bid.params.externalImpId) { tag.external_imp_id = bid.params.externalImpId; } - if (!isEmpty(bid.params.keywords)) { - let keywords = transformBidderParamKeywords(bid.params.keywords); + if (!utils.isEmpty(bid.params.keywords)) { + let keywords = utils.transformBidderParamKeywords(bid.params.keywords); if (keywords.length > 0) { keywords.forEach(deleteValues); @@ -260,7 +232,7 @@ function bidToTag(bid) { tag.keywords = keywords; } - let gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); + let gpid = utils.deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); if (gpid) { tag.gpid = gpid; } @@ -269,7 +241,7 @@ function bidToTag(bid) { tag.video = Object.assign({}, tag.video, {custom_renderer_present: true}); } - if (bid.params.frameworks && isArray(bid.params.frameworks)) { + if (bid.params.frameworks && utils.isArray(bid.params.frameworks)) { tag['banner_frameworks'] = bid.params.frameworks; } @@ -304,8 +276,8 @@ function transformSizes(requestSizes) { let sizes = []; let sizeObj = {}; - if (isArray(requestSizes) && requestSizes.length === 2 && - !isArray(requestSizes[0])) { + if (utils.isArray(requestSizes) && requestSizes.length === 2 && + !utils.isArray(requestSizes[0])) { sizeObj.width = parseInt(requestSizes[0], 10); sizeObj.height = parseInt(requestSizes[1], 10); sizes.push(sizeObj); @@ -323,7 +295,7 @@ function transformSizes(requestSizes) { } function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { + if (!utils.isFn(bid.getFloor)) { return (bid.params.reserve) ? bid.params.reserve : null; } @@ -332,7 +304,7 @@ function getBidFloor(bid) { mediaType: '*', size: '*' }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { + if (utils.isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { return floor.floor; } return null; @@ -345,7 +317,7 @@ function deleteValues(keyPairObj) { } function isPopulatedArray(arr) { - return !!(isArray(arr) && arr.length > 0); + return !!(utils.isArray(arr) && arr.length > 0); } registerBidder(spec); diff --git a/modules/pixfutureBidAdapter.md b/modules/pixfutureBidAdapter.md index b7911d6c9bb..e5728ededc6 100644 --- a/modules/pixfutureBidAdapter.md +++ b/modules/pixfutureBidAdapter.md @@ -25,130 +25,3 @@ var adUnits = [{ "pix_id": "Abc123" }]; ``` - -# Test Example -... - - - - - - - - - - - -

Basic Prebid.js Example

-
Div-1
-
- -
- -
- -
Div-2
-
- -
- - - - diff --git a/modules/playwireBidAdapter.md b/modules/playwireBidAdapter.md deleted file mode 100644 index dddb57c9bc1..00000000000 --- a/modules/playwireBidAdapter.md +++ /dev/null @@ -1,61 +0,0 @@ -# Overview - -Module Name: Playwire Bidder Adapter -Module Type: Bidder Adapter -Maintainer: grid-tech@themediagrid.com - -# Description - -Module that connects to Grid demand source to fetch bids. -The adapter is GDPR compliant and supports banner and video (instream and outstream). - -# Test Parameters -``` - var adUnits = [ - { - code: 'test-div', - sizes: [[300, 250]], - bids: [ - { - bidder: "playwire", - params: { - uid: '1', - bidFloor: 0.5 - } - } - ] - },{ - code: 'test-div', - sizes: [[728, 90]], - bids: [ - { - bidder: "playwire", - params: { - uid: 2, - keywords: { - brandsafety: ['disaster'], - topic: ['stress', 'fear'] - } - } - } - ] - }, - { - code: 'test-div', - sizes: [[728, 90]], - mediaTypes: { video: { - context: 'instream', - playerSize: [728, 90], - mimes: ['video/mp4'] - }, - bids: [ - { - bidder: "playwire", - params: { - uid: 11 - } - } - ] - } - ]; -``` diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 8279da13054..246127e443d 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -1,44 +1,18 @@ import Adapter from '../../src/adapter.js'; -import {createBid} from '../../src/bidfactory.js'; -import { - bind, - cleanObj, - createTrackPixelHtml, - deepAccess, - deepClone, - deepSetValue, - flatten, - generateUUID, - getBidRequest, - getDefinedParams, - getPrebidInternal, - insertUserSyncIframe, - isArray, - isEmpty, - isNumber, - isPlainObject, - isStr, - logError, - logInfo, - logMessage, - logWarn, - mergeDeep, - parseSizesInput, - pick, timestamp, - triggerPixel, - uniques -} from '../../src/utils.js'; +import { createBid } from '../../src/bidfactory.js'; +import * as utils from '../../src/utils.js'; import CONSTANTS from '../../src/constants.json'; import adapterManager from '../../src/adapterManager.js'; import { config } from '../../src/config.js'; import { VIDEO, NATIVE } from '../../src/mediaTypes.js'; +import { processNativeAdUnitParams } from '../../src/native.js'; import { isValid } from '../../src/adapters/bidderFactory.js'; -import * as events from '../../src/events.js'; -import {find, includes} from '../../src/polyfill.js'; +import events from '../../src/events.js'; +import includes from 'core-js-pure/features/array/includes.js'; import { S2S_VENDORS } from './config.js'; import { ajax } from '../../src/ajax.js'; -import {hook} from '../../src/hook.js'; -import {getGlobal} from '../../src/prebidGlobal.js'; +import find from 'core-js-pure/features/array/find.js'; +import { getPrebidInternal } from '../../src/utils.js'; const getConfig = config.getConfig; @@ -76,10 +50,8 @@ let eidPermissions; * @typedef {Object} S2SDefaultConfig * @summary Base config properties for server to server header bidding * @property {string} [adapter='prebidServer'] adapter code to use for S2S - * @property {boolean} [allowUnknownBidderCodes=false] allow bids from bidders that were not explicitly requested * @property {boolean} [enabled=false] enables S2S bidding * @property {number} [timeout=1000] timeout for S2S bidders - should be lower than `pbjs.requestBids({timeout})` - * @property {number} [syncTimeout=1000] timeout for cookie sync iframe / image rendering * @property {number} [maxBids=1] * @property {AdapterOptions} [adapterOptions] adds arguments to resulting OpenRTB payload to Prebid Server * @property {Object} [syncUrlModifier] @@ -100,12 +72,9 @@ let eidPermissions; * @type {S2SDefaultConfig} */ const s2sDefaultConfig = { - bidders: Object.freeze([]), timeout: 1000, - syncTimeout: 1000, maxBids: 1, adapter: 'prebidServer', - allowUnknownBidderCodes: false, adapterOptions: {}, syncUrlModifier: {} }; @@ -131,7 +100,7 @@ function updateConfigDefaultVendor(option) { } }); } else { - logError('Incorrect or unavailable prebid server default vendor option: ' + vendor); + utils.logError('Incorrect or unavailable prebid server default vendor option: ' + vendor); return false; } } @@ -145,9 +114,9 @@ function updateConfigDefaultVendor(option) { */ function validateConfigRequiredProps(option) { const keys = Object.keys(option); - if (['accountId', 'endpoint'].filter(key => { + if (['accountId', 'bidders', 'endpoint'].filter(key => { if (!includes(keys, key)) { - logError(key + ' missing in server to server config'); + utils.logError(key + ' missing in server to server config'); return true; } return false; @@ -160,14 +129,14 @@ function validateConfigRequiredProps(option) { // could be removed later as part of a major release, if we decide to not support the old format function formatUrlParams(option) { ['endpoint', 'syncEndpoint'].forEach((prop) => { - if (isStr(option[prop])) { + if (utils.isStr(option[prop])) { let temp = option[prop]; option[prop] = { p1Consent: temp, noP1Consent: temp }; } - if (isPlainObject(option[prop]) && (!option[prop].p1Consent || !option[prop].noP1Consent)) { + if (utils.isPlainObject(option[prop]) && (!option[prop].p1Consent || !option[prop].noP1Consent)) { ['p1Consent', 'noP1Consent'].forEach((conUrl) => { if (!option[prop][conUrl]) { - logWarn(`s2sConfig.${prop}.${conUrl} not defined. PBS request will be skipped in some P1 scenarios.`); + utils.logWarn(`s2sConfig.${prop}.${conUrl} not defined. PBS request will be skipped in some P1 scenarios.`); } }); } @@ -202,7 +171,7 @@ function setS2sConfig(options) { return true; } } - logWarn('prebidServer: s2s config is disabled'); + utils.logWarn('prebidServer: s2s config is disabled'); return false; }); @@ -229,13 +198,13 @@ function queueSync(bidderCodes, gdprConsent, uspConsent, s2sConfig) { _syncCount++; const payload = { - uuid: generateUUID(), + uuid: utils.generateUUID(), bidders: bidderCodes, account: s2sConfig.accountId }; let userSyncLimit = s2sConfig.userSyncLimit; - if (isNumber(userSyncLimit) && userSyncLimit > 0) { + if (utils.isNumber(userSyncLimit) && userSyncLimit > 0) { payload['limit'] = userSyncLimit; } @@ -263,7 +232,7 @@ function queueSync(bidderCodes, gdprConsent, uspConsent, s2sConfig) { response = JSON.parse(response); doAllSyncs(response.bidder_status, s2sConfig); } catch (e) { - logError(e); + utils.logError(e); } }, jsonPayload, @@ -283,7 +252,7 @@ function doAllSyncs(bidders, s2sConfig) { // if PBS reports this bidder doesn't have an ID, then call the sync and recurse to the next sync entry if (thisSync.no_cookie) { - doPreBidderSync(thisSync.usersync.type, thisSync.usersync.url, thisSync.bidder, bind.call(doAllSyncs, null, bidders, s2sConfig), s2sConfig); + doPreBidderSync(thisSync.usersync.type, thisSync.usersync.url, thisSync.bidder, utils.bind.call(doAllSyncs, null, bidders, s2sConfig), s2sConfig); } else { // bidder already has an ID, so just recurse to the next sync entry doAllSyncs(bidders, s2sConfig); @@ -301,9 +270,11 @@ function doAllSyncs(bidders, s2sConfig) { */ function doPreBidderSync(type, url, bidder, done, s2sConfig) { if (s2sConfig.syncUrlModifier && typeof s2sConfig.syncUrlModifier[bidder] === 'function') { - url = s2sConfig.syncUrlModifier[bidder](type, url, bidder); + const newSyncUrl = s2sConfig.syncUrlModifier[bidder](type, url, bidder); + doBidderSync(type, newSyncUrl, bidder, done) + } else { + doBidderSync(type, url, bidder, done) } - doBidderSync(type, url, bidder, done, s2sConfig.syncTimeout) } /** @@ -313,20 +284,19 @@ function doPreBidderSync(type, url, bidder, done, s2sConfig) { * @param {string} url the url to sync * @param {string} bidder name of bidder doing sync for * @param {function} done an exit callback; to signify this pixel has either: finished rendering or something went wrong - * @param {number} timeout: maximum time to wait for rendering in milliseconds */ -function doBidderSync(type, url, bidder, done, timeout) { +function doBidderSync(type, url, bidder, done) { if (!url) { - logError(`No sync url for bidder "${bidder}": ${url}`); + utils.logError(`No sync url for bidder "${bidder}": ${url}`); done(); } else if (type === 'image' || type === 'redirect') { - logMessage(`Invoking image pixel user sync for bidder: "${bidder}"`); - triggerPixel(url, done, timeout); - } else if (type === 'iframe') { - logMessage(`Invoking iframe user sync for bidder: "${bidder}"`); - insertUserSyncIframe(url, done, timeout); + utils.logMessage(`Invoking image pixel user sync for bidder: "${bidder}"`); + utils.triggerPixel(url, done); + } else if (type == 'iframe') { + utils.logMessage(`Invoking iframe user sync for bidder: "${bidder}"`); + utils.insertUserSyncIframe(url, done); } else { - logError(`User sync type "${type}" not supported for bidder: "${bidder}"`); + utils.logError(`User sync type "${type}" not supported for bidder: "${bidder}"`); done(); } } @@ -342,7 +312,7 @@ function doClientSideSyncs(bidders, gdprConsent, uspConsent) { if (clientAdapter && clientAdapter.registerSyncs) { config.runWithBidder( bidder, - bind.call( + utils.bind.call( clientAdapter.registerSyncs, clientAdapter, [], @@ -363,12 +333,12 @@ function _appendSiteAppDevice(request, pageUrl, accountId) { request.app.publisher = {id: accountId} } else { request.site = {}; - if (isPlainObject(config.getConfig('site'))) { + if (utils.isPlainObject(config.getConfig('site'))) { request.site = config.getConfig('site'); } // set publisher.id if not already defined - if (!deepAccess(request.site, 'publisher.id')) { - deepSetValue(request.site, 'publisher.id', accountId); + if (!utils.deepAccess(request.site, 'publisher.id')) { + utils.deepSetValue(request.site, 'publisher.id', accountId); } // set site.page if not already defined if (!request.site.page) { @@ -394,7 +364,13 @@ function addBidderFirstPartyDataToRequest(request) { const fpdConfigs = Object.keys(bidderConfig).reduce((acc, bidder) => { const currBidderConfig = bidderConfig[bidder]; if (currBidderConfig.ortb2) { - const ortb2 = mergeDeep({}, currBidderConfig.ortb2); + const ortb2 = {}; + if (currBidderConfig.ortb2.site) { + ortb2.site = currBidderConfig.ortb2.site; + } + if (currBidderConfig.ortb2.user) { + ortb2.user = currBidderConfig.ortb2.user; + } acc.push({ bidders: [ bidder ], @@ -405,7 +381,7 @@ function addBidderFirstPartyDataToRequest(request) { }, []); if (fpdConfigs.length) { - deepSetValue(request, 'ext.prebid.bidderconfig', fpdConfigs); + utils.deepSetValue(request, 'ext.prebid.bidderconfig', fpdConfigs); } } @@ -458,6 +434,7 @@ let nativeEventTrackerMethodMap = { * Protocol spec for OpenRTB endpoint * e.g., https:///v1/openrtb2/auction */ +let bidIdMap = {}; let nativeAssetCache = {}; // store processed native params to preserve /** @@ -471,13 +448,13 @@ let wurlMap = {}; * @param {string} wurl events.winurl passed from prebidServer as wurl */ function addWurl(auctionId, adId, wurl) { - if ([auctionId, adId].every(isStr)) { + if ([auctionId, adId].every(utils.isStr)) { wurlMap[`${auctionId}${adId}`] = wurl; } } function getPbsResponseData(bidderRequests, response, pbsName, pbjsName) { - const bidderValues = deepAccess(response, `ext.${pbsName}`); + const bidderValues = utils.deepAccess(response, `ext.${pbsName}`); if (bidderValues) { Object.keys(bidderValues).forEach(bidder => { let biddersReq = find(bidderRequests, bidderReq => bidderReq.bidderCode === bidder); @@ -493,7 +470,7 @@ function getPbsResponseData(bidderRequests, response, pbsName, pbjsName) { * @param {string} adId generated value set to bidObject.adId by bidderFactory Bid() */ function removeWurl(auctionId, adId) { - if ([auctionId, adId].every(isStr)) { + if ([auctionId, adId].every(utils.isStr)) { wurlMap[`${auctionId}${adId}`] = undefined; } } @@ -503,7 +480,7 @@ function removeWurl(auctionId, adId) { * @return {(string|undefined)} events.winurl which was passed as wurl */ function getWurl(auctionId, adId) { - if ([auctionId, adId].every(isStr)) { + if ([auctionId, adId].every(utils.isStr)) { return wurlMap[`${auctionId}${adId}`]; } } @@ -515,24 +492,8 @@ export function resetWurlMap() { wurlMap = {}; } -function ORTB2(s2sBidRequest, bidderRequests, adUnits, requestedBidders) { - this.s2sBidRequest = s2sBidRequest; - this.bidderRequests = bidderRequests; - this.adUnits = adUnits; - this.s2sConfig = s2sBidRequest.s2sConfig; - this.requestedBidders = requestedBidders; - - this.bidIdMap = {}; - this.adUnitsByImp = {}; - this.impRequested = {}; - this.auctionId = bidderRequests.map(br => br.auctionId).reduce((l, r) => (l == null || l === r) && r); - this.requestTimestamp = timestamp(); -} - -Object.assign(ORTB2.prototype, { - buildRequest() { - const {s2sBidRequest, bidderRequests: bidRequests, adUnits, s2sConfig, requestedBidders} = this; - +const OPEN_RTB_PROTOCOL = { + buildRequest(s2sBidRequest, bidRequests, adUnits, s2sConfig, requestedBidders) { let imps = []; let aliases = {}; const firstBidRequest = bidRequests[0]; @@ -540,14 +501,6 @@ Object.assign(ORTB2.prototype, { // transform ad unit into array of OpenRTB impression objects let impIds = new Set(); adUnits.forEach(adUnit => { - // TODO: support labels / conditional bids - // for now, just warn about them - adUnit.bids.forEach((bid) => { - if (bid.mediaTypes != null) { - logWarn(`Prebid Server adapter does not (yet) support bidder-specific mediaTypes for the same adUnit. Size mapping configuration will be ignored for adUnit: ${adUnit.code}, bidder: ${bid.bidder}`); - } - }) - // in case there is a duplicate imp.id, add '-2' suffix to the second imp.id. // e.g. if there are 2 adUnits (case of twin adUnit codes) with code 'test', // first imp will have id 'test' and second imp will have id 'test-2' @@ -558,47 +511,40 @@ Object.assign(ORTB2.prototype, { impressionId = `${adUnit.code}-${i}`; } impIds.add(impressionId); - this.adUnitsByImp[impressionId] = adUnit; - const nativeParams = adUnit.nativeParams; + const nativeParams = processNativeAdUnitParams(utils.deepAccess(adUnit, 'mediaTypes.native')); let nativeAssets; if (nativeParams) { - let idCounter = -1; try { nativeAssets = nativeAssetCache[impressionId] = Object.keys(nativeParams).reduce((assets, type) => { let params = nativeParams[type]; function newAsset(obj) { - idCounter++; return Object.assign({ - required: params.required ? 1 : 0, - id: (isNumber(params.id)) ? idCounter = params.id : idCounter - }, obj ? cleanObj(obj) : {}); + required: params.required ? 1 : 0 + }, obj ? utils.cleanObj(obj) : {}); } switch (type) { case 'image': case 'icon': let imgTypeId = nativeImgIdMap[type]; - let asset = cleanObj({ + let asset = utils.cleanObj({ type: imgTypeId, - w: deepAccess(params, 'sizes.0'), - h: deepAccess(params, 'sizes.1'), - wmin: deepAccess(params, 'aspect_ratios.0.min_width'), - hmin: deepAccess(params, 'aspect_ratios.0.min_height') + w: utils.deepAccess(params, 'sizes.0'), + h: utils.deepAccess(params, 'sizes.1'), + wmin: utils.deepAccess(params, 'aspect_ratios.0.min_width'), + hmin: utils.deepAccess(params, 'aspect_ratios.0.min_height') }); if (!((asset.w && asset.h) || (asset.hmin && asset.wmin))) { throw 'invalid img sizes (must provide sizes or min_height & min_width if using aspect_ratios)'; } if (Array.isArray(params.aspect_ratios)) { // pass aspect_ratios as ext data I guess? - const aspectRatios = params.aspect_ratios - .filter((ar) => ar.ratio_width && ar.ratio_height) - .map(ratio => `${ratio.ratio_width}:${ratio.ratio_height}`); - if (aspectRatios.length > 0) { - asset.ext = { - aspectratios: aspectRatios - } + asset.ext = { + aspectratios: params.aspect_ratios.map( + ratio => `${ratio.ratio_width}:${ratio.ratio_height}` + ) } } assets.push(newAsset({ @@ -629,14 +575,16 @@ Object.assign(ORTB2.prototype, { return assets; }, []); } catch (e) { - logError('error creating native request: ' + String(e)) + utils.logError('error creating native request: ' + String(e)) } } - const videoParams = deepAccess(adUnit, 'mediaTypes.video'); - const bannerParams = deepAccess(adUnit, 'mediaTypes.banner'); + const videoParams = utils.deepAccess(adUnit, 'mediaTypes.video'); + const bannerParams = utils.deepAccess(adUnit, 'mediaTypes.banner'); adUnit.bids.forEach(bid => { - this.setBidRequestId(impressionId, bid.bidder, bid.bid_id); + // OpenRTB response contains imp.id and bidder name. These are + // combined to create a unique key for each bid since an id isn't returned + bidIdMap[`${impressionId}${bid.bidder}`] = bid.bid_id; // check for and store valid aliases to add to the request if (adapterManager.aliasRegistry[bid.bidder]) { const bidder = adapterManager.bidderRegistry[bid.bidder]; @@ -650,7 +598,7 @@ Object.assign(ORTB2.prototype, { let mediaTypes = {}; if (bannerParams && bannerParams.sizes) { - const sizes = parseSizesInput(bannerParams.sizes); + const sizes = utils.parseSizesInput(bannerParams.sizes); // get banner sizes in form [{ w: , h: }, ...] const format = sizes.map(size => { @@ -665,10 +613,10 @@ Object.assign(ORTB2.prototype, { if (bannerParams.pos) mediaTypes['banner'].pos = bannerParams.pos; } - if (!isEmpty(videoParams)) { + if (!utils.isEmpty(videoParams)) { if (videoParams.context === 'outstream' && !videoParams.renderer && !adUnit.renderer) { // Don't push oustream w/o renderer to request object. - logError('Outstream bid without renderer cannot be sent to Prebid Server.'); + utils.logError('Outstream bid without renderer cannot be sent to Prebid Server.'); } else { if (videoParams.context === 'instream' && !videoParams.hasOwnProperty('placement')) { videoParams.placement = 1; @@ -677,8 +625,8 @@ Object.assign(ORTB2.prototype, { mediaTypes['video'] = Object.keys(videoParams).filter(param => param !== 'context') .reduce((result, param) => { if (param === 'playerSize') { - result.w = deepAccess(videoParams, `${param}.0.0`); - result.h = deepAccess(videoParams, `${param}.0.1`); + result.w = utils.deepAccess(videoParams, `${param}.0.0`); + result.h = utils.deepAccess(videoParams, `${param}.0.1`); } else { result[param] = videoParams[param]; } @@ -704,25 +652,24 @@ Object.assign(ORTB2.prototype, { ver: '1.2' } } catch (e) { - logError('error creating native request: ' + String(e)) + utils.logError('error creating native request: ' + String(e)) } } // get bidder params in form { : {...params} } // initialize reduce function with the user defined `ext` properties on the ad unit const ext = adUnit.bids.reduce((acc, bid) => { - if (bid.bidder == null) return acc; const adapter = adapterManager.bidderRegistry[bid.bidder]; if (adapter && adapter.getSpec().transformBidParams) { bid.params = adapter.getSpec().transformBidParams(bid.params, true, adUnit, bidRequests); } acc[bid.bidder] = (s2sConfig.adapterOptions && s2sConfig.adapterOptions[bid.bidder]) ? Object.assign({}, bid.params, s2sConfig.adapterOptions[bid.bidder]) : bid.params; return acc; - }, {...deepAccess(adUnit, 'ortb2Imp.ext')}); + }, {...utils.deepAccess(adUnit, 'ortb2Imp.ext')}); - const imp = { ...adUnit.ortb2Imp, id: impressionId, ext, secure: s2sConfig.secure }; + const imp = { id: impressionId, ext, secure: s2sConfig.secure }; - const ortb2 = {...deepAccess(adUnit, 'ortb2Imp.ext.data')}; + const ortb2 = {...utils.deepAccess(adUnit, 'ortb2Imp.ext.data')}; Object.keys(ortb2).forEach(prop => { /** * Prebid AdSlot @@ -730,7 +677,7 @@ Object.assign(ORTB2.prototype, { */ if (prop === 'pbadslot') { if (typeof ortb2[prop] === 'string' && ortb2[prop]) { - deepSetValue(imp, 'ext.data.pbadslot', ortb2[prop]); + utils.deepSetValue(imp, 'ext.data.pbadslot', ortb2[prop]); } else { // remove pbadslot property if it doesn't meet the spec delete imp.ext.data.pbadslot; @@ -741,82 +688,39 @@ Object.assign(ORTB2.prototype, { */ ['name', 'adslot'].forEach(name => { /** @type {(string|undefined)} */ - const value = deepAccess(ortb2, `adserver.${name}`); + const value = utils.deepAccess(ortb2, `adserver.${name}`); if (typeof value === 'string' && value) { - deepSetValue(imp, `ext.data.adserver.${name.toLowerCase()}`, value); + utils.deepSetValue(imp, `ext.data.adserver.${name.toLowerCase()}`, value); } }); } else { - deepSetValue(imp, `ext.data.${prop}`, ortb2[prop]); + utils.deepSetValue(imp, `ext.data.${prop}`, ortb2[prop]); } }); - mergeDeep(imp, mediaTypes); + Object.assign(imp, mediaTypes); // if storedAuctionResponse has been set, pass SRID const storedAuctionResponseBid = find(firstBidRequest.bids, bid => (bid.adUnitCode === adUnit.code && bid.storedAuctionResponse)); if (storedAuctionResponseBid) { - deepSetValue(imp, 'ext.prebid.storedauctionresponse.id', storedAuctionResponseBid.storedAuctionResponse.toString()); + utils.deepSetValue(imp, 'ext.prebid.storedauctionresponse.id', storedAuctionResponseBid.storedAuctionResponse.toString()); } - const floor = (() => { - // we have to pick a floor for the imp - here we attempt to find the minimum floor - // across all bids for this adUnit - - const convertCurrency = typeof getGlobal().convertCurrency !== 'function' - ? (amount) => amount - : (amount, from, to) => { - if (from === to) return amount; - let result = null; - try { - result = getGlobal().convertCurrency(amount, from, to); - } catch (e) { - } - return result; - } - const s2sCurrency = config.getConfig('currency.adServerCurrency') || DEFAULT_S2S_CURRENCY; - - return adUnit.bids - .map((bid) => this.getBidRequest(imp.id, bid.bidder)) - .map((bid) => { - if (!bid || typeof bid.getFloor !== 'function') return; - try { - const {currency, floor} = bid.getFloor({ - currency: s2sCurrency - }); - return { - currency, - floor: parseFloat(floor) - } - } catch (e) { - logError('PBS: getFloor threw an error: ', e); - } - }) - .reduce((min, floor) => { - // if any bid does not have a valid floor, do not attempt to send any to PBS - if (floor == null || floor.currency == null || floor.floor == null || isNaN(floor.floor)) { - min.min = null; - } - if (min.min === null) { - return min; - } - // otherwise, pick the minimum one (or, in some strange confluence of circumstances, the one in the best currency) - if (min.ref == null) { - min.ref = min.min = floor; - } else { - const value = convertCurrency(floor.floor, floor.currency, min.ref.currency); - if (value != null && value < min.ref.floor) { - min.ref.floor = value; - min.min = floor; - } - } - return min; - }, {}).min - })(); + const getFloorBid = find(firstBidRequest.bids, bid => bid.adUnitCode === adUnit.code && typeof bid.getFloor === 'function'); - if (floor) { - imp.bidfloor = floor.floor; - imp.bidfloorcur = floor.currency + if (getFloorBid) { + let floorInfo; + try { + floorInfo = getFloorBid.getFloor({ + currency: config.getConfig('currency.adServerCurrency') || DEFAULT_S2S_CURRENCY, + }); + } catch (e) { + utils.logError('PBS: getFloor threw an error: ', e); + } + if (floorInfo && floorInfo.currency && !isNaN(parseFloat(floorInfo.floor))) { + imp.bidfloor = parseFloat(floorInfo.floor); + imp.bidfloorcur = floorInfo.currency + } } if (imp.banner || imp.video || imp.native) { @@ -825,11 +729,11 @@ Object.assign(ORTB2.prototype, { }); if (!imps.length) { - logError('Request to Prebid Server rejected due to invalid media type(s) in adUnit.'); + utils.logError('Request to Prebid Server rejected due to invalid media type(s) in adUnit.'); return; } const request = { - id: firstBidRequest.auctionId, + id: s2sBidRequest.tid, source: {tid: s2sBidRequest.tid}, tmax: s2sConfig.timeout, imp: imps, @@ -849,7 +753,7 @@ Object.assign(ORTB2.prototype, { } }; - // This is no longer overwritten unless name and version explicitly overwritten by extPrebid (mergeDeep) + // Sets pbjs version, can be overwritten below if channel exists in s2sConfig.extPrebid request.ext.prebid = Object.assign(request.ext.prebid, {channel: {name: 'pbjs', version: $$PREBID_GLOBAL$$.version}}) // set debug flag if in debug mode @@ -859,7 +763,7 @@ Object.assign(ORTB2.prototype, { // s2sConfig video.ext.prebid is passed through openrtb to PBS if (s2sConfig.extPrebid && typeof s2sConfig.extPrebid === 'object') { - request.ext.prebid = mergeDeep(request.ext.prebid, s2sConfig.extPrebid); + request.ext.prebid = Object.assign(request.ext.prebid, s2sConfig.extPrebid); } /** @@ -877,36 +781,36 @@ Object.assign(ORTB2.prototype, { _appendSiteAppDevice(request, bidRequests[0].refererInfo.referer, s2sConfig.accountId); // pass schain object if it is present - const schain = deepAccess(bidRequests, '0.bids.0.schain'); + const schain = utils.deepAccess(bidRequests, '0.bids.0.schain'); if (schain) { request.source.ext = { schain: schain }; } - if (!isEmpty(aliases)) { + if (!utils.isEmpty(aliases)) { request.ext.prebid.aliases = {...request.ext.prebid.aliases, ...aliases}; } - const bidUserIdAsEids = deepAccess(bidRequests, '0.bids.0.userIdAsEids'); - if (isArray(bidUserIdAsEids) && bidUserIdAsEids.length > 0) { - deepSetValue(request, 'user.ext.eids', bidUserIdAsEids); + const bidUserIdAsEids = utils.deepAccess(bidRequests, '0.bids.0.userIdAsEids'); + if (utils.isArray(bidUserIdAsEids) && bidUserIdAsEids.length > 0) { + utils.deepSetValue(request, 'user.ext.eids', bidUserIdAsEids); } - if (isArray(eidPermissions) && eidPermissions.length > 0) { - if (requestedBidders && isArray(requestedBidders)) { + if (utils.isArray(eidPermissions) && eidPermissions.length > 0) { + if (requestedBidders && utils.isArray(requestedBidders)) { eidPermissions.forEach(i => { if (i.bidders) { - i.bidders = i.bidders.filter(bidder => includes(requestedBidders, bidder)) + i.bidders = i.bidders.filter(bidder => requestedBidders.includes(bidder)) } }); } - deepSetValue(request, 'ext.prebid.data.eidpermissions', eidPermissions); + utils.deepSetValue(request, 'ext.prebid.data.eidpermissions', eidPermissions); } const multibid = config.getConfig('multibid'); if (multibid) { - deepSetValue(request, 'ext.prebid.multibid', multibid.reduce((result, i) => { + utils.deepSetValue(request, 'ext.prebid.multibid', multibid.reduce((result, i) => { let obj = {}; Object.keys(i).forEach(key => { @@ -926,34 +830,36 @@ Object.assign(ORTB2.prototype, { if (typeof firstBidRequest.gdprConsent.gdprApplies === 'boolean') { gdprApplies = firstBidRequest.gdprConsent.gdprApplies ? 1 : 0; } - deepSetValue(request, 'regs.ext.gdpr', gdprApplies); - deepSetValue(request, 'user.ext.consent', firstBidRequest.gdprConsent.consentString); + utils.deepSetValue(request, 'regs.ext.gdpr', gdprApplies); + utils.deepSetValue(request, 'user.ext.consent', firstBidRequest.gdprConsent.consentString); if (firstBidRequest.gdprConsent.addtlConsent && typeof firstBidRequest.gdprConsent.addtlConsent === 'string') { - deepSetValue(request, 'user.ext.ConsentedProvidersSettings.consented_providers', firstBidRequest.gdprConsent.addtlConsent); + utils.deepSetValue(request, 'user.ext.ConsentedProvidersSettings.consented_providers', firstBidRequest.gdprConsent.addtlConsent); } } // US Privacy (CCPA) support if (firstBidRequest.uspConsent) { - deepSetValue(request, 'regs.ext.us_privacy', firstBidRequest.uspConsent); + utils.deepSetValue(request, 'regs.ext.us_privacy', firstBidRequest.uspConsent); } } if (getConfig('coppa') === true) { - deepSetValue(request, 'regs.coppa', 1); + utils.deepSetValue(request, 'regs.coppa', 1); } const commonFpd = getConfig('ortb2') || {}; - mergeDeep(request, commonFpd); - + if (commonFpd.site) { + utils.mergeDeep(request, {site: commonFpd.site}); + } + if (commonFpd.user) { + utils.mergeDeep(request, {user: commonFpd.user}); + } addBidderFirstPartyDataToRequest(request); - request.imp.forEach((imp) => this.impRequested[imp.id] = imp); return request; }, - interpretResponse(response) { - const {bidderRequests, s2sConfig} = this; + interpretResponse(response, bidderRequests, s2sConfig) { const bids = []; [['errors', 'serverErrors'], ['responsetimemillis', 'serverResponseTimeMs']] @@ -963,56 +869,51 @@ Object.assign(ORTB2.prototype, { // a seatbid object contains a `bid` array and a `seat` string response.seatbid.forEach(seatbid => { (seatbid.bid || []).forEach(bid => { - let bidRequest = this.getBidRequest(bid.impid, seatbid.seat); - if (bidRequest == null) { - if (!s2sConfig.allowUnknownBidderCodes) { - logWarn(`PBS adapter received bid from unknown bidder (${seatbid.seat}), but 's2sConfig.allowUnknownBidderCodes' is not set. Ignoring bid.`); - return; - } - // for stored impression, a request was made with bidder code `null`. Pick it up here so that NO_BID, BID_WON, etc events - // can work as expected (otherwise, the original request will always result in NO_BID). - bidRequest = this.getBidRequest(bid.impid, null); + let bidRequest; + let key = `${bid.impid}${seatbid.seat}`; + if (bidIdMap[key]) { + bidRequest = utils.getBidRequest( + bidIdMap[key], + bidderRequests + ); } const cpm = bid.price; const status = cpm !== 0 ? CONSTANTS.STATUS.GOOD : CONSTANTS.STATUS.NO_BID; - let bidObject = createBid(status, { + let bidObject = createBid(status, bidRequest || { bidder: seatbid.seat, - src: TYPE, - bidId: bidRequest ? (bidRequest.bidId || bidRequest.bid_Id) : null, - transactionId: this.adUnitsByImp[bid.impid].transactionId, - auctionId: this.auctionId, + src: TYPE }); - bidObject.requestTimestamp = this.requestTimestamp; + bidObject.cpm = cpm; // temporarily leaving attaching it to each bidResponse so no breaking change // BUT: this is a flat map, so it should be only attached to bidderRequest, a the change above does - let serverResponseTimeMs = deepAccess(response, ['ext', 'responsetimemillis', seatbid.seat].join('.')); + let serverResponseTimeMs = utils.deepAccess(response, ['ext', 'responsetimemillis', seatbid.seat].join('.')); if (bidRequest && serverResponseTimeMs) { bidRequest.serverResponseTimeMs = serverResponseTimeMs; } // Look for seatbid[].bid[].ext.prebid.bidid and place it in the bidResponse object for use in analytics adapters as 'pbsBidId' - const bidId = deepAccess(bid, 'ext.prebid.bidid'); - if (isStr(bidId)) { + const bidId = utils.deepAccess(bid, 'ext.prebid.bidid'); + if (utils.isStr(bidId)) { bidObject.pbsBidId = bidId; } // store wurl by auctionId and adId so it can be accessed from the BID_WON event handler - if (isStr(deepAccess(bid, 'ext.prebid.events.win'))) { - addWurl(this.auctionId, bidObject.adId, deepAccess(bid, 'ext.prebid.events.win')); + if (utils.isStr(utils.deepAccess(bid, 'ext.prebid.events.win'))) { + addWurl(bidRequest.auctionId, bidObject.adId, utils.deepAccess(bid, 'ext.prebid.events.win')); } - let extPrebidTargeting = deepAccess(bid, 'ext.prebid.targeting'); + let extPrebidTargeting = utils.deepAccess(bid, 'ext.prebid.targeting'); // If ext.prebid.targeting exists, add it as a property value named 'adserverTargeting' // The removal of hb_winurl and hb_bidid targeting values is temporary // once we get through the transition, this block will be removed. - if (isPlainObject(extPrebidTargeting)) { + if (utils.isPlainObject(extPrebidTargeting)) { // If wurl exists, remove hb_winurl and hb_bidid targeting attributes - if (isStr(deepAccess(bid, 'ext.prebid.events.win'))) { - extPrebidTargeting = getDefinedParams(extPrebidTargeting, Object.keys(extPrebidTargeting) + if (utils.isStr(utils.deepAccess(bid, 'ext.prebid.events.win'))) { + extPrebidTargeting = utils.getDefinedParams(extPrebidTargeting, Object.keys(extPrebidTargeting) .filter(i => (i.indexOf('hb_winurl') === -1 && i.indexOf('hb_bidid') === -1))); } bidObject.adserverTargeting = extPrebidTargeting; @@ -1020,10 +921,11 @@ Object.assign(ORTB2.prototype, { bidObject.seatBidId = bid.id; - if (deepAccess(bid, 'ext.prebid.type') === VIDEO) { + if (utils.deepAccess(bid, 'ext.prebid.type') === VIDEO) { bidObject.mediaType = VIDEO; - const impReq = this.impRequested[bid.impid]; - [bidObject.playerWidth, bidObject.playerHeight] = [impReq.video.w, impReq.video.h]; + let sizes = bidRequest.sizes && bidRequest.sizes[0]; + bidObject.playerWidth = sizes[0]; + bidObject.playerHeight = sizes[1]; // try to get cache values from 'response.ext.prebid.cache.js' // else try 'bid.ext.prebid.targeting' as fallback @@ -1038,7 +940,7 @@ Object.assign(ORTB2.prototype, { if (bid.adm) { bidObject.vastXml = bid.adm; } if (!bidObject.vastUrl && bid.nurl) { bidObject.vastUrl = bid.nurl; } - } else if (deepAccess(bid, 'ext.prebid.type') === NATIVE) { + } else if (utils.deepAccess(bid, 'ext.prebid.type') === NATIVE) { bidObject.mediaType = NATIVE; let adm; if (typeof bid.adm === 'string') { @@ -1064,18 +966,18 @@ Object.assign(ORTB2.prototype, { }); } - if (isPlainObject(adm) && Array.isArray(adm.assets)) { + if (utils.isPlainObject(adm) && Array.isArray(adm.assets)) { let origAssets = nativeAssetCache[bid.impid]; - bidObject.native = cleanObj(adm.assets.reduce((native, asset) => { + bidObject.native = utils.cleanObj(adm.assets.reduce((native, asset) => { let origAsset = origAssets[asset.id]; - if (isPlainObject(asset.img)) { - native[origAsset.img.type ? nativeImgIdMap[origAsset.img.type] : 'image'] = pick( + if (utils.isPlainObject(asset.img)) { + native[origAsset.img.type ? nativeImgIdMap[origAsset.img.type] : 'image'] = utils.pick( asset.img, ['url', 'w as width', 'h as height'] ); - } else if (isPlainObject(asset.title)) { + } else if (utils.isPlainObject(asset.title)) { native['title'] = asset.title.text - } else if (isPlainObject(asset.data)) { + } else if (utils.isPlainObject(asset.data)) { nativeDataNames.forEach(dataType => { if (nativeDataIdMap[dataType] === origAsset.data.type) { native[dataType] = asset.data.value; @@ -1083,19 +985,19 @@ Object.assign(ORTB2.prototype, { }); } return native; - }, cleanObj({ + }, utils.cleanObj({ clickUrl: adm.link, - clickTrackers: deepAccess(adm, 'link.clicktrackers'), + clickTrackers: utils.deepAccess(adm, 'link.clicktrackers'), impressionTrackers: trackers[nativeEventTrackerMethodMap.img], javascriptTrackers: trackers[nativeEventTrackerMethodMap.js] }))); } else { - logError('prebid server native response contained no assets'); + utils.logError('prebid server native response contained no assets'); } } else { // banner if (bid.adm && bid.nurl) { bidObject.ad = bid.adm; - bidObject.ad += createTrackPixelHtml(decodeURIComponent(bid.nurl)); + bidObject.ad += utils.createTrackPixelHtml(decodeURIComponent(bid.nurl)); } else if (bid.adm) { bidObject.ad = bid.adm; } else if (bid.nurl) { @@ -1106,13 +1008,14 @@ Object.assign(ORTB2.prototype, { bidObject.width = bid.w; bidObject.height = bid.h; if (bid.dealid) { bidObject.dealId = bid.dealid; } + bidObject.requestId = bidRequest.bidId || bidRequest.bid_Id; bidObject.creative_id = bid.crid; bidObject.creativeId = bid.crid; if (bid.burl) { bidObject.burl = bid.burl; } bidObject.currency = (response.cur) ? response.cur : DEFAULT_S2S_CURRENCY; bidObject.meta = {}; - let extPrebidMeta = deepAccess(bid, 'ext.prebid.meta'); - if (extPrebidMeta && isPlainObject(extPrebidMeta)) { bidObject.meta = deepClone(extPrebidMeta); } + let extPrebidMeta = utils.deepAccess(bid, 'ext.prebid.meta'); + if (extPrebidMeta && utils.isPlainObject(extPrebidMeta)) { bidObject.meta = utils.deepClone(extPrebidMeta); } if (bid.adomain) { bidObject.meta.advertiserDomains = bid.adomain; } // the OpenRTB location for "TTL" as understood by Prebid.js is "exp" (expiration). @@ -1120,24 +1023,14 @@ Object.assign(ORTB2.prototype, { bidObject.ttl = (bid.exp) ? bid.exp : configTtl; bidObject.netRevenue = (bid.netRevenue) ? bid.netRevenue : DEFAULT_S2S_NETREVENUE; - bids.push({ adUnit: this.adUnitsByImp[bid.impid].code, bid: bidObject }); + bids.push({ adUnit: bidRequest.adUnitCode, bid: bidObject }); }); }); } return bids; - }, - setBidRequestId(impId, bidderCode, bidId) { - this.bidIdMap[this.impBidderKey(impId, bidderCode)] = bidId; - }, - getBidRequest(impId, bidderCode) { - const key = this.impBidderKey(impId, bidderCode); - return this.bidIdMap[key] && getBidRequest(this.bidIdMap[key], this.bidderRequests); - }, - impBidderKey(impId, bidderCode) { - return `${impId}${bidderCode}`; } -}); +}; /** * BID_WON event to request the wurl @@ -1145,9 +1038,9 @@ Object.assign(ORTB2.prototype, { */ function bidWonHandler(bid) { const wurl = getWurl(bid.auctionId, bid.adId); - if (isStr(wurl)) { - logMessage(`Invoking image pixel for wurl on BID_WIN: "${wurl}"`); - triggerPixel(wurl); + if (utils.isStr(wurl)) { + utils.logMessage(`Invoking image pixel for wurl on BID_WIN: "${wurl}"`); + utils.triggerPixel(wurl); // remove from wurl cache, since the wurl url was called removeWurl(bid.auctionId, bid.adId); @@ -1158,7 +1051,7 @@ function hasPurpose1Consent(gdprConsent) { let result = true; if (gdprConsent) { if (gdprConsent.gdprApplies && gdprConsent.apiVersion === 2) { - result = !!(deepAccess(gdprConsent, 'vendorData.purpose.consents.1') === true); + result = !!(utils.deepAccess(gdprConsent, 'vendorData.purpose.consents.1') === true); } } return result; @@ -1185,8 +1078,20 @@ export function PrebidServer() { /* Prebid executes this function when the page asks to send out bid requests */ baseAdapter.callBids = function(s2sBidRequest, bidRequests, addBidResponse, done, ajax) { + const adUnits = utils.deepClone(s2sBidRequest.ad_units); let { gdprConsent, uspConsent } = getConsentData(bidRequests); + // at this point ad units should have a size array either directly or mapped so filter for that + const validAdUnits = adUnits.filter(unit => + unit.mediaTypes && (unit.mediaTypes.native || (unit.mediaTypes.banner && unit.mediaTypes.banner.sizes) || (unit.mediaTypes.video && unit.mediaTypes.video.playerSize)) + ); + + // in case config.bidders contains invalid bidders, we only process those we sent requests for + const requestedBidders = validAdUnits + .map(adUnit => adUnit.bids.map(bid => bid.bidder).filter(utils.uniques)) + .reduce(utils.flatten) + .filter(utils.uniques); + if (Array.isArray(_s2sConfigs)) { if (s2sBidRequest.s2sConfig && s2sBidRequest.s2sConfig.syncEndpoint && getMatchingConsentUrl(s2sBidRequest.s2sConfig.syncEndpoint, gdprConsent)) { let syncBidders = s2sBidRequest.s2sConfig.bidders @@ -1196,24 +1101,60 @@ export function PrebidServer() { queueSync(syncBidders, gdprConsent, uspConsent, s2sBidRequest.s2sConfig); } - processPBSRequest(s2sBidRequest, bidRequests, ajax, { - onResponse: function (isValid, requestedBidders) { - if (isValid) { - bidRequests.forEach(bidderRequest => events.emit(CONSTANTS.EVENTS.BIDDER_DONE, bidderRequest)); - } - done(); - doClientSideSyncs(requestedBidders, gdprConsent, uspConsent); - }, - onError: done, - onBid: function ({adUnit, bid}) { - if (isValid(adUnit, bid)) { - addBidResponse(adUnit, bid); - } - } - }) + const request = OPEN_RTB_PROTOCOL.buildRequest(s2sBidRequest, bidRequests, validAdUnits, s2sBidRequest.s2sConfig, requestedBidders); + const requestJson = request && JSON.stringify(request); + utils.logInfo('BidRequest: ' + requestJson); + const endpointUrl = getMatchingConsentUrl(s2sBidRequest.s2sConfig.endpoint, gdprConsent); + if (request && requestJson && endpointUrl) { + ajax( + endpointUrl, + { + success: response => handleResponse(response, requestedBidders, bidRequests, addBidResponse, done, s2sBidRequest.s2sConfig), + error: done + }, + requestJson, + { contentType: 'text/plain', withCredentials: true } + ); + } else { + utils.logError('PBS request not made. Check endpoints.'); + } } }; + /* Notify Prebid of bid responses so bids can get in the auction */ + function handleResponse(response, requestedBidders, bidderRequests, addBidResponse, done, s2sConfig) { + let result; + let bids = []; + let { gdprConsent, uspConsent } = getConsentData(bidderRequests); + + try { + result = JSON.parse(response); + + bids = OPEN_RTB_PROTOCOL.interpretResponse( + result, + bidderRequests, + s2sConfig + ); + + bids.forEach(({adUnit, bid}) => { + if (isValid(adUnit, bid, bidderRequests)) { + addBidResponse(adUnit, bid); + } + }); + + bidderRequests.forEach(bidderRequest => events.emit(CONSTANTS.EVENTS.BIDDER_DONE, bidderRequest)); + } catch (error) { + utils.logError(error); + } + + if (!result || (result.status && includes(result.status, 'Error'))) { + utils.logError('error parsing response: ', result.status); + } + + done(); + doClientSideSyncs(requestedBidders, gdprConsent, uspConsent); + } + // Listen for bid won to call wurl events.on(CONSTANTS.EVENTS.BID_WON, bidWonHandler); @@ -1224,61 +1165,6 @@ export function PrebidServer() { }); } -/** - * Build and send the appropriate HTTP request over the network, then interpret the response. - * @param s2sBidRequest - * @param bidRequests - * @param ajax - * @param onResponse {function(boolean, Array[String])} invoked on a successful HTTP response - with a flag indicating whether it was successful, - * and a list of the unique bidder codes that were sent in the request - * @param onError {function(String, {})} invoked on HTTP failure - with status message and XHR error - * @param onBid {function({})} invoked once for each bid in the response - with the bid as returned by interpretResponse - */ -export const processPBSRequest = hook('sync', function (s2sBidRequest, bidRequests, ajax, {onResponse, onError, onBid}) { - let { gdprConsent } = getConsentData(bidRequests); - const adUnits = deepClone(s2sBidRequest.ad_units); - - // in case config.bidders contains invalid bidders, we only process those we sent requests for - const requestedBidders = adUnits - .map(adUnit => adUnit.bids.map(bid => bid.bidder).filter(uniques)) - .reduce(flatten, []) - .filter(uniques); - - const ortb2 = new ORTB2(s2sBidRequest, bidRequests, adUnits, requestedBidders); - const request = ortb2.buildRequest(); - const requestJson = request && JSON.stringify(request); - logInfo('BidRequest: ' + requestJson); - const endpointUrl = getMatchingConsentUrl(s2sBidRequest.s2sConfig.endpoint, gdprConsent); - if (request && requestJson && endpointUrl) { - ajax( - endpointUrl, - { - success: function (response) { - let result; - try { - result = JSON.parse(response); - const bids = ortb2.interpretResponse(result); - bids.forEach(onBid); - } catch (error) { - logError(error); - } - if (!result || (result.status && includes(result.status, 'Error'))) { - logError('error parsing response: ', result ? result.status : 'not valid JSON'); - onResponse(false, requestedBidders); - } else { - onResponse(true, requestedBidders); - } - }, - error: onError - }, - requestJson, - {contentType: 'text/plain', withCredentials: true} - ); - } else { - logError('PBS request not made. Check endpoints.'); - } -}, 'processPBSRequest'); - /** * Global setter that sets eids permissions for bidders * This setter is to be used by userId module when included diff --git a/modules/prebidmanagerAnalyticsAdapter.js b/modules/prebidmanagerAnalyticsAdapter.js index 1ac7ba84916..b9a7d79f991 100644 --- a/modules/prebidmanagerAnalyticsAdapter.js +++ b/modules/prebidmanagerAnalyticsAdapter.js @@ -1,4 +1,3 @@ -import { generateUUID, getParameterByName, logError, parseUrl, logInfo } from '../src/utils.js'; import {ajaxBuilder} from '../src/ajax.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; @@ -7,17 +6,18 @@ import { getStorageManager } from '../src/storageManager.js'; /** * prebidmanagerAnalyticsAdapter.js - analytics adapter for prebidmanager */ -export const storage = getStorageManager({gvlid: undefined, moduleName: 'prebidmanager'}); +export const storage = getStorageManager(undefined, 'prebidmanager'); const DEFAULT_EVENT_URL = 'https://endpoint.prebidmanager.com/endpoint' const analyticsType = 'endpoint'; const analyticsName = 'Prebid Manager Analytics: '; +var utils = require('../src/utils.js'); var CONSTANTS = require('../src/constants.json'); let ajax = ajaxBuilder(0); var _VERSION = 1; var initOptions = null; -var _pageViewId = generateUUID(); +var _pageViewId = utils.generateUUID(); var _startAuction = 0; var _bidRequestTimeout = 0; let flushInterval; @@ -76,7 +76,7 @@ function collectUtmTagData() { let pmUtmTags = {}; try { utmTags.forEach(function (utmKey) { - let utmValue = getParameterByName(utmKey); + let utmValue = utils.getParameterByName(utmKey); if (utmValue !== '') { newUtm = true; } @@ -95,7 +95,7 @@ function collectUtmTagData() { }); } } catch (e) { - logError(`${analyticsName}Error`, e); + utils.logError(`${analyticsName}Error`, e); pmUtmTags['error_utm'] = 1; } return pmUtmTags; @@ -106,7 +106,7 @@ function collectPageInfo() { domain: window.location.hostname, } if (document.referrer) { - pageInfo.referrerDomain = parseUrl(document.referrer).hostname; + pageInfo.referrerDomain = utils.parseUrl(document.referrer).hostname; } return pageInfo; } @@ -128,7 +128,7 @@ function flush() { ajax( initOptions.url, - () => logInfo(`${analyticsName} sent events batch`), + () => utils.logInfo(`${analyticsName} sent events batch`), _VERSION + ':' + JSON.stringify(data), { contentType: 'text/plain', @@ -215,7 +215,7 @@ function handleEvent(eventType, eventArgs) { function sendEvent(event) { _eventQueue.push(event); - logInfo(`${analyticsName}Event ${event.eventType}:`, event); + utils.logInfo(`${analyticsName}Event ${event.eventType}:`, event); if (event.eventType === CONSTANTS.EVENTS.AUCTION_END) { flush(); diff --git a/modules/priceFloors.js b/modules/priceFloors.js index ff4213f1330..3555fedbf3a 100644 --- a/modules/priceFloors.js +++ b/modules/priceFloors.js @@ -1,30 +1,13 @@ -import { - debugTurnedOn, - deepAccess, - deepClone, - deepSetValue, - generateUUID, - getGptSlotInfoForAdUnitCode, - getParameterByName, - isNumber, - logError, - logInfo, - logWarn, - parseGPTSingleSizeArray, - parseUrl, - pick -} from '../src/utils.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import {config} from '../src/config.js'; -import {ajaxBuilder} from '../src/ajax.js'; -import * as events from '../src/events.js'; +import { getGlobal } from '../src/prebidGlobal.js'; +import { config } from '../src/config.js'; +import * as utils from '../src/utils.js'; +import { ajaxBuilder } from '../src/ajax.js'; +import events from '../src/events.js'; import CONSTANTS from '../src/constants.json'; -import {getHook} from '../src/hook.js'; -import {createBid} from '../src/bidfactory.js'; -import {find} from '../src/polyfill.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import {bidderSettings} from '../src/bidderSettings.js'; -import {auctionManager} from '../src/auctionManager.js'; +import { getHook } from '../src/hook.js'; +import { createBid } from '../src/bidfactory.js'; +import find from 'core-js-pure/features/array/find.js'; +import { getRefererInfo } from '../src/refererDetection.js'; /** * @summary This Module is intended to provide users with the ability to dynamically set and enforce price floors on a per auction basis. @@ -77,30 +60,19 @@ function roundUp(number, precision) { let referrerHostname; function getHostNameFromReferer(referer) { - referrerHostname = parseUrl(referer, {noDecodeWholeURL: true}).hostname; + referrerHostname = utils.parseUrl(referer, {noDecodeWholeURL: true}).hostname; return referrerHostname; } -// First look into bidRequest! -function getGptSlotFromAdUnit(transactionId, {index = auctionManager.index} = {}) { - const adUnit = index.getAdUnit({transactionId}); - const isGam = deepAccess(adUnit, 'ortb2Imp.ext.data.adserver.name') === 'gam'; - return isGam && adUnit.ortb2Imp.ext.data.adserver.adslot; -} - -function getAdUnitCode(request, response, {index = auctionManager.index} = {}) { - return request?.adUnitCode || index.getAdUnit(response).code; -} - /** * @summary floor field types with their matching functions to resolve the actual matched value */ export let fieldMatchingFunctions = { - 'size': (bidRequest, bidResponse) => parseGPTSingleSizeArray(bidResponse.size) || '*', + 'size': (bidRequest, bidResponse) => utils.parseGPTSingleSizeArray(bidResponse.size) || '*', 'mediaType': (bidRequest, bidResponse) => bidResponse.mediaType || 'banner', - 'gptSlot': (bidRequest, bidResponse) => getGptSlotFromAdUnit((bidRequest || bidResponse).transactionId) || getGptSlotInfoForAdUnitCode(getAdUnitCode(bidRequest, bidResponse)).gptSlot, + 'gptSlot': (bidRequest, bidResponse) => utils.getGptSlotInfoForAdUnitCode(bidRequest.adUnitCode).gptSlot, 'domain': (bidRequest, bidResponse) => referrerHostname || getHostNameFromReferer(getRefererInfo().referer), - 'adUnitCode': (bidRequest, bidResponse) => getAdUnitCode(bidRequest, bidResponse) + 'adUnitCode': (bidRequest, bidResponse) => bidRequest.adUnitCode } /** @@ -123,28 +95,28 @@ function enumeratePossibleFieldValues(floorFields, bidObject, responseObject) { * Generates all possible rule matches and picks the first matching one. */ export function getFirstMatchingFloor(floorData, bidObject, responseObject = {}) { - let fieldValues = enumeratePossibleFieldValues(deepAccess(floorData, 'schema.fields') || [], bidObject, responseObject); + let fieldValues = enumeratePossibleFieldValues(utils.deepAccess(floorData, 'schema.fields') || [], bidObject, responseObject); if (!fieldValues.length) return { matchingFloor: floorData.default }; // look to see if a request for this context was made already let matchingInput = fieldValues.map(field => field[0]).join('-'); // if we already have gotten the matching rule from this matching input then use it! No need to look again - let previousMatch = deepAccess(floorData, `matchingInputs.${matchingInput}`); + let previousMatch = utils.deepAccess(floorData, `matchingInputs.${matchingInput}`); if (previousMatch) { return {...previousMatch}; } - let allPossibleMatches = generatePossibleEnumerations(fieldValues, deepAccess(floorData, 'schema.delimiter') || '|'); + let allPossibleMatches = generatePossibleEnumerations(fieldValues, utils.deepAccess(floorData, 'schema.delimiter') || '|'); let matchingRule = find(allPossibleMatches, hashValue => floorData.values.hasOwnProperty(hashValue)); let matchingData = { floorMin: floorData.floorMin || 0, - floorRuleValue: isNaN(floorData.values[matchingRule]) ? floorData.default : floorData.values[matchingRule], + floorRuleValue: floorData.values[matchingRule] || floorData.default, matchingData: allPossibleMatches[0], // the first possible match is an "exact" so contains all data relevant for anlaytics adapters matchingRule }; matchingData.matchingFloor = Math.max(matchingData.floorMin, matchingData.floorRuleValue); // save for later lookup if needed - deepSetValue(floorData, `matchingInputs.${matchingInput}`, {...matchingData}); + utils.deepSetValue(floorData, `matchingInputs.${matchingInput}`, {...matchingData}); return matchingData; } @@ -169,7 +141,7 @@ function generatePossibleEnumerations(arrayOfFields, delimiter) { * @summary If a the input bidder has a registered cpmadjustment it returns the input CPM after being adjusted */ export function getBiddersCpmAdjustment(bidderName, inputCpm, bid = {}) { - const adjustmentFunction = bidderSettings.get(bidderName, 'bidCpmAdjustment'); + const adjustmentFunction = utils.deepAccess(getGlobal(), `bidderSettings.${bidderName}.bidCpmAdjustment`) || utils.deepAccess(getGlobal(), 'bidderSettings.standard.bidCpmAdjustment'); if (adjustmentFunction) { return parseFloat(adjustmentFunction(inputCpm, {...bid, cpm: inputCpm})); } @@ -189,9 +161,9 @@ export function calculateAdjustedFloor(oldFloor, newFloor) { * @summary gets the prebid set sizes depending on the input mediaType */ const getMediaTypesSizes = { - banner: (bid) => deepAccess(bid, 'mediaTypes.banner.sizes') || [], - video: (bid) => deepAccess(bid, 'mediaTypes.video.playerSize') || [], - native: (bid) => deepAccess(bid, 'mediaTypes.native.image.sizes') ? [deepAccess(bid, 'mediaTypes.native.image.sizes')] : [] + banner: (bid) => utils.deepAccess(bid, 'mediaTypes.banner.sizes') || [], + video: (bid) => utils.deepAccess(bid, 'mediaTypes.video.playerSize') || [], + native: (bid) => utils.deepAccess(bid, 'mediaTypes.native.image.sizes') ? [utils.deepAccess(bid, 'mediaTypes.native.image.sizes')] : [] } /** @@ -230,7 +202,7 @@ export function getFloor(requestParams = {currency: 'USD', mediaType: '*', size: try { floorInfo.matchingFloor = getGlobal().convertCurrency(floorInfo.matchingFloor, floorData.data.currency, currency); } catch (err) { - logWarn(`${MODULE_NAME}: Unable to get currency conversion for getFloor for bidder ${bidRequest.bidder}. You must have currency module enabled with defaultRates in your currency config`); + utils.logWarn(`${MODULE_NAME}: Unable to get currency conversion for getFloor for bidder ${bidRequest.bidder}. You must have currency module enabled with defaultRates in your currency config`); // since we were unable to convert to the bidders requested currency, we send back just the actual floors currency to them currency = floorData.data.currency; } @@ -255,7 +227,7 @@ export function getFloor(requestParams = {currency: 'USD', mediaType: '*', size: * @summary Takes a floorsData object and converts it into a hash map with appropriate keys */ export function getFloorsDataForAuction(floorData, adUnitCode) { - let auctionFloorData = deepClone(floorData); + let auctionFloorData = utils.deepClone(floorData); auctionFloorData.schema.delimiter = floorData.schema.delimiter || '|'; auctionFloorData.values = normalizeRulesForAuction(auctionFloorData, adUnitCode); // default the currency to USD if not passed in @@ -318,10 +290,10 @@ export function updateAdUnitsForAuction(adUnits, floorData, auctionId) { skipped: floorData.skipped, skipRate: floorData.skipRate, floorMin: floorData.floorMin, - modelVersion: deepAccess(floorData, 'data.modelVersion'), - modelWeight: deepAccess(floorData, 'data.modelWeight'), - modelTimestamp: deepAccess(floorData, 'data.modelTimestamp'), - location: deepAccess(floorData, 'data.location', 'noData'), + modelVersion: utils.deepAccess(floorData, 'data.modelVersion'), + modelWeight: utils.deepAccess(floorData, 'data.modelWeight'), + modelTimestamp: utils.deepAccess(floorData, 'data.modelTimestamp'), + location: utils.deepAccess(floorData, 'data.location', 'noData'), floorProvider: floorData.floorProvider, fetchStatus: _floorsConfig.fetchStatus }; @@ -345,27 +317,27 @@ export function pickRandomModel(modelGroups, weightSum) { * @summary Updates the adUnits accordingly and returns the necessary floorsData for the current auction */ export function createFloorsDataForAuction(adUnits, auctionId) { - let resolvedFloorsData = deepClone(_floorsConfig); + let resolvedFloorsData = utils.deepClone(_floorsConfig); // if using schema 2 pick a model here: - if (deepAccess(resolvedFloorsData, 'data.floorsSchemaVersion') === 2) { + if (utils.deepAccess(resolvedFloorsData, 'data.floorsSchemaVersion') === 2) { // merge the models specific stuff into the top level data settings (now it looks like floorsSchemaVersion 1!) let { modelGroups, ...rest } = resolvedFloorsData.data; resolvedFloorsData.data = Object.assign(rest, pickRandomModel(modelGroups, rest.modelWeightSum)); } // if we do not have a floors data set, we will try to use data set on adUnits - let useAdUnitData = Object.keys(deepAccess(resolvedFloorsData, 'data.values') || {}).length === 0; + let useAdUnitData = Object.keys(utils.deepAccess(resolvedFloorsData, 'data.values') || {}).length === 0; if (useAdUnitData) { resolvedFloorsData.data = getFloorDataFromAdUnits(adUnits); } else { resolvedFloorsData.data = getFloorsDataForAuction(resolvedFloorsData.data); } // if we still do not have a valid floor data then floors is not on for this auction, so skip - if (Object.keys(deepAccess(resolvedFloorsData, 'data.values') || {}).length === 0) { + if (Object.keys(utils.deepAccess(resolvedFloorsData, 'data.values') || {}).length === 0) { resolvedFloorsData.skipped = true; } else { // determine the skip rate now - const auctionSkipRate = getParameterByName('pbjs_skipRate') || resolvedFloorsData.skipRate; + const auctionSkipRate = utils.getParameterByName('pbjs_skipRate') || resolvedFloorsData.skipRate; const isSkipped = Math.random() * 100 < parseFloat(auctionSkipRate); resolvedFloorsData.skipped = isSkipped; } @@ -386,7 +358,7 @@ export function continueAuction(hookConfig) { _delayedAuctions = _delayedAuctions.filter(auctionConfig => auctionConfig.timer !== hookConfig.timer); // We need to know the auctionId at this time. So we will use the passed in one or generate and set it ourselves - hookConfig.reqBidsConfigObj.auctionId = hookConfig.reqBidsConfigObj.auctionId || generateUUID(); + hookConfig.reqBidsConfigObj.auctionId = hookConfig.reqBidsConfigObj.auctionId || utils.generateUUID(); // now we do what we need to with adUnits and save the data object to be used for getFloor and enforcement calls _floorDataForAuction[hookConfig.reqBidsConfigObj.auctionId] = createFloorsDataForAuction(hookConfig.reqBidsConfigObj.adUnits || getGlobal().adUnits, hookConfig.reqBidsConfigObj.auctionId); @@ -400,7 +372,7 @@ function validateSchemaFields(fields) { if (Array.isArray(fields) && fields.length > 0 && fields.every(field => allowedFields.indexOf(field) !== -1)) { return true; } - logError(`${MODULE_NAME}: Fields recieved do not match allowed fields`); + utils.logError(`${MODULE_NAME}: Fields recieved do not match allowed fields`); return false; } @@ -428,7 +400,7 @@ function validateRules(floorsData, numFields, delimiter) { function modelIsValid(model) { // schema.fields has only allowed attributes - if (!validateSchemaFields(deepAccess(model, 'schema.fields'))) { + if (!validateSchemaFields(utils.deepAccess(model, 'schema.fields'))) { return false; } return validateRules(model, model.schema.fields.length, model.schema.delimiter || '|') @@ -468,7 +440,7 @@ export function isFloorsDataValid(floorsData) { } floorsData.floorsSchemaVersion = floorsData.floorsSchemaVersion || 1; if (typeof floorsSchemaValidation[floorsData.floorsSchemaVersion] !== 'function') { - logError(`${MODULE_NAME}: Unknown floorsSchemaVersion: `, floorsData.floorsSchemaVersion); + utils.logError(`${MODULE_NAME}: Unknown floorsSchemaVersion: `, floorsData.floorsSchemaVersion); return false; } return floorsSchemaValidation[floorsData.floorsSchemaVersion](floorsData); @@ -479,13 +451,13 @@ export function isFloorsDataValid(floorsData) { */ export function parseFloorData(floorsData, location) { if (floorsData && typeof floorsData === 'object' && isFloorsDataValid(floorsData)) { - logInfo(`${MODULE_NAME}: A ${location} set the auction floor data set to `, floorsData); + utils.logInfo(`${MODULE_NAME}: A ${location} set the auction floor data set to `, floorsData); return { ...floorsData, location }; } - logError(`${MODULE_NAME}: The floors data did not contain correct values`, floorsData); + utils.logError(`${MODULE_NAME}: The floors data did not contain correct values`, floorsData); } /** @@ -506,7 +478,7 @@ export function requestBidsHook(fn, reqBidsConfigObj) { // If auction delay > 0 AND we are fetching -> Then wait until it finishes if (_floorsConfig.auctionDelay > 0 && fetching) { hookConfig.timer = setTimeout(() => { - logWarn(`${MODULE_NAME}: Fetch attempt did not return in time for auction`); + utils.logWarn(`${MODULE_NAME}: Fetch attempt did not return in time for auction`); _floorsConfig.fetchStatus = 'timeout'; continueAuction(hookConfig); }, _floorsConfig.auctionDelay); @@ -548,7 +520,7 @@ export function handleFetchResponse(fetchResponse) { // set .data to it _floorsConfig.data = fetchData; // set skipRate override if necessary - _floorsConfig.skipRate = isNumber(fetchData.skipRate) ? fetchData.skipRate : _floorsConfig.skipRate; + _floorsConfig.skipRate = utils.isNumber(fetchData.skipRate) ? fetchData.skipRate : _floorsConfig.skipRate; _floorsConfig.floorProvider = fetchData.floorProvider || _floorsConfig.floorProvider; } @@ -559,7 +531,7 @@ export function handleFetchResponse(fetchResponse) { function handleFetchError(status) { fetching = false; _floorsConfig.fetchStatus = 'error'; - logError(`${MODULE_NAME}: Fetch errored with: `, status); + utils.logError(`${MODULE_NAME}: Fetch errored with: `, status); // if any auctions are waiting for fetch to finish, we need to continue them! resumeDelayedAuctions(); @@ -575,13 +547,13 @@ export function generateAndHandleFetch(floorEndpoint) { // default to GET and we only support GET for now let requestMethod = floorEndpoint.method || 'GET'; if (requestMethod !== 'GET') { - logError(`${MODULE_NAME}: 'GET' is the only request method supported at this time!`); + utils.logError(`${MODULE_NAME}: 'GET' is the only request method supported at this time!`); } else { ajax(floorEndpoint.url, { success: handleFetchResponse, error: handleFetchError }, null, { method: 'GET' }); fetching = true; } } else if (fetching) { - logWarn(`${MODULE_NAME}: A fetch is already occuring. Skipping.`); + utils.logWarn(`${MODULE_NAME}: A fetch is already occuring. Skipping.`); } } @@ -602,14 +574,14 @@ function addFieldOverrides(overrides) { * @summary This is the function which controls what happens during a pbjs.setConfig({...floors: {}}) is called */ export function handleSetFloorsConfig(config) { - _floorsConfig = pick(config, [ + _floorsConfig = utils.pick(config, [ 'floorMin', 'enabled', enabled => enabled !== false, // defaults to true 'auctionDelay', auctionDelay => auctionDelay || 0, - 'floorProvider', floorProvider => deepAccess(config, 'data.floorProvider', floorProvider), + 'floorProvider', floorProvider => utils.deepAccess(config, 'data.floorProvider', floorProvider), 'endpoint', endpoint => endpoint || {}, - 'skipRate', () => !isNaN(deepAccess(config, 'data.skipRate')) ? config.data.skipRate : config.skipRate || 0, - 'enforcement', enforcement => pick(enforcement || {}, [ + 'skipRate', () => !isNaN(utils.deepAccess(config, 'data.skipRate')) ? config.data.skipRate : config.skipRate || 0, + 'enforcement', enforcement => utils.pick(enforcement || {}, [ 'enforceJS', enforceJS => enforceJS !== false, // defaults to true 'enforcePBS', enforcePBS => enforcePBS === true, // defaults to false 'floorDeals', floorDeals => floorDeals === true, // defaults to false @@ -635,11 +607,11 @@ export function handleSetFloorsConfig(config) { getGlobal().requestBids.before(requestBidsHook, 50); // if user has debug on then we want to allow the debugging module to run before this, assuming they are testing priceFloors // debugging is currently set at 5 priority - getHook('addBidResponse').before(addBidResponseHook, debugTurnedOn() ? 4 : 50); + getHook('addBidResponse').before(addBidResponseHook, utils.debugTurnedOn() ? 4 : 50); addedFloorsHook = true; } } else { - logInfo(`${MODULE_NAME}: Turning off module`); + utils.logInfo(`${MODULE_NAME}: Turning off module`); _floorsConfig = {}; _floorDataForAuction = {}; @@ -675,8 +647,8 @@ function addFloorDataToBid(floorData, floorInfo, bid, adjustedCpm) { * @summary takes the enforcement flags and the bid itself and determines if it should be floored */ function shouldFloorBid(floorData, floorInfo, bid) { - let enforceJS = deepAccess(floorData, 'enforcement.enforceJS') !== false; - let shouldFloorDeal = deepAccess(floorData, 'enforcement.floorDeals') === true || !bid.dealId; + let enforceJS = utils.deepAccess(floorData, 'enforcement.enforceJS') !== false; + let shouldFloorDeal = utils.deepAccess(floorData, 'enforcement.floorDeals') === true || !bid.dealId; let bidBelowFloor = bid.floorData.cpmAfterAdjustments < floorInfo.matchingFloor; return enforceJS && (bidBelowFloor && shouldFloorDeal); } @@ -686,19 +658,18 @@ function shouldFloorBid(floorData, floorInfo, bid) { * And if the rule we find determines a bid should be floored we will do so. */ export function addBidResponseHook(fn, adUnitCode, bid) { - let floorData = _floorDataForAuction[bid.auctionId]; - // if no floor data then bail - if (!floorData || !bid || floorData.skipped) { + let floorData = _floorDataForAuction[this.bidderRequest.auctionId]; + // if no floor data or associated bidRequest then bail + const matchingBidRequest = find(this.bidderRequest.bids, bidRequest => bidRequest.bidId && bidRequest.bidId === bid.requestId); + if (!floorData || !bid || floorData.skipped || !matchingBidRequest) { return fn.call(this, adUnitCode, bid); } - const matchingBidRequest = auctionManager.index.getBidRequest(bid) - // get the matching rule - let floorInfo = getFirstMatchingFloor(floorData.data, matchingBidRequest, {...bid, size: [bid.width, bid.height]}); + let floorInfo = getFirstMatchingFloor(floorData.data, {...matchingBidRequest}, {...bid, size: [bid.width, bid.height]}); if (!floorInfo.matchingFloor) { - logWarn(`${MODULE_NAME}: unable to determine a matching price floor for bidResponse`, bid); + utils.logWarn(`${MODULE_NAME}: unable to determine a matching price floor for bidResponse`, bid); return fn.call(this, adUnitCode, bid); } @@ -714,7 +685,7 @@ export function addBidResponseHook(fn, adUnitCode, bid) { try { adjustedCpm = getGlobal().convertCurrency(bid.cpm, bidResponseCurrency.toUpperCase(), floorCurrency); } catch (err) { - logError(`${MODULE_NAME}: Unable do get currency conversion for bidResponse to Floor Currency. Do you have Currency module enabled? ${bid}`); + utils.logError(`${MODULE_NAME}: Unable do get currency conversion for bidResponse to Floor Currency. Do you have Currency module enabled? ${bid}`); return fn.call(this, adUnitCode, bid); } } @@ -729,8 +700,8 @@ export function addBidResponseHook(fn, adUnitCode, bid) { if (shouldFloorBid(floorData, floorInfo, bid)) { // bid fails floor -> throw it out // create basic bid no-bid with necessary data fro analytics adapters - let flooredBid = createBid(CONSTANTS.STATUS.NO_BID, bid.getIdentifiers()); - Object.assign(flooredBid, pick(bid, [ + let flooredBid = createBid(CONSTANTS.STATUS.NO_BID, matchingBidRequest); + Object.assign(flooredBid, utils.pick(bid, [ 'floorData', 'width', 'height', @@ -743,7 +714,7 @@ export function addBidResponseHook(fn, adUnitCode, bid) { flooredBid.status = CONSTANTS.BID_STATUS.BID_REJECTED; // if floor not met update bid with 0 cpm so it is not included downstream and marked as no-bid flooredBid.cpm = 0; - logWarn(`${MODULE_NAME}: ${flooredBid.bidderCode}'s Bid Response for ${adUnitCode} was rejected due to floor not met`, bid); + utils.logWarn(`${MODULE_NAME}: ${flooredBid.bidderCode}'s Bid Response for ${adUnitCode} was rejected due to floor not met`, bid); return fn.call(this, adUnitCode, flooredBid); } return fn.call(this, adUnitCode, bid); diff --git a/modules/proxistoreBidAdapter.js b/modules/proxistoreBidAdapter.js index 42a98bcdb09..8b191c70e75 100644 --- a/modules/proxistoreBidAdapter.js +++ b/modules/proxistoreBidAdapter.js @@ -1,11 +1,10 @@ -import { isFn, isPlainObject } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'proxistore'; const PROXISTORE_VENDOR_ID = 418; const COOKIE_BASE_URL = 'https://abs.proxistore.com/v3/rtb/prebid/multi'; -const COOKIE_LESS_URL = - 'https://abs.cookieless-proxistore.com/v3/rtb/prebid/multi'; +const COOKIE_LESS_URL = 'https://abs.cookieless-proxistore.com/v3/rtb/prebid/multi'; function _createServerRequest(bidRequests, bidderRequest) { var sizeIds = []; @@ -171,7 +170,9 @@ function interpretResponse(serverResponse, bidRequest) { } function _assignFloor(bid) { - if (!isFn(bid.getFloor)) { + if (!utils.isFn(bid.getFloor)) { + // eslint-disable-next-line no-console + console.log(bid.params.bidFloor); return bid.params.bidFloor ? bid.params.bidFloor : null; } const floor = bid.getFloor({ @@ -180,7 +181,11 @@ function _assignFloor(bid) { size: '*', }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'EUR') { + if ( + utils.isPlainObject(floor) && + !isNaN(floor.floor) && + floor.currency === 'EUR' + ) { return floor.floor; } return null; @@ -191,7 +196,6 @@ export const spec = { isBidRequestValid: isBidRequestValid, buildRequests: buildRequests, interpretResponse: interpretResponse, - gvlid: PROXISTORE_VENDOR_ID, }; registerBidder(spec); diff --git a/modules/pubCommonId.js b/modules/pubCommonId.js index faca59cce1c..427f775c44b 100644 --- a/modules/pubCommonId.js +++ b/modules/pubCommonId.js @@ -3,9 +3,9 @@ * stored in the page's domain. When the module is included, an id is generated if needed, * persisted as a cookie, and automatically appended to all the bidRequest as bid.crumbs.pubcid. */ -import { logMessage, parseUrl, buildUrl, triggerPixel, generateUUID, isArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; -import * as events from '../src/events.js'; +import events from '../src/events.js'; import CONSTANTS from '../src/constants.json'; import { getStorageManager } from '../src/storageManager.js'; @@ -44,7 +44,7 @@ export function setStorageItem(key, val, expires) { storage.setDataInLocalStorage(key, val); } catch (e) { - logMessage(e); + utils.logMessage(e); } } @@ -74,7 +74,7 @@ export function getStorageItem(key) { } } } catch (e) { - logMessage(e); + utils.logMessage(e); } return val; @@ -89,7 +89,7 @@ export function removeStorageItem(key) { storage.removeDataFromLocalStorage(key + EXP_SUFFIX); storage.removeDataFromLocalStorage(key); } catch (e) { - logMessage(e); + utils.logMessage(e); } } @@ -141,13 +141,13 @@ function queuePixelCallback(pixelUrl, id) { id = id || ''; // Use pubcid as a cache buster - const urlInfo = parseUrl(pixelUrl); + const urlInfo = utils.parseUrl(pixelUrl); urlInfo.search.id = encodeURIComponent('pubcid:' + id); - const targetUrl = buildUrl(urlInfo); + const targetUrl = utils.buildUrl(urlInfo); events.on(CONSTANTS.EVENTS.AUCTION_END, function auctionEndHandler() { events.off(CONSTANTS.EVENTS.AUCTION_END, auctionEndHandler); - triggerPixel(targetUrl); + utils.triggerPixel(targetUrl); }); return true; @@ -177,7 +177,7 @@ export function requestBidHook(next, config) { if (typeof window[PUB_COMMON] === 'object') { // If the page includes its own pubcid object, then use that instead. pubcid = window[PUB_COMMON].getId(); - logMessage(PUB_COMMON + ': pubcid = ' + pubcid); + utils.logMessage(PUB_COMMON + ': pubcid = ' + pubcid); } else { // Otherwise get the existing cookie pubcid = readValue(ID_NAME); @@ -190,7 +190,7 @@ export function requestBidHook(next, config) { } // Generate a new id if (!pubcid) { - pubcid = generateUUID(); + pubcid = utils.generateUUID(); } // Update the cookie/storage with the latest expiration date writeValue(ID_NAME, pubcid, pubcidConfig.interval); @@ -205,14 +205,14 @@ export function requestBidHook(next, config) { } } - logMessage('pbjs: pubcid = ' + pubcid); + utils.logMessage('pbjs: pubcid = ' + pubcid); } // Append pubcid to each bid object, which will be incorporated // into bid requests later. if (adUnits && pubcid) { adUnits.forEach((unit) => { - if (unit.bids && isArray(unit.bids)) { + if (unit.bids && utils.isArray(unit.bids)) { unit.bids.forEach((bid) => { Object.assign(bid, {crumbs: {pubcid}}); }); diff --git a/modules/pubProvidedIdSystem.js b/modules/pubProvidedIdSystem.js index 669d223c57f..0b2175f57cb 100644 --- a/modules/pubProvidedIdSystem.js +++ b/modules/pubProvidedIdSystem.js @@ -6,7 +6,7 @@ */ import {submodule} from '../src/hook.js'; -import { logInfo, isArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; const MODULE_NAME = 'pubProvidedId'; @@ -27,7 +27,7 @@ export const pubProvidedIdSubmodule = { */ decode(value) { const res = value ? {pubProvidedId: value} : undefined; - logInfo('PubProvidedId: Decoded value ' + JSON.stringify(res)); + utils.logInfo('PubProvidedId: Decoded value ' + JSON.stringify(res)); return res; }, @@ -40,7 +40,7 @@ export const pubProvidedIdSubmodule = { getId(config) { const configParams = (config && config.params) || {}; let res = []; - if (isArray(configParams.eids)) { + if (utils.isArray(configParams.eids)) { res = res.concat(configParams.eids); } if (typeof configParams.eidsFunction === 'function') { diff --git a/modules/pubgeniusBidAdapter.js b/modules/pubgeniusBidAdapter.js index 28c4fdefd42..89dea545434 100644 --- a/modules/pubgeniusBidAdapter.js +++ b/modules/pubgeniusBidAdapter.js @@ -16,7 +16,7 @@ import { } from '../src/utils.js'; const BIDDER_VERSION = '1.1.0'; -const BASE_URL = 'https://auction.adpearl.io'; +const BASE_URL = 'https://ortb.adpearl.io'; export const spec = { code: 'pubgenius', diff --git a/modules/publinkIdSystem.js b/modules/publinkIdSystem.js deleted file mode 100644 index 9d5645a38cb..00000000000 --- a/modules/publinkIdSystem.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * This module adds the PublinkId to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/publinkIdSystem - * @requires module:modules/userId - */ - -import {submodule} from '../src/hook.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {ajax} from '../src/ajax.js'; -import { parseUrl, buildUrl, logError } from '../src/utils.js'; -import {uspDataHandler} from '../src/adapterManager.js'; - -const MODULE_NAME = 'publinkId'; -const GVLID = 24; -const PUBLINK_COOKIE = '_publink'; -const PUBLINK_S2S_COOKIE = '_publink_srv'; - -export const storage = getStorageManager({gvlid: GVLID}); - -function isHex(s) { - return /^[A-F0-9]+$/i.test(s); -} - -function publinkIdUrl(params, consentData) { - let url = parseUrl('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink'); - url.search = { - deh: params.e, - mpn: 'Prebid.js', - mpv: '$prebid.version$', - }; - - if (consentData) { - url.search.gdpr = (consentData.gdprApplies) ? 1 : 0; - url.search.gdpr_consent = consentData.consentString; - } - - if (params.site_id) { url.search.sid = params.site_id; } - - if (params.api_key) { url.search.apikey = params.api_key; } - - const usPrivacyString = uspDataHandler.getConsentData(); - if (usPrivacyString && typeof usPrivacyString === 'string') { - url.search.us_privacy = usPrivacyString; - } - - return buildUrl(url); -} - -function makeCallback(config = {}, consentData) { - return function(prebidCallback) { - const options = {method: 'GET', withCredentials: true}; - let handleResponse = function(responseText, xhr) { - if (xhr.status === 200) { - let response = JSON.parse(responseText); - if (response) { - prebidCallback(response.publink); - } - } - }; - - if (config.params && config.params.e) { - if (isHex(config.params.e)) { - ajax(publinkIdUrl(config.params, consentData), handleResponse, undefined, options); - } else { - logError('params.e must be a hex string'); - } - } - }; -} - -function getlocalValue() { - let result; - function getData(key) { - let value; - if (storage.hasLocalStorage()) { - value = storage.getDataFromLocalStorage(key); - } - if (!value) { - value = storage.getCookie(key); - } - - if (typeof value === 'string') { - // if it's a json object parse it and return the publink value, otherwise assume the value is the id - if (value.charAt(0) === '{') { - try { - const obj = JSON.parse(value); - if (obj) { - return obj.publink; - } - } catch (e) { - logError(e); - } - } else { - return value; - } - } - } - result = getData(PUBLINK_S2S_COOKIE); - if (!result) { - result = getData(PUBLINK_COOKIE); - } - return result; -} - -/** @type {Submodule} */ -export const publinkIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - gvlid: GVLID, - - /** - * decode the stored id value for passing to bid requests - * @function - * @param {string} publinkId encrypted userid - * @returns {{publinkId: string} | undefined} - */ - decode(publinkId) { - return {publinkId: publinkId}; - }, - - /** - * performs action to obtain id - * Use a publink cookie first if it is present, otherwise use prebids copy, if neither are available callout to get a new id - * @function - * @param {SubmoduleConfig} [config] Config object with params and storage properties - * @param {ConsentData|undefined} consentData GDPR consent - * @param {(Object|undefined)} storedId Previously cached id - * @returns {IdResponse} - */ - getId: function(config, consentData, storedId) { - const localValue = getlocalValue(); - if (localValue) { - return {id: localValue}; - } - if (!storedId) { - return {callback: makeCallback(config, consentData)}; - } - } -}; -submodule('userId', publinkIdSubmodule); diff --git a/modules/publinkIdSystem.md b/modules/publinkIdSystem.md deleted file mode 100644 index 263ce490529..00000000000 --- a/modules/publinkIdSystem.md +++ /dev/null @@ -1,33 +0,0 @@ -## Publink User ID Submodule - -Publink user id module - -## Configuration Descriptions for the `userId` Configuration Section - -| Param Name | Required | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Yes | String | module identifier | `"publinkId"` | -| params.e | Yes | String | hashed email address | `"7D320454942620664D96EF78ED4E3A2A"` | -| params.api_key | Yes | String | api key for access | `"7ab62359-bdc0-4095-b573-ef474fb55d24"` | -| params.site_id | Yes | String | site identifier | `"123456"` | - - -### Example configuration for Publink -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "publinkId", - storage: { - name: "pbjs_publink", - type: "html5" - }, - params: { - e: "7D320454942620664D96EF78ED4E3A2A", // example hashed email (md5) - site_id: "123456", // provided by Epsilon - api_key: "7ab62359-bdc0-4095-b573-ef474fb55d2" // provided by Epsilon - } - }], - } - }); -``` diff --git a/modules/pubmaticAnalyticsAdapter.js b/modules/pubmaticAnalyticsAdapter.js index f69fb20e5d5..9aa40a2282d 100755 --- a/modules/pubmaticAnalyticsAdapter.js +++ b/modules/pubmaticAnalyticsAdapter.js @@ -1,9 +1,9 @@ -import { _each, pick, logWarn, isStr, isArray, logError } from '../src/utils.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; import { ajax } from '../src/ajax.js'; import { config } from '../src/config.js'; +import * as utils from '../src/utils.js'; import { getGlobal } from '../src/prebidGlobal.js'; /// /////////// CONSTANTS ////////////// @@ -69,7 +69,7 @@ function setMediaTypes(types, bid) { if (typeof types === 'object') { if (!bid.sizes) { bid.dimensions = []; - _each(types, (type) => + utils._each(types, (type) => bid.dimensions = bid.dimensions.concat( type.sizes.map(sizeToDimensions) ) @@ -81,13 +81,13 @@ function setMediaTypes(types, bid) { } function copyRequiredBidDetails(bid) { - return pick(bid, [ + return utils.pick(bid, [ 'bidder', 'bidId', 'status', () => NO_BID, // default a bid to NO_BID until response is recieved or bid is timed out 'finalSource as source', 'params', - 'adUnit', () => pick(bid, [ + 'adUnit', () => utils.pick(bid, [ 'adUnitCode', 'transactionId', 'sizes as dimensions', sizes => sizes.map(sizeToDimensions), @@ -115,7 +115,7 @@ function setBidStatus(bid, args) { } function parseBidResponse(bid) { - return pick(bid, [ + return utils.pick(bid, [ 'bidPriceUSD', () => { // todo: check whether currency cases are handled here if (typeof bid.currency === 'string' && bid.currency.toUpperCase() === CURRENCY_USD) { @@ -125,7 +125,7 @@ function parseBidResponse(bid) { if (typeof bid.getCpmInNewCurrency === 'function') { return window.parseFloat(Number(bid.getCpmInNewCurrency(CURRENCY_USD)).toFixed(BID_PRECISION)); } - logWarn(LOG_PRE_FIX + 'Could not determine the Net cpm in USD for the bid thus using bid.cpm', bid); + utils.logWarn(LOG_PRE_FIX + 'Could not determine the Net cpm in USD for the bid thus using bid.cpm', bid); return bid.cpm }, 'bidGrossCpmUSD', () => { @@ -136,7 +136,7 @@ function parseBidResponse(bid) { if (typeof getGlobal().convertCurrency === 'function') { return window.parseFloat(Number(getGlobal().convertCurrency(bid.originalCpm, bid.originalCurrency, CURRENCY_USD)).toFixed(BID_PRECISION)); } - logWarn(LOG_PRE_FIX + 'Could not determine the Gross cpm in USD for the bid, thus using bid.originalCpm', bid); + utils.logWarn(LOG_PRE_FIX + 'Could not determine the Gross cpm in USD for the bid, thus using bid.originalCpm', bid); return bid.originalCpm }, 'dealId', @@ -154,7 +154,7 @@ function parseBidResponse(bid) { 'mi', 'regexPattern', () => bid.regexPattern || undefined, 'partnerImpId', // partner impression ID - 'dimensions', () => pick(bid, [ + 'dimensions', () => utils.pick(bid, [ 'width', 'height' ]) @@ -171,7 +171,7 @@ function getDevicePlatform() { var deviceType = 3; try { var ua = navigator.userAgent; - if (ua && isStr(ua) && ua.trim() != '') { + if (ua && utils.isStr(ua) && ua.trim() != '') { ua = ua.toLowerCase().trim(); var isMobileRegExp = new RegExp('(mobi|tablet|ios).*'); if (ua.match(isMobileRegExp)) { @@ -200,21 +200,6 @@ function getAdapterNameForAlias(aliasName) { return adapterManager.aliasRegistry[aliasName] || aliasName; } -function getAdDomain(bidResponse) { - if (bidResponse.meta && bidResponse.meta.advertiserDomains) { - let adomain = bidResponse.meta.advertiserDomains[0] - if (adomain) { - try { - let hostname = (new URL(adomain)); - return hostname.hostname.replace('www.', ''); - } catch (e) { - logWarn(LOG_PRE_FIX + 'Adomain URL (Not a proper URL):', adomain); - return adomain.replace('www.', ''); - } - } - } -} - function gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId, highestBid) { highestBid = (highestBid && highestBid.length > 0) ? highestBid[0] : null; return Object.keys(adUnit.bids).reduce(function(partnerBids, bidId) { @@ -233,7 +218,6 @@ function gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId, highestBid) { 'dc': bid.bidResponse ? (bid.bidResponse.dealChannel || EMPTY_STRING) : EMPTY_STRING, 'l1': bid.bidResponse ? bid.clientLatencyTimeMs : 0, 'l2': 0, - 'adv': bid.bidResponse ? getAdDomain(bid.bidResponse) || undefined : undefined, 'ss': (s2sBidders.indexOf(bid.bidder) > -1) ? 1 : 0, 't': (bid.status == ERROR && bid.error.code == TIMEOUT_ERROR) ? 1 : 0, 'wb': (highestBid && highestBid.requestId === bid.bidId ? 1 : 0), @@ -341,9 +325,9 @@ function executeBidWonLoggerCall(auctionId, adUnitId) { function auctionInitHandler(args) { s2sBidders = (function() { let s2sConf = config.getConfig('s2sConfig'); - return (s2sConf && isArray(s2sConf.bidders)) ? s2sConf.bidders : []; + return (s2sConf && utils.isArray(s2sConf.bidders)) ? s2sConf.bidders : []; }()); - let cacheEntry = pick(args, [ + let cacheEntry = utils.pick(args, [ 'timestamp', 'timeout', 'bidderDonePendingCount', () => args.bidderRequests.length, @@ -369,7 +353,7 @@ function bidRequestedHandler(args) { function bidResponseHandler(args) { let bid = cache.auctions[args.auctionId].adUnitCodes[args.adUnitCode].bids[args.requestId]; if (!bid) { - logError(LOG_PRE_FIX + 'Could not find associated bid request for bid response with requestId: ', args.requestId); + utils.logError(LOG_PRE_FIX + 'Could not find associated bid request for bid response with requestId: ', args.requestId); return; } bid.source = formatSource(bid.source || args.source); @@ -420,7 +404,7 @@ function bidTimeoutHandler(args) { code: TIMEOUT_ERROR }; } else { - logWarn(LOG_PRE_FIX + 'bid not found'); + utils.logWarn(LOG_PRE_FIX + 'bid not found'); } }); } @@ -440,17 +424,17 @@ let pubmaticAdapter = Object.assign({}, baseAdapter, { profileId = Number(conf.options.profileId) || DEFAULT_PROFILE_ID; profileVersionId = Number(conf.options.profileVersionId) || DEFAULT_PROFILE_VERSION_ID; } else { - logError(LOG_PRE_FIX + 'Config not found.'); + utils.logError(LOG_PRE_FIX + 'Config not found.'); error = true; } if (!publisherId) { - logError(LOG_PRE_FIX + 'Missing publisherId(Number).'); + utils.logError(LOG_PRE_FIX + 'Missing publisherId(Number).'); error = true; } if (error) { - logError(LOG_PRE_FIX + 'Not collecting data due to error(s).'); + utils.logError(LOG_PRE_FIX + 'Not collecting data due to error(s).'); } else { baseAdapter.enableAnalytics.call(this, conf); } diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index d64c6092afa..f6e6e67444a 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -1,4 +1,4 @@ -import { logWarn, _each, isBoolean, isStr, isArray, inIframe, mergeDeep, deepAccess, isNumber, deepSetValue, logInfo, logError, deepClone, convertTypes } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js'; import {config} from '../src/config.js'; @@ -11,15 +11,12 @@ const USER_SYNC_URL_IFRAME = 'https://ads.pubmatic.com/AdServer/js/user_sync.htm const USER_SYNC_URL_IMAGE = 'https://image8.pubmatic.com/AdServer/ImgSync?p='; const DEFAULT_CURRENCY = 'USD'; const AUCTION_TYPE = 1; -const GROUPM_ALIAS = {code: 'groupm', gvlid: 98}; -const MARKETPLACE_PARTNERS = ['groupm'] const UNDEFINED = undefined; const DEFAULT_WIDTH = 0; const DEFAULT_HEIGHT = 0; const PREBID_NATIVE_HELP_LINK = 'http://prebid.org/dev-docs/show-native-ads.html'; const PUBLICATION = 'pubmatic'; // Your publication on Blue Billywig, potentially with environment (e.g. publication.bbvms.com or publication.test.bbvms.com) const RENDERER_URL = 'https://pubmatic.bbvms.com/r/'.concat('$RENDERER', '.js'); // URL of the renderer application -const MSG_VIDEO_PLACEMENT_MISSING = 'Video.Placement param missing'; const CUSTOM_PARAMS = { 'kadpageurl': '', // Custom page url 'gender': '', // User gender @@ -127,7 +124,7 @@ const BB_RENDERER = { else if (bid.vastUrl) config.vastUrl = bid.vastUrl; if (!bid.vastXml && !bid.vastUrl) { - logWarn(`${LOG_WARN_PREFIX}: No vastXml or vastUrl on bid, bailing...`); + utils.logWarn(`${LOG_WARN_PREFIX}: No vastXml or vastUrl on bid, bailing...`); return; } @@ -145,7 +142,7 @@ const BB_RENDERER = { } if (renderer) renderer.bootstrap(config, ele); - else logWarn(`${LOG_WARN_PREFIX}: Couldn't find a renderer with ${rendererId}`); + else utils.logWarn(`${LOG_WARN_PREFIX}: Couldn't find a renderer with ${rendererId}`); }, newRenderer: function(rendererCode, adUnitCode) { var rendererUrl = RENDERER_URL.replace('$RENDERER', rendererCode); @@ -158,7 +155,7 @@ const BB_RENDERER = { try { renderer.setRender(BB_RENDERER.outstreamRender); } catch (err) { - logWarn(`${LOG_WARN_PREFIX}: Error tying to setRender on renderer`, err); + utils.logWarn(`${LOG_WARN_PREFIX}: Error tying to setRender on renderer`, err); } return renderer; @@ -183,9 +180,9 @@ let NATIVE_ASSET_ID_TO_KEY_MAP = {}; let NATIVE_ASSET_KEY_TO_ASSET_MAP = {}; // loading NATIVE_ASSET_ID_TO_KEY_MAP -_each(NATIVE_ASSETS, anAsset => { NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] = anAsset.KEY }); +utils._each(NATIVE_ASSETS, anAsset => { NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] = anAsset.KEY }); // loading NATIVE_ASSET_KEY_TO_ASSET_MAP -_each(NATIVE_ASSETS, anAsset => { NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); +utils._each(NATIVE_ASSETS, anAsset => { NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); function _getDomainFromURL(url) { let anchor = document.createElement('a'); @@ -194,8 +191,8 @@ function _getDomainFromURL(url) { } function _parseSlotParam(paramName, paramValue) { - if (!isStr(paramValue)) { - paramValue && logWarn(LOG_WARN_PREFIX + 'Ignoring param key: ' + paramName + ', expects string-value, found ' + typeof paramValue); + if (!utils.isStr(paramValue)) { + paramValue && utils.logWarn(LOG_WARN_PREFIX + 'Ignoring param key: ' + paramName + ', expects string-value, found ' + typeof paramValue); return UNDEFINED; } @@ -216,11 +213,11 @@ function _parseSlotParam(paramName, paramValue) { } function _cleanSlot(slotName) { - if (isStr(slotName)) { + if (utils.isStr(slotName)) { return slotName.replace(/^\s+/g, '').replace(/\s+$/g, ''); } if (slotName) { - logWarn(BIDDER_CODE + ': adSlot must be a string. Ignoring adSlot'); + utils.logWarn(BIDDER_CODE + ': adSlot must be a string. Ignoring adSlot'); } return ''; } @@ -246,7 +243,7 @@ function _parseAdSlot(bid) { // i.e size is specified in adslot, so consider that and ignore sizes array splits = splits[1].split('x'); if (splits.length != 2) { - logWarn(LOG_WARN_PREFIX + 'AdSlot Error: adSlot not in required format'); + utils.logWarn(LOG_WARN_PREFIX + 'AdSlot Error: adSlot not in required format'); return; } bid.params.width = parseInt(splits[0], 10); @@ -297,10 +294,10 @@ function _handleCustomParams(params, conf) { value = entry.f(value, conf); } - if (isStr(value)) { + if (utils.isStr(value)) { conf[key] = value; } else { - logWarn(LOG_WARN_PREFIX + 'Ignoring param : ' + key + ' with value : ' + CUSTOM_PARAMS[key] + ', expects string-value, found ' + typeof value); + utils.logWarn(LOG_WARN_PREFIX + 'Ignoring param : ' + key + ' with value : ' + CUSTOM_PARAMS[key] + ', expects string-value, found ' + typeof value); } } } @@ -337,22 +334,22 @@ function _checkParamDataType(key, value, datatype) { var functionToExecute; switch (datatype) { case DATA_TYPES.BOOLEAN: - functionToExecute = isBoolean; + functionToExecute = utils.isBoolean; break; case DATA_TYPES.NUMBER: - functionToExecute = isNumber; + functionToExecute = utils.isNumber; break; case DATA_TYPES.STRING: - functionToExecute = isStr; + functionToExecute = utils.isStr; break; case DATA_TYPES.ARRAY: - functionToExecute = isArray; + functionToExecute = utils.isArray; break; } if (functionToExecute(value)) { return value; } - logWarn(LOG_WARN_PREFIX + errMsg); + utils.logWarn(LOG_WARN_PREFIX + errMsg); return UNDEFINED; } @@ -389,7 +386,7 @@ function _createNativeRequest(params) { } }; } else { - logWarn(LOG_WARN_PREFIX + 'Error: Title Length is required for native ad: ' + JSON.stringify(params)); + utils.logWarn(LOG_WARN_PREFIX + 'Error: Title Length is required for native ad: ' + JSON.stringify(params)); } break; case NATIVE_ASSETS.IMAGE.KEY: @@ -408,7 +405,7 @@ function _createNativeRequest(params) { } }; } else { - logWarn(LOG_WARN_PREFIX + 'Error: Image sizes is required for native ad: ' + JSON.stringify(params)); + utils.logWarn(LOG_WARN_PREFIX + 'Error: Image sizes is required for native ad: ' + JSON.stringify(params)); } break; case NATIVE_ASSETS.ICON.KEY: @@ -423,7 +420,7 @@ function _createNativeRequest(params) { } }; } else { - logWarn(LOG_WARN_PREFIX + 'Error: Icon sizes is required for native ad: ' + JSON.stringify(params)); + utils.logWarn(LOG_WARN_PREFIX + 'Error: Icon sizes is required for native ad: ' + JSON.stringify(params)); }; break; case NATIVE_ASSETS.VIDEO.KEY: @@ -503,13 +500,13 @@ function _createBannerRequest(bid) { var sizes = bid.mediaTypes.banner.sizes; var format = []; var bannerObj; - if (sizes !== UNDEFINED && isArray(sizes)) { + if (sizes !== UNDEFINED && utils.isArray(sizes)) { bannerObj = {}; if (!bid.params.width && !bid.params.height) { if (sizes.length === 0) { // i.e. since bid.params does not have width or height, and length of sizes is 0, need to ignore this banner imp bannerObj = UNDEFINED; - logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.banner.size missing for adunit: ' + bid.params.adUnit + '. Ignoring the banner impression in the adunit.'); + utils.logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.banner.size missing for adunit: ' + bid.params.adUnit + '. Ignoring the banner impression in the adunit.'); return bannerObj; } else { bannerObj.w = parseInt(sizes[0][0], 10); @@ -532,44 +529,36 @@ function _createBannerRequest(bid) { } } bannerObj.pos = 0; - bannerObj.topframe = inIframe() ? 0 : 1; + bannerObj.topframe = utils.inIframe() ? 0 : 1; } else { - logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.banner.size missing for adunit: ' + bid.params.adUnit + '. Ignoring the banner impression in the adunit.'); + utils.logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.banner.size missing for adunit: ' + bid.params.adUnit + '. Ignoring the banner impression in the adunit.'); bannerObj = UNDEFINED; } return bannerObj; } -export function checkVideoPlacement(videoData, adUnitCode) { - // Check for video.placement property. If property is missing display log message. - if (!deepAccess(videoData, 'placement')) { - logWarn(MSG_VIDEO_PLACEMENT_MISSING + ' for ' + adUnitCode); - }; -} - function _createVideoRequest(bid) { - var videoData = mergeDeep(deepAccess(bid.mediaTypes, 'video'), bid.params.video); + var videoData = utils.mergeDeep(utils.deepAccess(bid.mediaTypes, 'video'), bid.params.video); var videoObj; if (videoData !== UNDEFINED) { videoObj = {}; - checkVideoPlacement(videoData, bid.adUnitCode); for (var key in VIDEO_CUSTOM_PARAMS) { if (videoData.hasOwnProperty(key)) { videoObj[key] = _checkParamDataType(key, videoData[key], VIDEO_CUSTOM_PARAMS[key]); } } // read playersize and assign to h and w. - if (isArray(bid.mediaTypes.video.playerSize[0])) { + if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0][0], 10); videoObj.h = parseInt(bid.mediaTypes.video.playerSize[0][1], 10); - } else if (isNumber(bid.mediaTypes.video.playerSize[0])) { + } else if (utils.isNumber(bid.mediaTypes.video.playerSize[0])) { videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0], 10); videoObj.h = parseInt(bid.mediaTypes.video.playerSize[1], 10); } } else { videoObj = UNDEFINED; - logWarn(LOG_WARN_PREFIX + 'Error: Video config params missing for adunit: ' + bid.params.adUnit + ' with mediaType set as video. Ignoring video impression in the adunit.'); + utils.logWarn(LOG_WARN_PREFIX + 'Error: Video config params missing for adunit: ' + bid.params.adUnit + ' with mediaType set as video. Ignoring video impression in the adunit.'); } return videoObj; } @@ -577,19 +566,19 @@ function _createVideoRequest(bid) { // support for PMP deals function _addPMPDealsInImpression(impObj, bid) { if (bid.params.deals) { - if (isArray(bid.params.deals)) { + if (utils.isArray(bid.params.deals)) { bid.params.deals.forEach(function(dealId) { - if (isStr(dealId) && dealId.length > 3) { + if (utils.isStr(dealId) && dealId.length > 3) { if (!impObj.pmp) { impObj.pmp = { private_auction: 0, deals: [] }; } impObj.pmp.deals.push({ id: dealId }); } else { - logWarn(LOG_WARN_PREFIX + 'Error: deal-id present in array bid.params.deals should be a strings with more than 3 charaters length, deal-id ignored: ' + dealId); + utils.logWarn(LOG_WARN_PREFIX + 'Error: deal-id present in array bid.params.deals should be a strings with more than 3 charaters length, deal-id ignored: ' + dealId); } }); } else { - logWarn(LOG_WARN_PREFIX + 'Error: bid.params.deals should be an array of strings.'); + utils.logWarn(LOG_WARN_PREFIX + 'Error: bid.params.deals should be an array of strings.'); } } } @@ -599,7 +588,7 @@ function _addDealCustomTargetings(imp, bid) { var dctrLen; if (bid.params.dctr) { dctr = bid.params.dctr; - if (isStr(dctr) && dctr.length > 0) { + if (utils.isStr(dctr) && dctr.length > 0) { var arr = dctr.split('|'); dctr = ''; arr.forEach(val => { @@ -611,36 +600,11 @@ function _addDealCustomTargetings(imp, bid) { } imp.ext['key_val'] = dctr.trim() } else { - logWarn(LOG_WARN_PREFIX + 'Ignoring param : dctr with value : ' + dctr + ', expects string-value, found empty or non-string value'); + utils.logWarn(LOG_WARN_PREFIX + 'Ignoring param : dctr with value : ' + dctr + ', expects string-value, found empty or non-string value'); } } } -function _addJWPlayerSegmentData(imp, bid, isS2S) { - var jwSegData = (bid.rtd && bid.rtd.jwplayer && bid.rtd.jwplayer.targeting) || undefined; - var jwPlayerData = ''; - const jwMark = 'jw-'; - - if (jwSegData === undefined || jwSegData === '' || !jwSegData.hasOwnProperty('segments')) return; - - var maxLength = jwSegData.segments.length; - - jwPlayerData += jwMark + 'id=' + jwSegData.content.id; // add the content id first - - for (var i = 0; i < maxLength; i++) { - jwPlayerData += '|' + jwMark + jwSegData.segments[i] + '=1'; - } - - var ext; - - if (isS2S) { - (imp.dctr === undefined || imp.dctr.length == 0) ? imp.dctr = jwPlayerData : imp.dctr += '|' + jwPlayerData; - } else { - ext = imp.ext; - ext && ext.key_val === undefined ? ext.key_val = jwPlayerData : ext.key_val += '|' + jwPlayerData; - } -} - function _createImpressionObject(bid, conf) { var impObj = {}; var bannerObj; @@ -663,7 +627,6 @@ function _createImpressionObject(bid, conf) { _addPMPDealsInImpression(impObj, bid); _addDealCustomTargetings(impObj, bid); - _addJWPlayerSegmentData(impObj, bid); if (bid.hasOwnProperty('mediaTypes')) { for (mediaTypes in bid.mediaTypes) { switch (mediaTypes) { @@ -678,7 +641,7 @@ function _createImpressionObject(bid, conf) { if (!isInvalidNativeRequest) { impObj.native = nativeObj; } else { - logWarn(LOG_WARN_PREFIX + 'Error: Error in Native adunit ' + bid.params.adUnit + '. Ignoring the adunit. Refer to ' + PREBID_NATIVE_HELP_LINK + ' for more details.'); + utils.logWarn(LOG_WARN_PREFIX + 'Error: Error in Native adunit ' + bid.params.adUnit + '. Ignoring the adunit. Refer to ' + PREBID_NATIVE_HELP_LINK + ' for more details.'); } break; case VIDEO: @@ -696,9 +659,9 @@ function _createImpressionObject(bid, conf) { pos: 0, w: bid.params.width, h: bid.params.height, - topframe: inIframe() ? 0 : 1 + topframe: utils.inIframe() ? 0 : 1 }; - if (isArray(sizes) && sizes.length > 1) { + if (utils.isArray(sizes) && sizes.length > 1) { sizes = sizes.splice(1, sizes.length - 1); sizes.forEach(size => { format.push({ @@ -721,31 +684,31 @@ function _createImpressionObject(bid, conf) { } function _addImpressionFPD(imp, bid) { - const ortb2 = {...deepAccess(bid, 'ortb2Imp.ext.data')}; + const ortb2 = {...utils.deepAccess(bid, 'ortb2Imp.ext.data')}; Object.keys(ortb2).forEach(prop => { /** * Prebid AdSlot * @type {(string|undefined)} */ if (prop === 'pbadslot') { - if (typeof ortb2[prop] === 'string' && ortb2[prop]) deepSetValue(imp, 'ext.data.pbadslot', ortb2[prop]); + if (typeof ortb2[prop] === 'string' && ortb2[prop]) utils.deepSetValue(imp, 'ext.data.pbadslot', ortb2[prop]); } else if (prop === 'adserver') { /** * Copy GAM AdUnit and Name to imp */ ['name', 'adslot'].forEach(name => { /** @type {(string|undefined)} */ - const value = deepAccess(ortb2, `adserver.${name}`); + const value = utils.deepAccess(ortb2, `adserver.${name}`); if (typeof value === 'string' && value) { - deepSetValue(imp, `ext.data.adserver.${name.toLowerCase()}`, value); + utils.deepSetValue(imp, `ext.data.adserver.${name.toLowerCase()}`, value); // copy GAM ad unit id as imp[].ext.dfp_ad_unit_code if (name === 'adslot') { - deepSetValue(imp, `ext.dfp_ad_unit_code`, value); + utils.deepSetValue(imp, `ext.dfp_ad_unit_code`, value); } } }); } else { - deepSetValue(imp, `ext.data.${prop}`, ortb2[prop]); + utils.deepSetValue(imp, `ext.data.${prop}`, ortb2[prop]); } }); } @@ -756,53 +719,27 @@ function _addFloorFromFloorModule(impObj, bid) { if (typeof bid.getFloor === 'function' && !config.getConfig('pubmatic.disableFloors')) { [BANNER, VIDEO, NATIVE].forEach(mediaType => { if (impObj.hasOwnProperty(mediaType)) { - let sizesArray = []; - - if (mediaType === 'banner') { - if (impObj[mediaType].w && impObj[mediaType].h) { - sizesArray.push([impObj[mediaType].w, impObj[mediaType].h]); - } - if (isArray(impObj[mediaType].format)) { - impObj[mediaType].format.forEach(size => sizesArray.push([size.w, size.h])); - } - } - - if (sizesArray.length === 0) { - sizesArray.push('*') + let floorInfo = bid.getFloor({ currency: impObj.bidfloorcur, mediaType: mediaType, size: '*' }); + if (typeof floorInfo === 'object' && floorInfo.currency === impObj.bidfloorcur && !isNaN(parseInt(floorInfo.floor))) { + let mediaTypeFloor = parseFloat(floorInfo.floor); + bidFloor = (bidFloor == -1 ? mediaTypeFloor : Math.min(mediaTypeFloor, bidFloor)) } - - sizesArray.forEach(size => { - let floorInfo = bid.getFloor({ currency: impObj.bidfloorcur, mediaType: mediaType, size: size }); - logInfo(LOG_WARN_PREFIX, 'floor from floor module returned for mediatype:', mediaType, ' and size:', size, ' is: currency', floorInfo.currency, 'floor', floorInfo.floor); - if (typeof floorInfo === 'object' && floorInfo.currency === impObj.bidfloorcur && !isNaN(parseInt(floorInfo.floor))) { - let mediaTypeFloor = parseFloat(floorInfo.floor); - logInfo(LOG_WARN_PREFIX, 'floor from floor module:', mediaTypeFloor, 'previous floor value', bidFloor, 'Min:', Math.min(mediaTypeFloor, bidFloor)); - if (bidFloor === -1) { - bidFloor = mediaTypeFloor; - } else { - bidFloor = Math.min(mediaTypeFloor, bidFloor) - } - logInfo(LOG_WARN_PREFIX, 'new floor value:', bidFloor); - } - }); } }); } // get highest from impObj.bidfllor and floor from floor module // as we are using Math.max, it is ok if we have not got any floor from floorModule, then value of bidFloor will be -1 if (impObj.bidfloor) { - logInfo(LOG_WARN_PREFIX, 'floor from floor module:', bidFloor, 'impObj.bidfloor', impObj.bidfloor, 'Max:', Math.max(bidFloor, impObj.bidfloor)); bidFloor = Math.max(bidFloor, impObj.bidfloor) } // assign value only if bidFloor is > 0 impObj.bidfloor = ((!isNaN(bidFloor) && bidFloor > 0) ? bidFloor : UNDEFINED); - logInfo(LOG_WARN_PREFIX, 'new impObj.bidfloor value:', impObj.bidfloor); } function _getFlocId(validBidRequests, flocFormat) { var flocIdObject = null; - var flocId = deepAccess(validBidRequests, '0.userId.flocId'); + var flocId = utils.deepAccess(validBidRequests, '0.userId.flocId'); if (flocId && flocId.id) { switch (flocFormat) { case FLOC_FORMAT.SEGMENT: @@ -853,7 +790,7 @@ function _handleFlocId(payload, validBidRequests) { } function _handleEids(payload, validBidRequests) { - let bidUserIdAsEids = deepAccess(validBidRequests, '0.userIdAsEids'); + let bidUserIdAsEids = utils.deepAccess(validBidRequests, '0.userIdAsEids'); let flocObject = _getFlocId(validBidRequests, FLOC_FORMAT.EID); if (flocObject) { if (!bidUserIdAsEids) { @@ -861,17 +798,17 @@ function _handleEids(payload, validBidRequests) { } bidUserIdAsEids.push(flocObject); } - if (isArray(bidUserIdAsEids) && bidUserIdAsEids.length > 0) { - deepSetValue(payload, 'user.eids', bidUserIdAsEids); + if (utils.isArray(bidUserIdAsEids) && bidUserIdAsEids.length > 0) { + utils.deepSetValue(payload, 'user.eids', bidUserIdAsEids); } } function _checkMediaType(bid, newBid) { // Create a regex here to check the strings - if (bid.ext && bid.ext['bidtype'] != undefined) { - newBid.mediaType = MEDIATYPE[bid.ext.bidtype]; + if (bid.ext && bid.ext['BidType'] != undefined) { + newBid.mediaType = MEDIATYPE[bid.ext.BidType]; } else { - logInfo(LOG_WARN_PREFIX + 'bid.ext.bidtype does not exist, checking alternatively for mediaType') + utils.logInfo(LOG_WARN_PREFIX + 'bid.ext.BidType does not exist, checking alternatively for mediaType') var adm = bid.adm; var admStr = ''; var videoRegex = new RegExp(/VAST\s+version/); @@ -886,7 +823,7 @@ function _checkMediaType(bid, newBid) { newBid.mediaType = NATIVE; } } catch (e) { - logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native reponse for ad response: ' + adm); + utils.logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native reponse for ad response: ' + adm); } } } @@ -899,7 +836,7 @@ function _parseNativeResponse(bid, newBid) { try { adm = JSON.parse(bid.adm.replace(/\\/g, '')); } catch (ex) { - logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native reponse for ad response: ' + newBid.adm); + utils.logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native reponse for ad response: ' + newBid.adm); return; } if (adm && adm.native && adm.native.assets && adm.native.assets.length > 0) { @@ -959,7 +896,7 @@ function _blockedIabCategoriesValidation(payload, blockedIabCategories) { if (typeof category === 'string') { // only strings return true; } else { - logWarn(LOG_WARN_PREFIX + 'bcat: Each category should be a string, ignoring category: ' + category); + utils.logWarn(LOG_WARN_PREFIX + 'bcat: Each category should be a string, ignoring category: ' + category); return false; } }) @@ -968,34 +905,15 @@ function _blockedIabCategoriesValidation(payload, blockedIabCategories) { if (category.length > 3) { return arr.indexOf(category) === index; // unique value only } else { - logWarn(LOG_WARN_PREFIX + 'bcat: Each category should have a value of a length of more than 3 characters, ignoring category: ' + category) + utils.logWarn(LOG_WARN_PREFIX + 'bcat: Each category should have a value of a length of more than 3 characters, ignoring category: ' + category) } }); if (blockedIabCategories.length > 0) { - logWarn(LOG_WARN_PREFIX + 'bcat: Selected: ', blockedIabCategories); + utils.logWarn(LOG_WARN_PREFIX + 'bcat: Selected: ', blockedIabCategories); payload.bcat = blockedIabCategories; } } -function _allowedIabCategoriesValidation(payload, allowedIabCategories) { - allowedIabCategories = allowedIabCategories - .filter(function(category) { - if (typeof category === 'string') { // returns only strings - return true; - } else { - logWarn(LOG_WARN_PREFIX + 'acat: Each category should be a string, ignoring category: ' + category); - return false; - } - }) - .map(category => category.trim()) // trim all categories - .filter((category, index, arr) => arr.indexOf(category) === index); // return unique values only - - if (allowedIabCategories.length > 0) { - logWarn(LOG_WARN_PREFIX + 'acat: Selected: ', allowedIabCategories); - payload.ext.acat = allowedIabCategories; - } -} - function _assignRenderer(newBid, request) { let bidParams, context, adUnitCode; if (request.bidderRequest && request.bidderRequest.bids) { @@ -1014,7 +932,7 @@ function _assignRenderer(newBid, request) { } function isNonEmptyArray(test) { - if (isArray(test) === true) { + if (utils.isArray(test) === true) { if (test.length > 0) { return true; } @@ -1026,7 +944,6 @@ export const spec = { code: BIDDER_CODE, gvlid: 76, supportedMediaTypes: [BANNER, VIDEO, NATIVE], - aliases: [GROUPM_ALIAS], /** * Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid * @@ -1035,27 +952,27 @@ export const spec = { */ isBidRequestValid: bid => { if (bid && bid.params) { - if (!isStr(bid.params.publisherId)) { - logWarn(LOG_WARN_PREFIX + 'Error: publisherId is mandatory and cannot be numeric (wrap it in quotes in your config). Call to OpenBid will not be sent for ad unit: ' + JSON.stringify(bid)); + if (!utils.isStr(bid.params.publisherId)) { + utils.logWarn(LOG_WARN_PREFIX + 'Error: publisherId is mandatory and cannot be numeric (wrap it in quotes in your config). Call to OpenBid will not be sent for ad unit: ' + JSON.stringify(bid)); return false; } // video ad validation if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(VIDEO)) { // bid.mediaTypes.video.mimes OR bid.params.video.mimes should be present and must be a non-empty array - let mediaTypesVideoMimes = deepAccess(bid.mediaTypes, 'video.mimes'); - let paramsVideoMimes = deepAccess(bid, 'params.video.mimes'); + let mediaTypesVideoMimes = utils.deepAccess(bid.mediaTypes, 'video.mimes'); + let paramsVideoMimes = utils.deepAccess(bid, 'params.video.mimes'); if (isNonEmptyArray(mediaTypesVideoMimes) === false && isNonEmptyArray(paramsVideoMimes) === false) { - logWarn(LOG_WARN_PREFIX + 'Error: For video ads, bid.mediaTypes.video.mimes OR bid.params.video.mimes should be present and must be a non-empty array. Call to OpenBid will not be sent for ad unit:' + JSON.stringify(bid)); + utils.logWarn(LOG_WARN_PREFIX + 'Error: For video ads, bid.mediaTypes.video.mimes OR bid.params.video.mimes should be present and must be a non-empty array. Call to OpenBid will not be sent for ad unit:' + JSON.stringify(bid)); return false; } if (!bid.mediaTypes[VIDEO].hasOwnProperty('context')) { - logError(`${LOG_WARN_PREFIX}: no context specified in bid. Rejecting bid: `, bid); + utils.logError(`${LOG_WARN_PREFIX}: no context specified in bid. Rejecting bid: `, bid); return false; } if (bid.mediaTypes[VIDEO].context === 'outstream' && - !isStr(bid.params.outstreamAU) && + !utils.isStr(bid.params.outstreamAU) && !bid.hasOwnProperty('renderer') && !bid.mediaTypes[VIDEO].hasOwnProperty('renderer')) { // we are here since outstream ad-unit is provided without outstreamAU and renderer @@ -1065,10 +982,10 @@ export const spec = { if (bid.mediaTypes.hasOwnProperty(BANNER) || bid.mediaTypes.hasOwnProperty(NATIVE)) { delete bid.mediaTypes[VIDEO]; - logWarn(`${LOG_WARN_PREFIX}: for "outstream" bids either outstreamAU parameter must be provided or ad unit supplied renderer is required. Rejecting mediatype Video of bid: `, bid); + utils.logWarn(`${LOG_WARN_PREFIX}: for "outstream" bids either outstreamAU parameter must be provided or ad unit supplied renderer is required. Rejecting mediatype Video of bid: `, bid); return true; } else { - logError(`${LOG_WARN_PREFIX}: for "outstream" bids either outstreamAU parameter must be provided or ad unit supplied renderer is required. Rejecting bid: `, bid); + utils.logError(`${LOG_WARN_PREFIX}: for "outstream" bids either outstreamAU parameter must be provided or ad unit supplied renderer is required. Rejecting bid: `, bid); return false; } } @@ -1085,12 +1002,6 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: (validBidRequests, bidderRequest) => { - if (bidderRequest && MARKETPLACE_PARTNERS.includes(bidderRequest.bidderCode)) { - // We have got the buildRequests function call for Marketplace Partners - logInfo('For all publishers using ' + bidderRequest.bidderCode + ' bidder, the PubMatic bidder will also be enabled so PubMatic server will respond back with the bids that needs to be submitted for PubMatic and ' + bidderRequest.bidderCode + ' in the network call sent by PubMatic bidder. Hence we do not want to create a network call for ' + bidderRequest.bidderCode + '. This way we are trying to save a network call from browser.'); - return; - } - var refererInfo; if (bidderRequest && bidderRequest.refererInfo) { refererInfo = bidderRequest.refererInfo; @@ -1101,19 +1012,18 @@ export const spec = { var dctrArr = []; var bid; var blockedIabCategories = []; - var allowedIabCategories = []; validBidRequests.forEach(originalBid => { - bid = deepClone(originalBid); + bid = utils.deepClone(originalBid); bid.params.adSlot = bid.params.adSlot || ''; _parseAdSlot(bid); - if ((bid.mediaTypes && bid.mediaTypes.hasOwnProperty('video')) || bid.params.hasOwnProperty('video')) { + if (bid.params.hasOwnProperty('video')) { // Nothing to do } else { // If we have a native mediaType configured alongside banner, its ok if the banner size is not set in width and height // The corresponding banner imp object will not be generated, but we still want the native object to be sent, hence the following check if (!(bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(NATIVE)) && bid.params.width === 0 && bid.params.height === 0) { - logWarn(LOG_WARN_PREFIX + 'Skipping the non-standard adslot: ', bid.params.adSlot, JSON.stringify(bid)); + utils.logWarn(LOG_WARN_PREFIX + 'Skipping the non-standard adslot: ', bid.params.adSlot, JSON.stringify(bid)); return; } } @@ -1123,19 +1033,16 @@ export const spec = { if (bidCurrency === '') { bidCurrency = bid.params.currency || UNDEFINED; } else if (bid.params.hasOwnProperty('currency') && bidCurrency !== bid.params.currency) { - logWarn(LOG_WARN_PREFIX + 'Currency specifier ignored. Only one currency permitted.'); + utils.logWarn(LOG_WARN_PREFIX + 'Currency specifier ignored. Only one currency permitted.'); } bid.params.currency = bidCurrency; // check if dctr is added to more than 1 adunit - if (bid.params.hasOwnProperty('dctr') && isStr(bid.params.dctr)) { + if (bid.params.hasOwnProperty('dctr') && utils.isStr(bid.params.dctr)) { dctrArr.push(bid.params.dctr); } - if (bid.params.hasOwnProperty('bcat') && isArray(bid.params.bcat)) { + if (bid.params.hasOwnProperty('bcat') && utils.isArray(bid.params.bcat)) { blockedIabCategories = blockedIabCategories.concat(bid.params.bcat); } - if (bid.params.hasOwnProperty('acat') && isArray(bid.params.acat)) { - allowedIabCategories = allowedIabCategories.concat(bid.params.acat); - } var impObj = _createImpressionObject(bid, conf); if (impObj) { payload.imp.push(impObj); @@ -1176,7 +1083,7 @@ export const spec = { } // passing transactionId in source.tid - deepSetValue(payload, 'source.tid', conf.transactionId); + utils.deepSetValue(payload, 'source.tid', conf.transactionId); // test bids if (window.location.href.indexOf('pubmaticTest=true') !== -1) { @@ -1185,46 +1092,37 @@ export const spec = { // adding schain object if (validBidRequests[0].schain) { - deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); + utils.deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); } // Attaching GDPR Consent Params if (bidderRequest && bidderRequest.gdprConsent) { - deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(payload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + utils.deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(payload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); } // CCPA if (bidderRequest && bidderRequest.uspConsent) { - deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); } // coppa compliance if (config.getConfig('coppa') === true) { - deepSetValue(payload, 'regs.coppa', 1); + utils.deepSetValue(payload, 'regs.coppa', 1); } _handleEids(payload, validBidRequests); - + _blockedIabCategoriesValidation(payload, blockedIabCategories); _handleFlocId(payload, validBidRequests); // First Party Data const commonFpd = config.getConfig('ortb2') || {}; if (commonFpd.site) { - mergeDeep(payload, {site: commonFpd.site}); + utils.mergeDeep(payload, {site: commonFpd.site}); } if (commonFpd.user) { - mergeDeep(payload, {user: commonFpd.user}); - } - if (commonFpd.bcat) { - blockedIabCategories = blockedIabCategories.concat(commonFpd.bcat) - } - if (commonFpd.ext?.prebid?.bidderparams?.[bidderRequest.bidderCode]?.acat) { - const acatParams = commonFpd.ext.prebid.bidderparams[bidderRequest.bidderCode].acat; - _allowedIabCategoriesValidation(payload, acatParams); - } else if (allowedIabCategories.length) { - _allowedIabCategoriesValidation(payload, allowedIabCategories); + utils.mergeDeep(payload, {user: commonFpd.user}); } - _blockedIabCategoriesValidation(payload, blockedIabCategories); + // Note: Do not move this block up // if site object is set in Prebid config then we need to copy required fields from site into app and unset the site object if (typeof config.getConfig('app') === 'object') { @@ -1260,12 +1158,12 @@ export const spec = { let parsedRequest = JSON.parse(request.data); let parsedReferrer = parsedRequest.site && parsedRequest.site.ref ? parsedRequest.site.ref : ''; try { - if (response.body && response.body.seatbid && isArray(response.body.seatbid)) { + if (response.body && response.body.seatbid && utils.isArray(response.body.seatbid)) { // Supporting multiple bid responses for same adSize respCur = response.body.cur || respCur; response.body.seatbid.forEach(seatbidder => { seatbidder.bid && - isArray(seatbidder.bid) && + utils.isArray(seatbidder.bid) && seatbidder.bid.forEach(bid => { let newBid = { requestId: bid.impid, @@ -1326,19 +1224,12 @@ export const spec = { }; } - // if from the server-response the bid.ext.marketplace is set then - // submit the bid to Prebid as marketplace name - if (bid.ext && !!bid.ext.marketplace && MARKETPLACE_PARTNERS.includes(bid.ext.marketplace)) { - newBid.bidderCode = bid.ext.marketplace; - newBid.bidder = bid.ext.marketplace; - } - bidResponses.push(newBid); }); }); } } catch (error) { - logError(error); + utils.logError(error); } return bidResponses; }, @@ -1384,10 +1275,8 @@ export const spec = { * @param {Boolean} isOpenRtb boolean to check openrtb2 protocol * @return {Object} params bid params */ - - transformBidParams: function (params, isOpenRtb, adUnit, bidRequests) { - _addJWPlayerSegmentData(params, adUnit.bids[0], true); - return convertTypes({ + transformBidParams: function (params, isOpenRtb) { + return utils.convertTypes({ 'publisherId': 'string', 'adSlot': 'string' }, params); diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index baf58177505..e9d93d79758 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -25,7 +25,7 @@ var adUnits = [ bidder: 'pubmatic', params: { publisherId: '156209', // required, must be a string, not an integer or other js type. - outstreamAU: 'renderer_test_pubmatic', // required if mediaTypes-> video-> context is 'outstream' and optional if renderer is defined in adUnits or in mediaType video. This value can be get by BlueBillyWig Team. + oustreamAU: 'renderer_test_pubmatic', // required if mediaTypes-> video-> context is 'outstream' and optional if renderer is defined in adUnits or in mediaType video. This value can be get by BlueBillyWig Team. adSlot: 'pubmatic_test2', // optional, must be a string, not an integer or other js type. pmzoneid: 'zone1, zone11', // optional lat: '40.712775', // optional diff --git a/modules/pubnxBidAdapter.md b/modules/pubnxBidAdapter.md new file mode 100644 index 00000000000..6c843322402 --- /dev/null +++ b/modules/pubnxBidAdapter.md @@ -0,0 +1,31 @@ +# Overview + +``` +Module Name: PubNX Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid-team@pubnx.com +``` + +# Description + +Connects to PubNX exchange for bids. +PubNX Bidder adapter supports Banner ads. +Use bidder code ```pubnx``` for all PubNX traffic. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + sizes: [[300, 250], [300,600]], // a display size(s) + bids: [{ + bidder: 'pubnx', + params: { + placementId: 'PNX-HB-G396432V4809F3' + } + }] + }, +]; +``` + diff --git a/modules/pubperfAnalyticsAdapter.js b/modules/pubperfAnalyticsAdapter.js index 9282d5814c0..800ea1cd550 100644 --- a/modules/pubperfAnalyticsAdapter.js +++ b/modules/pubperfAnalyticsAdapter.js @@ -4,7 +4,7 @@ import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; -import { logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; var pubperfAdapter = adapter({ global: 'pubperf_pbjs', @@ -16,11 +16,11 @@ pubperfAdapter.originEnableAnalytics = pubperfAdapter.enableAnalytics; pubperfAdapter.enableAnalytics = config => { if (!config || !config.provider || config.provider !== 'pubperf') { - logError('expected config.provider to equal pubperf'); + utils.logError('expected config.provider to equal pubperf'); return; } if (!window['pubperf_pbjs']) { - logError( + utils.logError( `Make sure that Pubperf tag from https://www.pubperf.com is included before the Prebid configuration.` ); return; diff --git a/modules/pubwiseAnalyticsAdapter.js b/modules/pubwiseAnalyticsAdapter.js index 006d6da7eb7..fe217454b88 100644 --- a/modules/pubwiseAnalyticsAdapter.js +++ b/modules/pubwiseAnalyticsAdapter.js @@ -1,9 +1,9 @@ -import { getParameterByName, logInfo, generateUUID, debugTurnedOn } from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; import { getStorageManager } from '../src/storageManager.js'; +const utils = require('../src/utils.js'); const storage = getStorageManager(); /**** @@ -76,7 +76,7 @@ function enrichWithUTM(dataBag) { let newUtm = false; try { for (let prop in utmKeys) { - utmKeys[prop] = getParameterByName(prop); + utmKeys[prop] = utils.getParameterByName(prop); if (utmKeys[prop]) { newUtm = true; dataBag[prop] = utmKeys[prop]; @@ -192,7 +192,7 @@ function markEnabled() { } function pwInfo(info, context) { - logInfo(`${analyticsName} ` + info, context); + utils.logInfo(`${analyticsName} ` + info, context); } function filterBidResponse(data) { @@ -304,7 +304,7 @@ pubwiseAnalytics.storeSessionID = function (userSessID) { // ensure a session exists, if not make one, always store it pubwiseAnalytics.ensureSession = function () { if (sessionExpired() === true || userSessionID() === null || userSessionID() === '') { - let generatedId = generateUUID(); + let generatedId = utils.generateUUID(); expireUtmData(); this.storeSessionID(generatedId); sessionData.sessionId = generatedId; @@ -320,10 +320,10 @@ pubwiseAnalytics.enableAnalytics = function (config) { configOptions = Object.assign(configOptions, config.options); // take the PBJS debug for our debug setting if no PW debug is defined if (configOptions.debug === null) { - configOptions.debug = debugTurnedOn(); + configOptions.debug = utils.debugTurnedOn(); } markEnabled(); - sessionData.activationId = generateUUID(); + sessionData.activationId = utils.generateUUID(); this.ensureSession(); pubwiseAnalytics.adapterEnableAnalytics(config); }; diff --git a/modules/pubwiseBidAdapter.js b/modules/pubwiseBidAdapter.js index a1b9ffb56a0..f450a8bede8 100644 --- a/modules/pubwiseBidAdapter.js +++ b/modules/pubwiseBidAdapter.js @@ -1,4 +1,4 @@ -import { _each, isStr, deepClone, isArray, deepSetValue, inIframe, logMessage, logInfo, logWarn, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE } from '../src/mediaTypes.js'; @@ -81,9 +81,9 @@ let NATIVE_ASSET_KEY_TO_ASSET_MAP = {}; // together allows traversal of NATIVE_ASSETS_LIST in any direction // id -> key -_each(NATIVE_ASSETS, anAsset => { NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] = anAsset.KEY }); +utils._each(NATIVE_ASSETS, anAsset => { NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] = anAsset.KEY }); // key -> asset -_each(NATIVE_ASSETS, anAsset => { NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); +utils._each(NATIVE_ASSETS, anAsset => { NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); export const spec = { code: BIDDER_CODE, @@ -99,7 +99,7 @@ export const spec = { // siteId is required if (bid.params && bid.params.siteId) { // it must be a string - if (!isStr(bid.params.siteId)) { + if (!utils.isStr(bid.params.siteId)) { _logWarn('siteId is required for bid', bid); return false; } @@ -127,7 +127,7 @@ export const spec = { var blockedIabCategories = []; validBidRequests.forEach(originalBid => { - bid = deepClone(originalBid); + bid = utils.deepClone(originalBid); bid.params.adSlot = bid.params.adSlot || ''; _parseAdSlot(bid); @@ -136,7 +136,7 @@ export const spec = { bidCurrency = bid.params.currency || UNDEFINED; bid.params.currency = bidCurrency; - if (bid.params.hasOwnProperty('bcat') && isArray(bid.params.bcat)) { + if (bid.params.hasOwnProperty('bcat') && utils.isArray(bid.params.bcat)) { blockedIabCategories = blockedIabCategories.concat(bid.params.bcat); } @@ -180,27 +180,27 @@ export const spec = { } // passing transactionId in source.tid - deepSetValue(payload, 'source.tid', conf.transactionId); + utils.deepSetValue(payload, 'source.tid', conf.transactionId); // schain if (validBidRequests[0].schain) { - deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); + utils.deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); } // gdpr consent if (bidderRequest && bidderRequest.gdprConsent) { - deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(payload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + utils.deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(payload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); } // ccpa on the root object if (bidderRequest && bidderRequest.uspConsent) { - deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); } // if coppa is in effect then note it if (config.getConfig('coppa') === true) { - deepSetValue(payload, 'regs.coppa', 1); + utils.deepSetValue(payload, 'regs.coppa', 1); } var options = {contentType: 'text/plain'} @@ -230,12 +230,12 @@ export const spec = { // let parsedReferrer = parsedRequest.site && parsedRequest.site.ref ? parsedRequest.site.ref : ''; // try { - if (response.body && response.body.seatbid && isArray(response.body.seatbid)) { + if (response.body && response.body.seatbid && utils.isArray(response.body.seatbid)) { // Supporting multiple bid responses for same adSize respCur = response.body.cur || respCur; response.body.seatbid.forEach(seatbidder => { seatbidder.bid && - isArray(seatbidder.bid) && + utils.isArray(seatbidder.bid) && seatbidder.bid.forEach(bid => { let newBid = { requestId: bid.impid, @@ -388,7 +388,7 @@ function _handleCustomParams(params, conf) { value = entry.f(value, conf); } - if (isStr(value)) { + if (utils.isStr(value)) { conf[key] = value; } else { _logWarn('Ignoring param : ' + key + ' with value : ' + CUSTOM_PARAMS[key] + ', expects string-value, found ' + typeof value); @@ -469,7 +469,7 @@ function _createImpressionObject(bid, conf) { } function _parseSlotParam(paramName, paramValue) { - if (!isStr(paramValue)) { + if (!utils.isStr(paramValue)) { paramValue && _logWarn('Ignoring param key: ' + paramName + ', expects string-value, found ' + typeof paramValue); return UNDEFINED; } @@ -520,7 +520,7 @@ function _parseAdSlot(bid) { } function _cleanSlotName(slotName) { - if (isStr(slotName)) { + if (utils.isStr(slotName)) { return slotName.replace(/^\s+/g, '').replace(/\s+$/g, ''); } return ''; @@ -705,7 +705,7 @@ function _createBannerRequest(bid) { var sizes = bid.mediaTypes.banner.sizes; var format = []; var bannerObj; - if (sizes !== UNDEFINED && isArray(sizes)) { + if (sizes !== UNDEFINED && utils.isArray(sizes)) { bannerObj = {}; if (!bid.params.width && !bid.params.height) { if (sizes.length === 0) { @@ -734,7 +734,7 @@ function _createBannerRequest(bid) { } } bannerObj.pos = 0; - bannerObj.topframe = inIframe() ? 0 : 1; + bannerObj.topframe = utils.inIframe() ? 0 : 1; } else { _logWarn('Error: mediaTypes.banner.size missing for adunit: ' + bid.params.adUnit + '. Ignoring the banner impression in the adunit.'); bannerObj = UNDEFINED; @@ -745,22 +745,22 @@ function _createBannerRequest(bid) { // various error levels are not always used // eslint-disable-next-line no-unused-vars function _logMessage(textValue, objectValue) { - logMessage('PubWise: ' + textValue, objectValue); + utils.logMessage('PubWise: ' + textValue, objectValue); } // eslint-disable-next-line no-unused-vars function _logInfo(textValue, objectValue) { - logInfo('PubWise: ' + textValue, objectValue); + utils.logInfo('PubWise: ' + textValue, objectValue); } // eslint-disable-next-line no-unused-vars function _logWarn(textValue, objectValue) { - logWarn('PubWise: ' + textValue, objectValue); + utils.logWarn('PubWise: ' + textValue, objectValue); } // eslint-disable-next-line no-unused-vars function _logError(textValue, objectValue) { - logError('PubWise: ' + textValue, objectValue); + utils.logError('PubWise: ' + textValue, objectValue); } // function _decorateLog() { diff --git a/modules/pubxBidAdapter.js b/modules/pubxBidAdapter.js index 18d2bb11404..c7b63d3f7f7 100644 --- a/modules/pubxBidAdapter.js +++ b/modules/pubxBidAdapter.js @@ -1,5 +1,5 @@ -import { deepSetValue } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'pubx'; const BID_ENDPOINT = 'https://api.primecaster.net/adlogue/api/slot/bid'; @@ -43,7 +43,7 @@ export const spec = { ad: body.adm }; if (body.adomains) { - deepSetValue(bidResponse, 'meta.advertiserDomains', Array.isArray(body.adomains) ? body.adomains : [body.adomains]); + utils.deepSetValue(bidResponse, 'meta.advertiserDomains', Array.isArray(body.adomains) ? body.adomains : [body.adomains]); } bidResponses.push(bidResponse); } else {}; diff --git a/modules/pubxaiAnalyticsAdapter.js b/modules/pubxaiAnalyticsAdapter.js index 669bd062206..98b4dec1dca 100644 --- a/modules/pubxaiAnalyticsAdapter.js +++ b/modules/pubxaiAnalyticsAdapter.js @@ -1,8 +1,8 @@ -import { deepAccess, getGptSlotInfoForAdUnitCode, parseSizesInput, getWindowLocation, buildUrl } from '../src/utils.js'; import { ajax } from '../src/ajax.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; +import * as utils from '../src/utils.js'; const emptyUrl = ''; const analyticsType = 'endpoint'; @@ -21,14 +21,6 @@ let events = { deviceDetail: {} }; -function getStorage() { - try { - return window.top['sessionStorage']; - } catch (e) { - return null; - } -} - var pubxaiAnalyticsAdapter = Object.assign(adapter( { emptyUrl, @@ -42,7 +34,7 @@ var pubxaiAnalyticsAdapter = Object.assign(adapter( events.auctionInit = args; events.floorDetail = {}; events.bids = []; - const floorData = deepAccess(args, 'bidderRequests.0.bids.0.floorData'); + const floorData = utils.deepAccess(args, 'bidderRequests.0.bids.0.floorData'); if (typeof floorData !== 'undefined') { Object.assign(events.floorDetail, floorData); } @@ -65,7 +57,7 @@ function mapBidResponse(bidResponse, status) { if (typeof bidResponse !== 'undefined') { let bid = { adUnitCode: bidResponse.adUnitCode, - gptSlotCode: getGptSlotInfoForAdUnitCode(bidResponse.adUnitCode).gptSlot || null, + gptSlotCode: utils.getGptSlotInfoForAdUnitCode(bidResponse.adUnitCode).gptSlot || null, auctionId: bidResponse.auctionId, bidderCode: bidResponse.bidder, cpm: bidResponse.cpm, @@ -85,7 +77,7 @@ function mapBidResponse(bidResponse, status) { Object.assign(bid, { bidId: status === 'timeout' ? bidResponse.bidId : bidResponse.requestId, renderStatus: status === 'timeout' ? 3 : 2, - sizes: parseSizesInput(bidResponse.size).toString(), + sizes: utils.parseSizesInput(bidResponse.size).toString(), }); events.bids.push(bid); } else { @@ -93,7 +85,7 @@ function mapBidResponse(bidResponse, status) { bidId: bidResponse.requestId, floorProvider: events.floorDetail ? events.floorDetail.floorProvider : null, isWinningBid: true, - placementId: bidResponse.params ? deepAccess(bidResponse, 'params.0.placementId') : null, + placementId: bidResponse.params ? utils.deepAccess(bidResponse, 'params.0.placementId') : null, renderedSize: bidResponse.size, renderStatus: 4 }); @@ -139,26 +131,17 @@ pubxaiAnalyticsAdapter.shouldFireEventRequest = function (samplingRate = 1) { function send(data, status) { if (pubxaiAnalyticsAdapter.shouldFireEventRequest(initOptions.samplingRate)) { - let location = getWindowLocation(); - const storage = getStorage(); + let location = utils.getWindowLocation(); data.initOptions = initOptions; - data.pageDetail = {}; - Object.assign(data.pageDetail, { - host: location.host, - path: location.pathname, - search: location.search - }); if (typeof data !== 'undefined' && typeof data.auctionInit !== 'undefined') { - data.pageDetail.adUnitCount = data.auctionInit.adUnitCodes ? data.auctionInit.adUnitCodes.length : null; + Object.assign(data.pageDetail, { + host: location.host, + path: location.pathname, + search: location.search, + adUnitCount: data.auctionInit.adUnitCodes ? data.auctionInit.adUnitCodes.length : null + }); data.initOptions.auctionId = data.auctionInit.auctionId; delete data.auctionInit; - - data.pmcDetail = {} - Object.assign(data.pmcDetail, { - bidDensity: storage ? storage.getItem('pbx:dpbid') : null, - maxBid: storage ? storage.getItem('pbx:mxbid') : null, - auctionId: storage ? storage.getItem('pbx:aucid') : null, - }); } data.deviceDetail = {}; Object.assign(data.deviceDetail, { @@ -167,8 +150,7 @@ function send(data, status) { deviceOS: getOS(), browser: getBrowser() }); - - let pubxaiAnalyticsRequestUrl = buildUrl({ + let pubxaiAnalyticsRequestUrl = utils.buildUrl({ protocol: 'https', hostname: (initOptions && initOptions.hostName) || defaultHost, pathname: status == 'bidwon' ? winningBidPath : auctionPath, diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index c0280e944ae..adea33fc3b9 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -1,5 +1,5 @@ /* eslint dot-notation:0, quote-props:0 */ -import { convertTypes, deepAccess, isArray, logError, isFn } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { Renderer } from '../src/Renderer.js'; @@ -77,7 +77,7 @@ export const spec = { } }, transformBidParams: function(params, isOpenRtb) { - return convertTypes({ + return utils.convertTypes({ 'cf': 'string', 'cp': 'number', 'ct': 'number' @@ -124,8 +124,8 @@ function bidResponseAvailable(request, response) { }; if (idToImpMap[id].video) { // for outstream, a renderer is specified - if (idToSlotConfig[id] && deepAccess(idToSlotConfig[id], 'mediaTypes.video.context') === 'outstream') { - bid.renderer = outstreamRenderer(deepAccess(idToSlotConfig[id], 'renderer.options'), deepAccess(idToBidMap[id], 'ext.outstream')); + if (idToSlotConfig[id] && utils.deepAccess(idToSlotConfig[id], 'mediaTypes.video.context') === 'outstream') { + bid.renderer = outstreamRenderer(utils.deepAccess(idToSlotConfig[id], 'renderer.options'), utils.deepAccess(idToBidMap[id], 'ext.outstream')); } bid.vastXml = idToBidMap[id].adm; bid.mediaType = 'video'; @@ -178,9 +178,9 @@ function banner(slot) { * Produce openrtb format objects based on the sizes configured for the slot. */ function parseSizes(slot) { - const sizes = deepAccess(slot, 'mediaTypes.banner.sizes'); - if (sizes && isArray(sizes)) { - return sizes.filter(sz => isArray(sz) && sz.length === 2).map(sz => ({ + const sizes = utils.deepAccess(slot, 'mediaTypes.banner.sizes'); + if (sizes && utils.isArray(sizes)) { + return sizes.filter(sz => utils.isArray(sz) && sz.length === 2).map(sz => ({ w: sz[0], h: sz[1] })); @@ -387,7 +387,7 @@ function parse(rawResponse) { return JSON.parse(rawResponse); } } catch (ex) { - logError('pulsepointLite.safeParse', 'ERROR', ex); + utils.logError('pulsepointLite.safeParse', 'ERROR', ex); } return null; } @@ -419,14 +419,55 @@ function user(bidRequest, bidderRequest) { } } if (bidRequest) { - let eids = bidRequest.userIdAsEids; - if (eids) { - ext.eids = eids; + if (bidRequest.userId) { + ext.eids = []; + addExternalUserId(ext.eids, bidRequest.userId.pubcid, 'pubcommon'); + addExternalUserId(ext.eids, bidRequest.userId.britepoolid, 'britepool.com'); + addExternalUserId(ext.eids, bidRequest.userId.criteoId, 'criteo'); + addExternalUserId(ext.eids, bidRequest.userId.idl_env, 'identityLink'); + addExternalUserId(ext.eids, utils.deepAccess(bidRequest, 'userId.id5id.uid'), 'id5-sync.com', utils.deepAccess(bidRequest, 'userId.id5id.ext')); + addExternalUserId(ext.eids, utils.deepAccess(bidRequest, 'userId.parrableId.eid'), 'parrable.com'); + // liveintent + if (bidRequest.userId.lipb && bidRequest.userId.lipb.lipbid) { + addExternalUserId(ext.eids, bidRequest.userId.lipb.lipbid, 'liveintent.com'); + } + // TTD + addExternalUserId(ext.eids, bidRequest.userId.tdid, 'adserver.org', { + rtiPartner: 'TDID' + }); + // digitrust + const digitrustResponse = bidRequest.userId.digitrustid; + if (digitrustResponse && digitrustResponse.data) { + var digitrust = {}; + if (digitrustResponse.data.id) { + digitrust.id = digitrustResponse.data.id; + } + if (digitrustResponse.data.keyv) { + digitrust.keyv = digitrustResponse.data.keyv; + } + ext.digitrust = digitrust; + } } } return { ext }; } +/** + * Produces external userid object in ortb 3.0 model. + */ +function addExternalUserId(eids, id, source, uidExt) { + if (id) { + var uid = { id }; + if (uidExt) { + uid.ext = uidExt; + } + eids.push({ + source, + uids: [ uid ] + }); + } +} + /** * Produces the regulations ortb object */ @@ -485,7 +526,7 @@ function nativeResponse(imp, bid) { function bidFloor(slot) { let floor = slot.params.bidfloor; - if (isFn(slot.getFloor)) { + if (utils.isFn(slot.getFloor)) { const floorData = slot.getFloor({ mediaType: slot.mediaTypes.banner ? 'banner' : slot.mediaTypes.video ? 'video' : 'Native', size: '*', diff --git a/modules/pxyzBidAdapter.js b/modules/pxyzBidAdapter.js index e144eb84a01..9baff4d1533 100644 --- a/modules/pxyzBidAdapter.js +++ b/modules/pxyzBidAdapter.js @@ -1,6 +1,6 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; -import { logInfo, logError, isArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'pxyz'; const URL = 'https://ads.playground.xyz/host-config/prebid?v=2'; @@ -61,15 +61,15 @@ export const spec = { if (bidderRequest && bidderRequest.gdprConsent) { const gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; const consentString = bidderRequest.gdprConsent.consentString; - logInfo(`PXYZ: GDPR applies ${gdpr}`); - logInfo(`PXYZ: GDPR consent string ${consentString}`); + utils.logInfo(`PXYZ: GDPR applies ${gdpr}`); + utils.logInfo(`PXYZ: GDPR consent string ${consentString}`); payload.Regs.ext.gdpr = gdpr; payload.User = { ext: { consent: consentString } }; } // CCPA if (bidderRequest && bidderRequest.uspConsent) { - logInfo(`PXYZ: USP Consent ${bidderRequest.uspConsent}`); + utils.logInfo(`PXYZ: USP Consent ${bidderRequest.uspConsent}`); payload.Regs.ext['us_privacy'] = bidderRequest.uspConsent; } @@ -95,14 +95,14 @@ export const spec = { let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; - logError(errorMessage); + utils.logError(errorMessage); } return bids; } - if (!isArray(serverResponse.seatbid)) { + if (!utils.isArray(serverResponse.seatbid)) { let errorMessage = `in response for ${bidderRequest.bidderCode} adapter `; - logError(errorMessage += 'Malformed seatbid response'); + utils.logError(errorMessage += 'Malformed seatbid response'); return bids; } diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 449c7d12d6f..ecb5ad3176e 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,9 +1,9 @@ -import {deepAccess, isArray, isEmpty, logError, logInfo} from '../src/utils.js'; -import {ajax} from '../src/ajax.js'; -import {config} from '../src/config.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {find} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { ajax } from '../src/ajax.js'; +import { config } from '../src/config.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import find from 'core-js-pure/features/array/find.js'; const BIDDER_CODE = 'quantcast'; const DEFAULT_BID_FLOOR = 0.0000000001; @@ -21,11 +21,11 @@ export const QUANTCAST_PROTOCOL = 'https'; export const QUANTCAST_PORT = '8443'; export const QUANTCAST_FPA = '__qca'; -export const storage = getStorageManager({gvlid: QUANTCAST_VENDOR_ID, bidderCode: BIDDER_CODE}); +export const storage = getStorageManager(QUANTCAST_VENDOR_ID, BIDDER_CODE); function makeVideoImp(bid) { - const videoInMediaType = deepAccess(bid, 'mediaTypes.video') || {}; - const videoInParams = deepAccess(bid, 'params.video') || {}; + const videoInMediaType = utils.deepAccess(bid, 'mediaTypes.video') || {}; + const videoInParams = utils.deepAccess(bid, 'params.video') || {}; const video = Object.assign({}, videoInParams, videoInMediaType); if (video.playerSize) { @@ -142,10 +142,10 @@ export const spec = { */ buildRequests(bidRequests, bidderRequest) { const bids = bidRequests || []; - const gdprConsent = deepAccess(bidderRequest, 'gdprConsent') || {}; - const uspConsent = deepAccess(bidderRequest, 'uspConsent'); - const referrer = deepAccess(bidderRequest, 'refererInfo.referer'); - const page = deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || config.getConfig('pageUrl') || deepAccess(window, 'location.href'); + const gdprConsent = utils.deepAccess(bidderRequest, 'gdprConsent') || {}; + const uspConsent = utils.deepAccess(bidderRequest, 'uspConsent'); + const referrer = utils.deepAccess(bidderRequest, 'refererInfo.referer'); + const page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href'); const domain = getDomain(page); // Check for GDPR consent for purpose 1, and drop request if consent has not been given @@ -153,11 +153,11 @@ export const spec = { if (gdprConsent.gdprApplies) { if (gdprConsent.vendorData) { if (gdprConsent.apiVersion === 1 && !checkTCFv1(gdprConsent.vendorData)) { - logInfo(`${BIDDER_CODE}: No purpose 1 consent for TCF v1`); + utils.logInfo(`${BIDDER_CODE}: No purpose 1 consent for TCF v1`); return; } if (gdprConsent.apiVersion === 2 && !checkTCFv2(gdprConsent.vendorData)) { - logInfo(`${BIDDER_CODE}: No purpose 1 consent for TCF v2`); + utils.logInfo(`${BIDDER_CODE}: No purpose 1 consent for TCF v2`); return; } } @@ -174,7 +174,7 @@ export const spec = { imp = makeBannerImp(bid); } else { // Unsupported mediaType - logInfo(`${BIDDER_CODE}: No supported mediaTypes found in ${JSON.stringify(bid.mediaTypes)}`); + utils.logInfo(`${BIDDER_CODE}: No supported mediaTypes found in ${JSON.stringify(bid.mediaTypes)}`); return; } } else { @@ -231,18 +231,18 @@ export const spec = { */ interpretResponse(serverResponse) { if (serverResponse === undefined) { - logError('Server Response is undefined'); + utils.logError('Server Response is undefined'); return []; } const response = serverResponse['body']; if (response === undefined || !response.hasOwnProperty('bids')) { - logError('Sub-optimal JSON received from Quantcast server'); + utils.logError('Sub-optimal JSON received from Quantcast server'); return []; } - if (isEmpty(response.bids)) { + if (utils.isEmpty(response.bids)) { // Shortcut response handling if no bids are present return []; } @@ -271,7 +271,7 @@ export const spec = { result['dealId'] = dealId; } - if (meta !== undefined && meta.advertiserDomains && isArray(meta.advertiserDomains)) { + if (meta !== undefined && meta.advertiserDomains && utils.isArray(meta.advertiserDomains)) { result.meta = {}; result.meta.advertiserDomains = meta.advertiserDomains; } @@ -289,11 +289,11 @@ export const spec = { const syncs = [] if (!hasUserSynced && syncOptions.pixelEnabled) { const responseWithUrl = find(serverResponses, serverResponse => - deepAccess(serverResponse.body, 'userSync.url') + utils.deepAccess(serverResponse.body, 'userSync.url') ); if (responseWithUrl) { - const url = deepAccess(responseWithUrl.body, 'userSync.url') + const url = utils.deepAccess(responseWithUrl.body, 'userSync.url') syncs.push({ type: 'image', url: url diff --git a/modules/radsBidAdapter.js b/modules/radsBidAdapter.js index fee5daa3fb4..5cc88440629 100644 --- a/modules/radsBidAdapter.js +++ b/modules/radsBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; @@ -216,7 +216,7 @@ function prepareExtraParams(params, payload, bidderRequest, bidRequest) { * @returns {boolean} True if it's a banner bid */ function isBannerRequest(bid) { - return bid.mediaType === 'banner' || !!deepAccess(bid, 'mediaTypes.banner') || !isVideoRequest(bid); + return bid.mediaType === 'banner' || !!utils.deepAccess(bid, 'mediaTypes.banner') || !isVideoRequest(bid); } /** @@ -226,7 +226,7 @@ function isBannerRequest(bid) { * @returns {boolean} True if it's a video bid */ function isVideoRequest(bid) { - return bid.mediaType === 'video' || !!deepAccess(bid, 'mediaTypes.video'); + return bid.mediaType === 'video' || !!utils.deepAccess(bid, 'mediaTypes.video'); } /** @@ -236,7 +236,7 @@ function isVideoRequest(bid) { * @returns {object} True if it's a video bid */ function getVideoSizes(bid) { - return parseSizes(deepAccess(bid, 'mediaTypes.video.playerSize') || bid.sizes); + return parseSizes(utils.deepAccess(bid, 'mediaTypes.video.playerSize') || bid.sizes); } /** @@ -246,7 +246,7 @@ function getVideoSizes(bid) { * @returns {object} True if it's a video bid */ function getBannerSizes(bid) { - return parseSizes(deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes); + return parseSizes(utils.deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes); } /** diff --git a/modules/readpeakBidAdapter.js b/modules/readpeakBidAdapter.js index 099e1fb6332..31e430d79f9 100644 --- a/modules/readpeakBidAdapter.js +++ b/modules/readpeakBidAdapter.js @@ -1,7 +1,7 @@ import { logError, replaceAuctionPrice, parseUrl } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; -import { NATIVE, BANNER } from '../src/mediaTypes.js'; +import { NATIVE } from '../src/mediaTypes.js'; export const ENDPOINT = 'https://app.readpeak.com/header/prebid'; @@ -19,9 +19,10 @@ const BIDDER_CODE = 'readpeak'; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [NATIVE, BANNER], + supportedMediaTypes: [NATIVE], - isBidRequestValid: bid => !!(bid && bid.params && bid.params.publisherId), + isBidRequestValid: bid => + !!(bid && bid.params && bid.params.publisherId && bid.nativeParams), buildRequests: (bidRequests, bidderRequest) => { const currencyObj = config.getConfig('currency'); @@ -30,7 +31,8 @@ export const spec = { const request = { id: bidRequests[0].bidderRequestId, imp: bidRequests - .map(slot => impression(slot)), + .map(slot => impression(slot)) + .filter(imp => imp.native != null), site: site(bidRequests, bidderRequest), app: app(bidRequests), device: device(), @@ -94,16 +96,10 @@ function bidResponseAvailable(bidRequest, bidResponse) { creativeId: idToBidMap[id].crid, ttl: 300, netRevenue: true, - mediaType: idToImpMap[id].native ? NATIVE : BANNER, - currency: bidResponse.cur + mediaType: NATIVE, + currency: bidResponse.cur, + native: nativeResponse(idToImpMap[id], idToBidMap[id]) }; - if (idToImpMap[id].native) { - bid.native = nativeResponse(idToImpMap[id], idToBidMap[id]); - } else if (idToImpMap[id].banner) { - bid.ad = idToBidMap[id].adm - bid.width = idToBidMap[id].w - bid.height = idToBidMap[id].h - } if (idToBidMap[id].adomain) { bid.meta = { advertiserDomains: idToBidMap[id].adomain @@ -125,19 +121,13 @@ function impression(slot) { }); bidFloorFromModule = floorInfo.currency === 'USD' ? floorInfo.floor : undefined; } - const imp = { + return { id: slot.bidId, + native: nativeImpression(slot), bidfloor: bidFloorFromModule || slot.params.bidfloor || 0, bidfloorcur: (bidFloorFromModule && 'USD') || slot.params.bidfloorcur || 'USD', tagId: slot.params.tagId || '0' }; - - if (slot.mediaTypes.native) { - imp.native = nativeImpression(slot); - } else if (slot.mediaTypes.banner) { - imp.banner = bannerImpression(slot); - } - return imp } function nativeImpression(slot) { @@ -228,15 +218,6 @@ function dataAsset(id, params, type, defaultLen) { : null; } -function bannerImpression(slot) { - var sizes = slot.mediaTypes.banner.sizes || slot.sizes; - return { - format: sizes.map((s) => ({ w: s[0], h: s[1] })), - w: sizes[0][0], - h: sizes[0][1], - } -} - function site(bidRequests, bidderRequest) { const url = config.getConfig('pageUrl') || diff --git a/modules/readpeakBidAdapter.md b/modules/readpeakBidAdapter.md index 8f8e7369ea5..da250e7f77a 100644 --- a/modules/readpeakBidAdapter.md +++ b/modules/readpeakBidAdapter.md @@ -15,48 +15,17 @@ Please reach out to your account team or hello@readpeak.com for more information # Test Parameters ```javascript - var adUnits = [ - { - code: '/19968336/prebid_native_example_2', - mediaTypes: { - native: { - title: { - required: true - }, - image: { - required: true - }, - body: { - required: true - }, - } + var adUnits = [{ + code: '/19968336/prebid_native_example_2', + mediaTypes: { native: { type: 'image' } }, + bids: [{ + bidder: 'readpeak', + params: { + bidfloor: 5.00, + publisherId: 'test', + siteId: 'test', + tagId: 'test-tag-1' }, - bids: [{ - bidder: 'readpeak', - params: { - bidfloor: 5.00, - publisherId: 'test', - siteId: 'test', - tagId: 'test-tag-1' - }, - }] - }, - { - code: '/19968336/prebid_banner_example_2', - mediaTypes: { - banner: { - sizes: [[640, 320], [300, 600]], - } - }, - bids: [{ - bidder: 'readpeak', - params: { - bidfloor: 5.00, - publisherId: 'test', - siteId: 'test', - tagId: 'test-tag-2' - }, - }] - } - ]; + }] + }]; ``` diff --git a/modules/realvuAnalyticsAdapter.js b/modules/realvuAnalyticsAdapter.js index 832e907893c..5540d136dea 100644 --- a/modules/realvuAnalyticsAdapter.js +++ b/modules/realvuAnalyticsAdapter.js @@ -3,9 +3,11 @@ import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; import { getStorageManager } from '../src/storageManager.js'; -import { logMessage, logError } from '../src/utils.js'; + const storage = getStorageManager(); +const utils = require('../src/utils.js'); + let realvuAnalyticsAdapter = adapter({ global: 'realvuAnalytics', handler: 'on', @@ -399,7 +401,7 @@ export let lib = { // @if NODE_ENV='debug' let now = new Date(); let msg = (now.getTime() - time0) / 1000 + ' RENDERED ' + a.unit_id; - logMessage(msg); + utils.logMessage(msg); // @endif let rpt = z.bids_rpt(a, true); z.track(a, 'rend', rpt); @@ -883,7 +885,7 @@ realvuAnalyticsAdapter.originEnableAnalytics = realvuAnalyticsAdapter.enableAnal realvuAnalyticsAdapter.enableAnalytics = function (config) { _options = config.options; if (typeof (_options.partnerId) == 'undefined' || _options.partnerId == '') { - logError('Missed realvu.com partnerId parameter', 101, 'Missed partnerId parameter'); + utils.logError('Missed realvu.com partnerId parameter', 101, 'Missed partnerId parameter'); } realvuAnalyticsAdapter.originEnableAnalytics(config); return _options.partnerId; @@ -903,7 +905,7 @@ realvuAnalyticsAdapter.track = function ({eventType, args}) { ' creativei_id=' + args.creative_id; } // msg += '\nargs=' + JSON.stringify(args) + '
'; - logMessage(msg); + utils.logMessage(msg); // @endif const boost = window.top1.realvu_aa; @@ -933,7 +935,7 @@ realvuAnalyticsAdapter.track = function ({eventType, args}) { realvuAnalyticsAdapter.checkIn = function (bid, partnerId) { // find (or add if not registered yet) the unit in boost if (typeof (partnerId) == 'undefined' || partnerId == '') { - logError('Missed realvu.com partnerId parameter', 102, 'Missed partnerId parameter'); + utils.logError('Missed realvu.com partnerId parameter', 102, 'Missed partnerId parameter'); } let a = window.top1.realvu_aa.check({ unit_id: bid.adUnitCode, diff --git a/modules/reconciliationRtdProvider.js b/modules/reconciliationRtdProvider.js index 9b6a3d7aca3..f8636862d4c 100644 --- a/modules/reconciliationRtdProvider.js +++ b/modules/reconciliationRtdProvider.js @@ -16,10 +16,10 @@ * @property {?boolean} allowAccess */ -import {submodule} from '../src/hook.js'; -import {ajaxBuilder} from '../src/ajax.js'; -import {generateUUID, isGptPubadsDefined, logError, timestamp} from '../src/utils.js'; -import {find} from '../src/polyfill.js'; +import { submodule } from '../src/hook.js'; +import { ajaxBuilder } from '../src/ajax.js'; +import * as utils from '../src/utils.js'; +import find from 'core-js-pure/features/array/find.js'; /** @type {Object} */ const MessageType = { @@ -52,7 +52,7 @@ function handleAdMessage(e) { } if (data.type === MessageType.IMPRESSION_REQUEST) { - if (isGptPubadsDefined()) { + if (utils.isGptPubadsDefined()) { // 1. Find the last iframed window before window.top where the tracker was injected // (the tracker could be injected in nested iframes) const adWin = getTopIFrameWin(e.source); @@ -65,7 +65,7 @@ function handleAdMessage(e) { adDeliveryId = adSlot.getTargeting('RSDK_ADID'); adDeliveryId = adDeliveryId.length ? adDeliveryId[0] - : `${timestamp()}-${generateUUID()}`; + : `${utils.timestamp()}-${utils.generateUUID()}`; } } } @@ -136,7 +136,7 @@ export function getTopIFrameWin(win, topWin) { * @return {Object[]} slot GoogleTag slots */ function getAllSlots() { - return isGptPubadsDefined() && window.googletag.pubads().getSlots(); + return utils.isGptPubadsDefined() && window.googletag.pubads().getSlots(); } /** @@ -246,7 +246,7 @@ function getReconciliationData(adUnitsCodes) { const adSlot = getSlotByCode(adUnitCode); const adUnitId = adSlot ? adSlot.getAdUnitPath() : adUnitCode; - const adDeliveryId = `${timestamp()}-${generateUUID()}`; + const adDeliveryId = `${utils.timestamp()}-${utils.generateUUID()}`; dataToReturn[adUnitCode] = { RSDK_AUID: adUnitId, @@ -287,7 +287,7 @@ function init(moduleConfig) { _moduleParams = Object.assign({}, DEFAULT_PARAMS, params); initListeners(); } else { - logError('missing params for Reconciliation provider'); + utils.logError('missing params for Reconciliation provider'); } return true; } diff --git a/modules/relaidoBidAdapter.js b/modules/relaidoBidAdapter.js index db381555ef9..14effa263a3 100644 --- a/modules/relaidoBidAdapter.js +++ b/modules/relaidoBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, logWarn, getBidIdParameter, parseQueryStringParameters, triggerPixel, generateUUID, isArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { Renderer } from '../src/Renderer.js'; @@ -6,112 +6,89 @@ import { getStorageManager } from '../src/storageManager.js'; const BIDDER_CODE = 'relaido'; const BIDDER_DOMAIN = 'api.relaido.jp'; -const ADAPTER_VERSION = '1.0.7'; +const ADAPTER_VERSION = '1.0.5'; const DEFAULT_TTL = 300; const UUID_KEY = 'relaido_uuid'; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); +const storage = getStorageManager(); function isBidRequestValid(bid) { - if (!deepAccess(bid, 'params.placementId')) { - logWarn('placementId param is reqeuired.'); + if (!utils.deepAccess(bid, 'params.placementId')) { + utils.logWarn('placementId param is reqeuired.'); return false; } if (hasVideoMediaType(bid) && isVideoValid(bid)) { return true; } else { - logWarn('Invalid mediaType video.'); + utils.logWarn('Invalid mediaType video.'); } if (hasBannerMediaType(bid) && isBannerValid(bid)) { return true; } else { - logWarn('Invalid mediaType banner.'); + utils.logWarn('Invalid mediaType banner.'); } return false; } function buildRequests(validBidRequests, bidderRequest) { - const bids = []; - let imuid = null; - let bidDomain = null; - let bidder = null; - let count = null; + let bidRequests = []; for (let i = 0; i < validBidRequests.length; i++) { const bidRequest = validBidRequests[i]; + const placementId = utils.getBidIdParameter('placementId', bidRequest.params); + const bidDomain = bidRequest.params.domain || BIDDER_DOMAIN; + const bidUrl = `https://${bidDomain}/bid/v1/prebid/${placementId}`; + const uuid = getUuid(); let mediaType = ''; let width = 0; let height = 0; if (hasVideoMediaType(bidRequest) && isVideoValid(bidRequest)) { - const playerSize = getValidSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize')); + const playerSize = getValidSizes(utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize')); width = playerSize[0][0]; height = playerSize[0][1]; mediaType = VIDEO; } else if (hasBannerMediaType(bidRequest) && isBannerValid(bidRequest)) { - const sizes = getValidSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes')); + const sizes = getValidSizes(utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes')); width = sizes[0][0]; height = sizes[0][1]; mediaType = BANNER; } - if (!imuid) { - const pickImuid = deepAccess(bidRequest, 'userId.imuid'); - if (pickImuid) { - imuid = pickImuid; - } - } - - if (!bidDomain) { - bidDomain = bidRequest.params.domain; - } - - if (!bidder) { - bidder = bidRequest.bidder - } - - if (!bidder) { - bidder = bidRequest.bidder - } - - if (!count) { - count = bidRequest.bidRequestsCount; - } - - bids.push({ - bid_id: bidRequest.bidId, - placement_id: getBidIdParameter('placementId', bidRequest.params), - transaction_id: bidRequest.transactionId, - bidder_request_id: bidRequest.bidderRequestId, + let payload = { + version: ADAPTER_VERSION, + timeout_ms: bidderRequest.timeout, ad_unit_code: bidRequest.adUnitCode, auction_id: bidRequest.auctionId, - player: bidRequest.params.player, + bidder: bidRequest.bidder, + bidder_request_id: bidRequest.bidderRequestId, + bid_requests_count: bidRequest.bidRequestsCount, + bid_id: bidRequest.bidId, + transaction_id: bidRequest.transactionId, + media_type: mediaType, + uuid: uuid, width: width, - height: height, - media_type: mediaType + height: height + }; + + // It may not be encoded, so add it at the end of the payload + payload.ref = bidderRequest.refererInfo.referer; + + bidRequests.push({ + method: 'GET', + url: bidUrl, + data: payload, + options: { + withCredentials: true + }, + bidId: bidRequest.bidId, + player: bidRequest.params.player, + width: payload.width, + height: payload.height, + mediaType: payload.media_type }); } - - const data = JSON.stringify({ - version: ADAPTER_VERSION, - bids: bids, - timeout_ms: bidderRequest.timeout, - bidder: bidder, - bid_requests_count: count, - uuid: getUuid(), - pv: '$prebid.version$', - imuid: imuid, - ref: bidderRequest.refererInfo.referer - }) - - return { - method: 'POST', - url: `https://${bidDomain || BIDDER_DOMAIN}/bid/v1/sprebid`, - options: { - withCredentials: true - }, - data: data - }; + return bidRequests; } function interpretResponse(serverResponse, bidRequest) { @@ -121,39 +98,35 @@ function interpretResponse(serverResponse, bidRequest) { return []; } - for (const res of body.ads) { - const playerUrl = res.playerUrl || bidRequest.player || body.playerUrl; - let bidResponse = { - requestId: res.bidId, - width: res.width, - height: res.height, - cpm: res.price, - currency: res.currency, - creativeId: res.creativeId, - playerUrl: playerUrl, - dealId: body.dealId || '', - ttl: body.ttl || DEFAULT_TTL, - netRevenue: true, - mediaType: res.mediaType || VIDEO, - meta: { - advertiserDomains: res.adomain || [], - mediaType: VIDEO - } - }; - - if (bidResponse.mediaType === VIDEO) { - bidResponse.vastXml = res.vast; - bidResponse.renderer = newRenderer(res.bidId, playerUrl); - } else { - const playerTag = createPlayerTag(playerUrl); - const renderTag = createRenderTag(res.width, res.height, res.vast); - bidResponse.ad = `
${playerTag}${renderTag}
`; + const playerUrl = bidRequest.player || body.playerUrl; + const mediaType = bidRequest.mediaType || VIDEO; + + let bidResponse = { + requestId: bidRequest.bidId, + width: bidRequest.width, + height: bidRequest.height, + cpm: body.price, + currency: body.currency, + creativeId: body.creativeId, + dealId: body.dealId || '', + ttl: body.ttl || DEFAULT_TTL, + netRevenue: true, + mediaType: mediaType, + meta: { + advertiserDomains: body.adomain || [], + mediaType: VIDEO } - bidResponses.push(bidResponse); + }; + if (mediaType === VIDEO) { + bidResponse.vastXml = body.vast; + bidResponse.renderer = newRenderer(bidRequest.bidId, playerUrl); + } else { + const playerTag = createPlayerTag(playerUrl); + const renderTag = createRenderTag(bidRequest.width, bidRequest.height, body.vast); + bidResponse.ad = `
${playerTag}${renderTag}
`; } + bidResponses.push(bidResponse); - // eslint-disable-next-line no-console - console.log(JSON.stringify(bidResponses)); return bidResponses; } @@ -163,7 +136,7 @@ function getUserSyncs(syncOptions, serverResponses) { } let syncUrl = `https://${BIDDER_DOMAIN}/tr/v1/prebid/sync.html`; if (serverResponses.length > 0) { - syncUrl = deepAccess(serverResponses, '0.body.syncUrl') || syncUrl; + syncUrl = utils.deepAccess(serverResponses, '0.body.syncUrl') || syncUrl; } return [{ type: 'iframe', @@ -172,34 +145,34 @@ function getUserSyncs(syncOptions, serverResponses) { } function onBidWon(bid) { - let query = parseQueryStringParameters({ - placement_id: deepAccess(bid, 'params.0.placementId'), - creative_id: deepAccess(bid, 'creativeId'), - price: deepAccess(bid, 'cpm'), - auction_id: deepAccess(bid, 'auctionId'), - bid_id: deepAccess(bid, 'requestId'), - ad_id: deepAccess(bid, 'adId'), - ad_unit_code: deepAccess(bid, 'adUnitCode'), + let query = utils.parseQueryStringParameters({ + placement_id: utils.deepAccess(bid, 'params.0.placementId'), + creative_id: utils.deepAccess(bid, 'creativeId'), + price: utils.deepAccess(bid, 'cpm'), + auction_id: utils.deepAccess(bid, 'auctionId'), + bid_id: utils.deepAccess(bid, 'requestId'), + ad_id: utils.deepAccess(bid, 'adId'), + ad_unit_code: utils.deepAccess(bid, 'adUnitCode'), ref: window.location.href, }).replace(/\&$/, ''); - const bidDomain = deepAccess(bid, 'params.0.domain') || BIDDER_DOMAIN; + const bidDomain = utils.deepAccess(bid, 'params.0.domain') || BIDDER_DOMAIN; const burl = `https://${bidDomain}/tr/v1/prebid/win.gif?${query}`; - triggerPixel(burl); + utils.triggerPixel(burl); } function onTimeout(data) { - let query = parseQueryStringParameters({ - placement_id: deepAccess(data, '0.params.0.placementId'), - timeout: deepAccess(data, '0.timeout'), - auction_id: deepAccess(data, '0.auctionId'), - bid_id: deepAccess(data, '0.bidId'), - ad_unit_code: deepAccess(data, '0.adUnitCode'), + let query = utils.parseQueryStringParameters({ + placement_id: utils.deepAccess(data, '0.params.0.placementId'), + timeout: utils.deepAccess(data, '0.timeout'), + auction_id: utils.deepAccess(data, '0.auctionId'), + bid_id: utils.deepAccess(data, '0.bidId'), + ad_unit_code: utils.deepAccess(data, '0.adUnitCode'), version: ADAPTER_VERSION, ref: window.location.href, }).replace(/\&$/, ''); - const bidDomain = deepAccess(data, '0.params.0.domain') || BIDDER_DOMAIN; + const bidDomain = utils.deepAccess(data, '0.params.0.domain') || BIDDER_DOMAIN; const timeoutUrl = `https://${bidDomain}/tr/v1/prebid/timeout.gif?${query}`; - triggerPixel(timeoutUrl); + utils.triggerPixel(timeoutUrl); } function createPlayerTag(playerUrl) { @@ -226,7 +199,7 @@ function newRenderer(bidId, playerUrl) { try { renderer.setRender(outstreamRender); } catch (err) { - logWarn('renderer.setRender Error', err); + utils.logWarn('renderer.setRender Error', err); } return renderer; } @@ -247,7 +220,7 @@ function isBannerValid(bid) { if (!isMobile()) { return false; } - const sizes = getValidSizes(deepAccess(bid, 'mediaTypes.banner.sizes')); + const sizes = getValidSizes(utils.deepAccess(bid, 'mediaTypes.banner.sizes')); if (sizes.length > 0) { return true; } @@ -255,9 +228,9 @@ function isBannerValid(bid) { } function isVideoValid(bid) { - const playerSize = getValidSizes(deepAccess(bid, 'mediaTypes.video.playerSize')); + const playerSize = getValidSizes(utils.deepAccess(bid, 'mediaTypes.video.playerSize')); if (playerSize.length > 0) { - const context = deepAccess(bid, 'mediaTypes.video.context'); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); if (context && context === 'outstream') { return true; } @@ -268,7 +241,7 @@ function isVideoValid(bid) { function getUuid() { const id = storage.getCookie(UUID_KEY) if (id) return id; - const newId = generateUUID(); + const newId = utils.generateUUID(); storage.setCookie(UUID_KEY, newId); return newId; } @@ -282,18 +255,18 @@ export function isMobile() { } function hasBannerMediaType(bid) { - return !!deepAccess(bid, 'mediaTypes.banner'); + return !!utils.deepAccess(bid, 'mediaTypes.banner'); } function hasVideoMediaType(bid) { - return !!deepAccess(bid, 'mediaTypes.video'); + return !!utils.deepAccess(bid, 'mediaTypes.video'); } function getValidSizes(sizes) { let result = []; - if (sizes && isArray(sizes) && sizes.length > 0) { + if (sizes && utils.isArray(sizes) && sizes.length > 0) { for (let i = 0; i < sizes.length; i++) { - if (isArray(sizes[i]) && sizes[i].length == 2) { + if (utils.isArray(sizes[i]) && sizes[i].length == 2) { const width = sizes[i][0]; const height = sizes[i][1]; if (width == 1 && height == 1) { diff --git a/modules/resetdigitalBidAdapter.js b/modules/resetdigitalBidAdapter.js index 255ee32629c..7591c3391a0 100644 --- a/modules/resetdigitalBidAdapter.js +++ b/modules/resetdigitalBidAdapter.js @@ -1,7 +1,8 @@ -import { timestamp, deepAccess, getOrigin } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {getOrigin} from '../src/utils.js'; const BIDDER_CODE = 'resetdigital'; export const spec = { @@ -19,7 +20,7 @@ export const spec = { ? config.getConfig('userSync').syncsPerBidder : 5 const payload = { - start_time: timestamp(), + start_time: utils.timestamp(), language: window.navigator.userLanguage || window.navigator.language, site: { domain: getOrigin(), @@ -50,7 +51,7 @@ export const spec = { imp_id: req.transactionId, sizes: req.sizes, force_bid: req.params.forceBid, - media_types: deepAccess(req, 'mediaTypes') + media_types: utils.deepAccess(req, 'mediaTypes') }); } diff --git a/modules/revcontentBidAdapter.js b/modules/revcontentBidAdapter.js index 0888e5ad1b4..777060a5eb6 100644 --- a/modules/revcontentBidAdapter.js +++ b/modules/revcontentBidAdapter.js @@ -3,7 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE } from '../src/mediaTypes.js'; -import { triggerPixel, isFn, deepAccess, getAdUnitSizes, parseGPTSingleSizeArrayToRtbSize, _map } from '../src/utils.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'revcontent'; const NATIVE_PARAMS = { @@ -160,7 +160,7 @@ export const spec = { }, onBidWon: function (bid) { if (bid.nurl) { - triggerPixel(bid.nurl); + utils.triggerPixel(bid.nurl); } return true; } @@ -215,14 +215,14 @@ function extractHostname(url) { function buildImp(bid, id) { let bidfloor; - if (isFn(bid.getFloor)) { + if (utils.isFn(bid.getFloor)) { bidfloor = bid.getFloor({ currency: 'USD', mediaType: '*', size: '*' }).floor; } else { - bidfloor = deepAccess(bid, `params.bidfloor`) || 0.1; + bidfloor = utils.deepAccess(bid, `params.bidfloor`) || 0.1; } let imp = { @@ -236,17 +236,17 @@ function buildImp(bid, id) { secure: '1' }; - let bannerReq = deepAccess(bid, `mediaTypes.banner`); - let nativeReq = deepAccess(bid, `mediaTypes.native`); + let bannerReq = utils.deepAccess(bid, `mediaTypes.banner`); + let nativeReq = utils.deepAccess(bid, `mediaTypes.native`); if (bannerReq) { - let sizes = getAdUnitSizes(bid); + let sizes = utils.getAdUnitSizes(bid); imp.banner = { w: sizes[0][0], h: sizes[0][1], - format: sizes.map(wh => parseGPTSingleSizeArrayToRtbSize(wh)), + format: sizes.map(wh => utils.parseGPTSingleSizeArrayToRtbSize(wh)), } } else if (nativeReq) { - const assets = _map(bid.nativeParams, (bidParams, key) => { + const assets = utils._map(bid.nativeParams, (bidParams, key) => { const props = NATIVE_PARAMS[key]; const asset = { required: bidParams.required & 1 diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 9e378f2d2ed..36b2c369213 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -1,14 +1,12 @@ - 'use strict'; -import { deepAccess, getDNT, parseSizesInput, isArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; function RhythmOneBidAdapter() { this.code = 'rhythmone'; this.supportedMediaTypes = [VIDEO, BANNER]; - this.gvlid = 36; let SUPPORTED_VIDEO_PROTOCOLS = [2, 3, 5, 6]; let SUPPORTED_VIDEO_MIMES = ['video/mp4']; @@ -43,13 +41,13 @@ function RhythmOneBidAdapter() { impObj.bidfloor = 0; impObj.secure = isSecure; - if (deepAccess(BRs[i], 'mediaTypes.banner') || deepAccess(BRs[i], 'mediaType') === 'banner') { + if (utils.deepAccess(BRs[i], 'mediaTypes.banner') || utils.deepAccess(BRs[i], 'mediaType') === 'banner') { let banner = frameBanner(BRs[i]); if (banner) { impObj.banner = banner; } } - if (deepAccess(BRs[i], 'mediaTypes.video') || deepAccess(BRs[i], 'mediaType') === 'video') { + if (utils.deepAccess(BRs[i], 'mediaTypes.video') || utils.deepAccess(BRs[i], 'mediaType') === 'video') { impObj.video = frameVideo(BRs[i]); } if (!(impObj.banner || impObj.video)) { @@ -87,7 +85,7 @@ function RhythmOneBidAdapter() { return { ua: navigator.userAgent, ip: '', // Empty Ip string is required, server gets the ip from HTTP header - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, } } @@ -107,7 +105,7 @@ function RhythmOneBidAdapter() { if (adUnit.mediaTypes && adUnit.mediaTypes.banner) { sizeList = adUnit.mediaTypes.banner.sizes; } - var sizeStringList = parseSizesInput(sizeList); + var sizeStringList = utils.parseSizesInput(sizeList); var format = []; sizeStringList.forEach(function(size) { if (size) { @@ -131,9 +129,9 @@ function RhythmOneBidAdapter() { function frameVideo(bid) { var size = []; - if (deepAccess(bid, 'mediaTypes.video.playerSize')) { + if (utils.deepAccess(bid, 'mediaTypes.video.playerSize')) { var dimensionSet = bid.mediaTypes.video.playerSize; - if (isArray(bid.mediaTypes.video.playerSize[0])) { + if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { dimensionSet = bid.mediaTypes.video.playerSize[0]; } var validSize = getValidSizeSet(dimensionSet) @@ -142,15 +140,15 @@ function RhythmOneBidAdapter() { } } return { - mimes: deepAccess(bid, 'mediaTypes.video.mimes') || SUPPORTED_VIDEO_MIMES, - protocols: deepAccess(bid, 'mediaTypes.video.protocols') || SUPPORTED_VIDEO_PROTOCOLS, + mimes: utils.deepAccess(bid, 'mediaTypes.video.mimes') || SUPPORTED_VIDEO_MIMES, + protocols: utils.deepAccess(bid, 'mediaTypes.video.protocols') || SUPPORTED_VIDEO_PROTOCOLS, w: size[0], h: size[1], - startdelay: deepAccess(bid, 'mediaTypes.video.startdelay') || 0, - skip: deepAccess(bid, 'mediaTypes.video.skip') || 0, - playbackmethod: deepAccess(bid, 'mediaTypes.video.playbackmethod') || SUPPORTED_VIDEO_PLAYBACK_METHODS, - delivery: deepAccess(bid, 'mediaTypes.video.delivery') || SUPPORTED_VIDEO_DELIVERY, - api: deepAccess(bid, 'mediaTypes.video.api') || SUPPORTED_VIDEO_API, + startdelay: utils.deepAccess(bid, 'mediaTypes.video.startdelay') || 0, + skip: utils.deepAccess(bid, 'mediaTypes.video.skip') || 0, + playbackmethod: utils.deepAccess(bid, 'mediaTypes.video.playbackmethod') || SUPPORTED_VIDEO_PLAYBACK_METHODS, + delivery: utils.deepAccess(bid, 'mediaTypes.video.delivery') || SUPPORTED_VIDEO_DELIVERY, + api: utils.deepAccess(bid, 'mediaTypes.video.api') || SUPPORTED_VIDEO_API, } } @@ -172,14 +170,14 @@ function RhythmOneBidAdapter() { device: frameDevice(), user: { ext: { - consent: deepAccess(bidderRequest, 'gdprConsent.gdprApplies') ? bidderRequest.gdprConsent.consentString : '' + consent: utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies') ? bidderRequest.gdprConsent.consentString : '' } }, at: 1, tmax: 1000, regs: { ext: { - gdpr: deepAccess(bidderRequest, 'gdprConsent.gdprApplies') ? Boolean(bidderRequest.gdprConsent.gdprApplies & 1) : false + gdpr: utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies') ? Boolean(bidderRequest.gdprConsent.gdprApplies & 1) : false } } }; diff --git a/modules/richaudienceBidAdapter.js b/modules/richaudienceBidAdapter.js index b49d7c5584c..4b556e83236 100755 --- a/modules/richaudienceBidAdapter.js +++ b/modules/richaudienceBidAdapter.js @@ -1,7 +1,7 @@ -import {isEmpty, deepAccess, isStr} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; import { Renderer } from '../src/Renderer.js'; const BIDDER_CODE = 'richaudience'; @@ -52,22 +52,17 @@ export const spec = { videoData: raiGetVideoInfo(bid), scr_rsl: raiGetResolution(), cpuc: (typeof window.navigator != 'undefined' ? window.navigator.hardwareConcurrency : null), - kws: (!isEmpty(bid.params.keywords) ? bid.params.keywords : null), - schain: bid.schain + kws: (!utils.isEmpty(bid.params.keywords) ? bid.params.keywords : null) }; REFERER = (typeof bidderRequest.refererInfo.referer != 'undefined' ? encodeURIComponent(bidderRequest.refererInfo.referer) : null) payload.gdpr_consent = ''; - payload.gdpr = false; + payload.gdpr = null; if (bidderRequest && bidderRequest.gdprConsent) { - if (typeof bidderRequest.gdprConsent.gdprApplies != 'undefined') { - payload.gdpr = bidderRequest.gdprConsent.gdprApplies; - } - if (typeof bidderRequest.gdprConsent.consentString != 'undefined') { - payload.gdpr_consent = bidderRequest.gdprConsent.consentString; - } + payload.gdpr_consent = bidderRequest.gdprConsent.consentString; + payload.gdpr = bidderRequest.gdprConsent.gdprApplies; } var payloadString = JSON.stringify(payload); @@ -197,13 +192,6 @@ function raiGetSizes(bid) { function raiGetDemandType(bid) { let raiFormat = 'display'; - if (typeof bid.sizes != 'undefined') { - bid.sizes.forEach(function (sz) { - if ((sz[0] == '1800' && sz[1] == '1000') || (sz[0] == '1' && sz[1] == '1')) { - raiFormat = 'skin' - } - }) - } if (bid.mediaTypes != undefined) { if (bid.mediaTypes.video != undefined) { raiFormat = 'video'; @@ -232,19 +220,19 @@ function raiSetEids(bid) { let eids = []; if (bid && bid.userId) { - raiSetUserId(bid, eids, 'id5-sync.com', deepAccess(bid, `userId.id5id.uid`)); - raiSetUserId(bid, eids, 'pubcommon', deepAccess(bid, `userId.pubcid`)); - raiSetUserId(bid, eids, 'criteo.com', deepAccess(bid, `userId.criteoId`)); - raiSetUserId(bid, eids, 'liveramp.com', deepAccess(bid, `userId.idl_env`)); - raiSetUserId(bid, eids, 'liveintent.com', deepAccess(bid, `userId.lipb.lipbid`)); - raiSetUserId(bid, eids, 'adserver.org', deepAccess(bid, `userId.tdid`)); + raiSetUserId(bid, eids, 'id5-sync.com', utils.deepAccess(bid, `userId.id5id.uid`)); + raiSetUserId(bid, eids, 'pubcommon', utils.deepAccess(bid, `userId.pubcid`)); + raiSetUserId(bid, eids, 'criteo.com', utils.deepAccess(bid, `userId.criteoId`)); + raiSetUserId(bid, eids, 'liveramp.com', utils.deepAccess(bid, `userId.idl_env`)); + raiSetUserId(bid, eids, 'liveintent.com', utils.deepAccess(bid, `userId.lipb.lipbid`)); + raiSetUserId(bid, eids, 'adserver.org', utils.deepAccess(bid, `userId.tdid`)); } return eids; } function raiSetUserId(bid, eids, source, value) { - if (isStr(value)) { + if (utils.isStr(value)) { eids.push({ userId: value, source: source @@ -307,8 +295,8 @@ function raiGetFloor(bid, config) { raiFloor = bid.params.bidfloor; } else if (typeof bid.getFloor == 'function') { let floorSpec = bid.getFloor({ - currency: config.getConfig('floors.data.currency') != null ? config.getConfig('floors.data.currency') : 'USD', - mediaType: typeof bid.mediaTypes['banner'] == 'object' ? 'banner' : 'video', + currency: config.getConfig('currency.adServerCurrency'), + mediaType: bid.mediaType.banner ? 'banner' : 'video', size: '*' }) diff --git a/modules/riseBidAdapter.js b/modules/riseBidAdapter.js index a8ea023d46a..6887805b854 100644 --- a/modules/riseBidAdapter.js +++ b/modules/riseBidAdapter.js @@ -1,17 +1,17 @@ -import { logWarn, logInfo, isArray, isFn, deepAccess, isEmpty, contains, timestamp, getBidIdParameter, triggerPixel, isInteger } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import * as utils from '../src/utils.js'; +import {VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; +const SUPPORTED_AD_TYPES = [VIDEO]; const BIDDER_CODE = 'rise'; -const ADAPTER_VERSION = '6.0.0'; +const BIDDER_VERSION = '4.0.1'; const TTL = 360; const CURRENCY = 'USD'; const SELLER_ENDPOINT = 'https://hb.yellowblue.io/'; const MODES = { - PRODUCTION: 'hb-multi', - TEST: 'hb-multi-test' + PRODUCTION: 'hb', + TEST: 'hb-test' } const SUPPORTED_SYNC_METHODS = { IFRAME: 'iframe', @@ -20,86 +20,59 @@ const SUPPORTED_SYNC_METHODS = { export const spec = { code: BIDDER_CODE, - gvlid: 1043, - version: ADAPTER_VERSION, + version: BIDDER_VERSION, supportedMediaTypes: SUPPORTED_AD_TYPES, - isBidRequestValid: function (bidRequest) { - if (!bidRequest.params) { - logWarn('no params have been set to Rise adapter'); - return false; - } - - if (!bidRequest.params.org) { - logWarn('org is a mandatory param for Rise adapter'); - return false; - } - - return true; + isBidRequestValid: function(bidRequest) { + return !!(bidRequest.params.org); }, - buildRequests: function (validBidRequests, bidderRequest) { - const combinedRequestsObject = {}; + buildRequests: function (bidRequests, bidderRequest) { + if (bidRequests.length === 0) { + return []; + } - // use data from the first bid, to create the general params for all bids - const generalObject = validBidRequests[0]; - const testMode = generalObject.params.testMode; + const requests = []; - combinedRequestsObject.params = generateGeneralParams(generalObject, bidderRequest); - combinedRequestsObject.bids = generateBidsParams(validBidRequests, bidderRequest); + bidRequests.forEach(bid => { + requests.push(buildVideoRequest(bid, bidderRequest)); + }); - return { - method: 'POST', - url: getEndpoint(testMode), - data: combinedRequestsObject - } + return requests; }, - interpretResponse: function ({body}) { + interpretResponse: function({body}) { const bidResponses = []; - if (body.bids) { - body.bids.forEach(adUnit => { - const bidResponse = { - requestId: adUnit.requestId, - cpm: adUnit.cpm, - currency: adUnit.currency || CURRENCY, - width: adUnit.width, - height: adUnit.height, - ttl: adUnit.ttl || TTL, - creativeId: adUnit.requestId, - netRevenue: adUnit.netRevenue || true, - nurl: adUnit.nurl, - mediaType: adUnit.mediaType, - meta: { - mediaType: adUnit.mediaType - } - }; - - if (adUnit.mediaType === VIDEO) { - bidResponse.vastXml = adUnit.vastXml; - } else if (adUnit.mediaType === BANNER) { - bidResponse.ad = adUnit.ad; - } - - if (adUnit.adomain && adUnit.adomain.length) { - bidResponse.meta.advertiserDomains = adUnit.adomain; - } - - bidResponses.push(bidResponse); - }); + const bidResponse = { + requestId: body.requestId, + cpm: body.cpm, + width: body.width, + height: body.height, + creativeId: body.requestId, + currency: body.currency, + netRevenue: body.netRevenue, + ttl: body.ttl || TTL, + vastXml: body.vastXml, + mediaType: VIDEO + }; + + if (body.adomain && body.adomain.length) { + bidResponse.meta = {}; + bidResponse.meta.advertiserDomains = body.adomain } + bidResponses.push(bidResponse); return bidResponses; }, - getUserSyncs: function (syncOptions, serverResponses) { + getUserSyncs: function(syncOptions, serverResponses) { const syncs = []; for (const response of serverResponses) { - if (syncOptions.iframeEnabled && response.body.params.userSyncURL) { + if (syncOptions.iframeEnabled && response.body.userSyncURL) { syncs.push({ type: 'iframe', - url: response.body.params.userSyncURL + url: response.body.userSyncURL }); } - if (syncOptions.pixelEnabled && isArray(response.body.params.userSyncPixels)) { - const pixels = response.body.params.userSyncPixels.map(pixel => { + if (syncOptions.pixelEnabled && utils.isArray(response.body.userSyncPixels)) { + const pixels = response.body.userSyncPixels.map(pixel => { return { type: 'image', url: pixel @@ -109,16 +82,6 @@ export const spec = { } } return syncs; - }, - onBidWon: function (bid) { - if (bid == null) { - return; - } - - logInfo('onBidWon:', bid); - if (bid.hasOwnProperty('nurl') && bid.nurl.length > 0) { - triggerPixel(bid.nurl); - } } }; @@ -129,33 +92,46 @@ registerBidder(spec); * @param bid {bid} * @returns {Number} */ -function getFloor(bid, mediaType) { - if (!isFn(bid.getFloor)) { +function getFloor(bid) { + if (!utils.isFn(bid.getFloor)) { return 0; } let floorResult = bid.getFloor({ currency: CURRENCY, - mediaType: mediaType, + mediaType: VIDEO, size: '*' }); - return floorResult.currency === CURRENCY && floorResult.floor ? floorResult.floor : 0; + return floorResult.currency === CURRENCY ? floorResult.floor : 0; } /** - * Get the the ad sizes array from the bid + * Build the video request * @param bid {bid} - * @returns {Array} + * @param bidderRequest {bidderRequest} + * @returns {Object} */ -function getSizesArray(bid, mediaType) { - let sizesArray = [] +function buildVideoRequest(bid, bidderRequest) { + const sellerParams = generateParameters(bid, bidderRequest); + const {params} = bid; + return { + method: 'GET', + url: getEndpoint(params.testMode), + data: sellerParams + }; +} - if (deepAccess(bid, `mediaTypes.${mediaType}.sizes`)) { - sizesArray = bid.mediaTypes[mediaType].sizes; +/** + * Get the the ad size from the bid + * @param bid {bid} + * @returns {Array} + */ +function getSizes(bid) { + if (utils.deepAccess(bid, 'mediaTypes.video.sizes')) { + return bid.mediaTypes.video.sizes[0]; } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) { - sizesArray = bid.sizes; + return bid.sizes[0]; } - - return sizesArray; + return []; } /** @@ -164,7 +140,7 @@ function getSizesArray(bid, mediaType) { * @returns {string} */ function getSupplyChain(schainObject) { - if (isEmpty(schainObject)) { + if (utils.isEmpty(schainObject)) { return ''; } let scStr = `${schainObject.ver},${schainObject.complete}`; @@ -172,7 +148,7 @@ function getSupplyChain(schainObject) { scStr += '!'; scStr += `${getEncodedValIfNotEmpty(node.asi)},`; scStr += `${getEncodedValIfNotEmpty(node.sid)},`; - scStr += `${node.hp ? encodeURIComponent(node.hp) : ''},`; + scStr += `${getEncodedValIfNotEmpty(node.hp)},`; scStr += `${getEncodedValIfNotEmpty(node.rid)},`; scStr += `${getEncodedValIfNotEmpty(node.name)},`; scStr += `${getEncodedValIfNotEmpty(node.domain)}`; @@ -186,7 +162,7 @@ function getSupplyChain(schainObject) { * @returns {string} */ function getEncodedValIfNotEmpty(val) { - return !isEmpty(val) ? encodeURIComponent(val) : ''; + return !utils.isEmpty(val) ? encodeURIComponent(val) : ''; } /** @@ -216,8 +192,8 @@ function isSyncMethodAllowed(syncRule, bidderCode) { return false; } const isInclude = syncRule.filter === 'include'; - const bidders = isArray(syncRule.bidders) ? syncRule.bidders : [bidderCode]; - return isInclude && contains(bidders, bidderCode); + const bidders = utils.isArray(syncRule.bidders) ? syncRule.bidders : [bidderCode]; + return isInclude && utils.contains(bidders, bidderCode); } /** @@ -232,200 +208,69 @@ function getEndpoint(testMode) { } /** - * get device type - * @param uad {ua} - * @returns {string} - */ -function getDeviceType(ua) { - if (/ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i - .test(ua.toLowerCase())) { - return '5'; - } - if (/iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i - .test(ua.toLowerCase())) { - return '4'; - } - if (/smart[-_\s]?tv|hbbtv|appletv|googletv|hdmi|netcast|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b/i - .test(ua.toLowerCase())) { - return '3'; - } - return '1'; -} - -function generateBidsParams(validBidRequests, bidderRequest) { - const bidsArray = []; - - if (validBidRequests.length) { - validBidRequests.forEach(bid => { - bidsArray.push(generateBidParameters(bid, bidderRequest)); - }); - } - - return bidsArray; -} - -/** - * Generate bid specific parameters - * @param {bid} bid - * @param {bidderRequest} bidderRequest - * @returns {Object} bid specific params object - */ -function generateBidParameters(bid, bidderRequest) { - const {params} = bid; - const mediaType = isBanner(bid) ? BANNER : VIDEO; - const sizesArray = getSizesArray(bid, mediaType); - - // fix floor price in case of NAN - if (isNaN(params.floorPrice)) { - params.floorPrice = 0; - } - - const bidObject = { - mediaType, - adUnitCode: getBidIdParameter('adUnitCode', bid), - sizes: sizesArray, - floorPrice: Math.max(getFloor(bid, mediaType), params.floorPrice), - bidId: getBidIdParameter('bidId', bid), - bidderRequestId: getBidIdParameter('bidderRequestId', bid), - transactionId: getBidIdParameter('transactionId', bid), - }; - - const pos = deepAccess(bid, `mediaTypes.${mediaType}.pos`); - if (pos) { - bidObject.pos = pos; - } - - const gpid = deepAccess(bid, `ortb2Imp.ext.gpid`); - if (gpid) { - bidObject.gpid = gpid; - } - - const placementId = params.placementId || deepAccess(bid, `mediaTypes.${mediaType}.name`); - if (placementId) { - bidObject.placementId = placementId; - } - - if (mediaType === VIDEO) { - const playbackMethod = deepAccess(bid, `mediaTypes.video.playbackmethod`); - let playbackMethodValue; - - // verify playbackMethod is of type integer array, or integer only. - if (Array.isArray(playbackMethod) && isInteger(playbackMethod[0])) { - // only the first playbackMethod in the array will be used, according to OpenRTB 2.5 recommendation - playbackMethodValue = playbackMethod[0]; - } else if (isInteger(playbackMethod)) { - playbackMethodValue = playbackMethod; - } - - if (playbackMethodValue) { - bidObject.playbackMethod = playbackMethodValue; - } - - const placement = deepAccess(bid, `mediaTypes.video.placement`); - if (placement) { - bidObject.placement = placement; - } - - const minDuration = deepAccess(bid, `mediaTypes.video.minduration`); - if (minDuration) { - bidObject.minDuration = minDuration; - } - - const maxDuration = deepAccess(bid, `mediaTypes.video.maxduration`); - if (maxDuration) { - bidObject.maxDuration = maxDuration; - } - - const skip = deepAccess(bid, `mediaTypes.video.skip`); - if (skip) { - bidObject.skip = skip; - } - - const linearity = deepAccess(bid, `mediaTypes.video.linearity`); - if (linearity) { - bidObject.linearity = linearity; - } - } - - return bidObject; -} - -function isBanner(bid) { - return bid.mediaTypes && bid.mediaTypes.banner; -} - -/** - * Generate params that are common between all bids - * @param {single bid object} generalObject - * @param {bidderRequest} bidderRequest - * @returns {object} the common params object + * Generate query parameters for the request + * @param bid {bid} + * @param bidderRequest {bidderRequest} + * @returns {Object} */ -function generateGeneralParams(generalObject, bidderRequest) { - const domain = window.location.hostname; - const {syncEnabled, filterSettings} = config.getConfig('userSync') || {}; - const {bidderCode} = bidderRequest; - const generalBidParams = generalObject.params; +function generateParameters(bid, bidderRequest) { const timeout = config.getConfig('bidderTimeout'); + const { syncEnabled, filterSettings } = config.getConfig('userSync') || {}; + const [ width, height ] = getSizes(bid); + const { params } = bid; + const { bidderCode } = bidderRequest; + const domain = window.location.hostname; - // these params are snake_case instead of camelCase to allow backwards compatability on the server. - // in the future, these will be converted to camelCase to match our convention. - const generalParams = { - wrapper_type: 'prebidjs', - wrapper_vendor: '$$PREBID_GLOBAL$$', - wrapper_version: '$prebid.version$', - adapter_version: ADAPTER_VERSION, - auction_start: timestamp(), - publisher_id: generalBidParams.org, + const requestParams = { + auction_start: utils.timestamp(), + ad_unit_code: utils.getBidIdParameter('adUnitCode', bid), + tmax: timeout, + width: width, + height: height, + publisher_id: params.org, + floor_price: Math.max(getFloor(bid), params.floorPrice), + ua: navigator.userAgent, + bid_id: utils.getBidIdParameter('bidId', bid), + bidder_request_id: utils.getBidIdParameter('bidderRequestId', bid), + transaction_id: utils.getBidIdParameter('transactionId', bid), + session_id: utils.getBidIdParameter('auctionId', bid), publisher_name: domain, site_domain: domain, - dnt: (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0, - device_type: getDeviceType(navigator.userAgent), - ua: navigator.userAgent, - session_id: getBidIdParameter('auctionId', generalObject), - tmax: timeout - } - - const userIdsParam = getBidIdParameter('userId', generalObject); - if (userIdsParam) { - generalParams.userIds = JSON.stringify(userIdsParam); - } + bidder_version: BIDDER_VERSION + }; - const ortb2Metadata = config.getConfig('ortb2') || {}; - if (ortb2Metadata.site) { - generalParams.site_metadata = JSON.stringify(ortb2Metadata.site); - } - if (ortb2Metadata.user) { - generalParams.user_metadata = JSON.stringify(ortb2Metadata.user); + if (params.placementId) { + requestParams.placement_id = params.placementId; } if (syncEnabled) { const allowedSyncMethod = getAllowedSyncMethod(filterSettings, bidderCode); if (allowedSyncMethod) { - generalParams.cs_method = allowedSyncMethod; + requestParams.cs_method = allowedSyncMethod; } } if (bidderRequest.uspConsent) { - generalParams.us_privacy = bidderRequest.uspConsent; + requestParams.us_privacy = bidderRequest.uspConsent; } if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { - generalParams.gdpr = bidderRequest.gdprConsent.gdprApplies; - generalParams.gdpr_consent = bidderRequest.gdprConsent.consentString; + requestParams.gdpr = bidderRequest.gdprConsent.gdprApplies; + requestParams.gdpr_consent = bidderRequest.gdprConsent.consentString; } - if (generalBidParams.ifa) { - generalParams.ifa = generalBidParams.ifa; + if (params.ifa) { + requestParams.ifa = params.ifa; } - if (generalObject.schain) { - generalParams.schain = getSupplyChain(generalObject.schain); + if (bid.schain) { + requestParams.schain = getSupplyChain(bid.schain); } if (bidderRequest && bidderRequest.refererInfo) { - generalParams.referrer = deepAccess(bidderRequest, 'refererInfo.referer'); - generalParams.page_url = config.getConfig('pageUrl') || deepAccess(window, 'location.href'); + requestParams.referrer = utils.deepAccess(bidderRequest, 'refererInfo.referer'); + requestParams.page_url = config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href'); } - return generalParams + return requestParams; } diff --git a/modules/riseBidAdapter.md b/modules/riseBidAdapter.md index 83f8adfd645..6251b92e0a9 100644 --- a/modules/riseBidAdapter.md +++ b/modules/riseBidAdapter.md @@ -13,7 +13,7 @@ Module that connects to Rise's demand sources. The Rise adapter requires setup and approval from the Rise. Please reach out to prebid-rise-engage@risecodes.com to create an Rise account. -The adapter supports Video(instream). +The adapter supports Video(instream). For the integration, Rise returns content as vastXML and requires the publisher to define the cache url in config passed to Prebid for it to be valid in the auction. # Bid Parameters ## Video @@ -22,6 +22,7 @@ The adapter supports Video(instream). | ---- | ----- | ---- | ----------- | ------- | `org` | required | String | Rise publisher Id provided by your Rise representative | "56f91cd4d3e3660002000033" | `floorPrice` | optional | Number | Minimum price in USD. Misuse of this parameter can impact revenue | 2.00 +| `ifa` | optional | String | The ID for advertisers (also referred to as "IDFA") | "XXX-XXX" | `placementId` | optional | String | A unique placement identifier | "12345678" | `testMode` | optional | Boolean | This activates the test mode | false @@ -42,6 +43,7 @@ var adUnits = [ params: { org: '56f91cd4d3e3660002000033', // Required floorPrice: 2.00, // Optional + ifa: 'XXX-XXX', // Optional placementId: '12345678', // Optional testMode: false // Optional } diff --git a/modules/roxotAnalyticsAdapter.js b/modules/roxotAnalyticsAdapter.js index b11898b9ea8..b6857d69f45 100644 --- a/modules/roxotAnalyticsAdapter.js +++ b/modules/roxotAnalyticsAdapter.js @@ -1,13 +1,13 @@ -import {deepClone, getParameterByName, logError, logInfo} from '../src/utils.js'; import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; -import {includes} from '../src/polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js'; import {ajaxBuilder} from '../src/ajax.js'; -import {getStorageManager} from '../src/storageManager.js'; +import { getStorageManager } from '../src/storageManager.js'; const storage = getStorageManager(); +const utils = require('../src/utils.js'); let ajax = ajaxBuilder(0); const DEFAULT_EVENT_URL = 'pa.rxthdr.com/v3'; @@ -153,7 +153,7 @@ function buildBidderRequest(auction, bidRequest) { function buildBidAfterTimeout(adUnitAuction, args) { return { - 'auction': deepClone(adUnitAuction), + 'auction': utils.deepClone(adUnitAuction), 'adUnit': extractAdUnitCode(args), 'bidder': extractBidder(args), 'cpm': args.cpm, @@ -170,7 +170,7 @@ function buildBidAfterTimeout(adUnitAuction, args) { function buildImpression(adUnitAuction, args) { return { 'isNew': checkIsNewFlag() ? 1 : 0, - 'auction': deepClone(adUnitAuction), + 'auction': utils.deepClone(adUnitAuction), 'adUnit': extractAdUnitCode(args), 'bidder': extractBidder(args), 'cpm': args.cpm, @@ -342,7 +342,7 @@ roxotAdapter.originEnableAnalytics = roxotAdapter.enableAnalytics; roxotAdapter.enableAnalytics = function (config) { if (this.initConfig(config)) { - _logInfo('Analytics adapter enabled', initOptions); + logInfo('Analytics adapter enabled', initOptions); roxotAdapter.originEnableAnalytics(config); } }; @@ -351,7 +351,7 @@ roxotAdapter.buildUtmTagData = function () { let utmTagData = {}; let utmTagsDetected = false; utmTags.forEach(function (utmTagKey) { - let utmTagValue = getParameterByName(utmTagKey); + let utmTagValue = utils.getParameterByName(utmTagKey); if (utmTagValue !== '') { utmTagsDetected = true; } @@ -374,11 +374,11 @@ roxotAdapter.buildUtmTagData = function () { roxotAdapter.initConfig = function (config) { let isCorrectConfig = true; initOptions = {}; - initOptions.options = deepClone(config.options); + initOptions.options = utils.deepClone(config.options); initOptions.publisherId = initOptions.options.publisherId || (initOptions.options.publisherIds[0]) || null; if (!initOptions.publisherId) { - _logError('"options.publisherId" is empty'); + logError('"options.publisherId" is empty'); isCorrectConfig = false; } @@ -407,7 +407,7 @@ function registerEvent(eventType, eventName, data) { sendEventCache.push(eventData); - _logInfo('Register event', eventData); + logInfo('Register event', eventData); (typeof initOptions.serverConfig === 'undefined') ? checkEventAfterTimeout() : checkSendEvent(); } @@ -427,7 +427,7 @@ function checkSendEvent() { let event = sendEventCache.shift(); let isNeedSend = initOptions.serverConfig[event.eventType] || 0; if (Number(isNeedSend) === 0) { - _logInfo('Skip event ' + event.eventName, event); + logInfo('Skip event ' + event.eventName, event); continue; } sendEvent(event.eventType, event.eventName, event.data); @@ -454,7 +454,7 @@ function sendEvent(eventType, eventName, data) { ajax( url, function () { - _logInfo(eventName + ' sent', eventData); + logInfo(eventName + ' sent', eventData); }, JSON.stringify(eventData), { @@ -490,12 +490,12 @@ function loadServerConfig() { ); } -function _logInfo(message, meta) { - logInfo(buildLogMessage(message), meta); +function logInfo(message, meta) { + utils.logInfo(buildLogMessage(message), meta); } -function _logError(message) { - logError(buildLogMessage(message)); +function logError(message) { + utils.logError(buildLogMessage(message)); } function buildLogMessage(message) { diff --git a/modules/rtbhouseBidAdapter.js b/modules/rtbhouseBidAdapter.js index b8436179a30..036bdfaebeb 100644 --- a/modules/rtbhouseBidAdapter.js +++ b/modules/rtbhouseBidAdapter.js @@ -1,7 +1,7 @@ -import {deepAccess, getOrigin, isArray, logError} from '../src/utils.js'; -import {BANNER, NATIVE} from '../src/mediaTypes.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {includes} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { BANNER, NATIVE } from '../src/mediaTypes.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import includes from 'core-js-pure/features/array/includes.js'; const BIDDER_CODE = 'rtbhouse'; const REGIONS = ['prebid-eu', 'prebid-us', 'prebid-asia']; @@ -9,7 +9,6 @@ const ENDPOINT_URL = 'creativecdn.com/bidder/prebid/bids'; const DEFAULT_CURRENCY_ARR = ['USD']; // NOTE - USD is the only supported currency right now; Hardcoded for bids const SUPPORTED_MEDIA_TYPES = [BANNER, NATIVE]; const TTL = 55; -const GVLID = 16; // Codes defined by OpenRTB Native Ads 1.1 specification export const OPENRTB = { @@ -37,7 +36,6 @@ export const OPENRTB = { export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_MEDIA_TYPES, - gvlid: GVLID, isBidRequestValid: function (bid) { return !!(includes(REGIONS, bid.params.region) && bid.params.publisherId); @@ -84,7 +82,7 @@ export const spec = { }, interpretResponse: function (serverResponse, originalRequest) { const responseBody = serverResponse.body; - if (!isArray(responseBody)) { + if (!utils.isArray(responseBody)) { return []; } @@ -147,7 +145,7 @@ function mapImpression(slot) { */ function mapBanner(slot) { if (slot.mediaType === 'banner' || - deepAccess(slot, 'mediaTypes.banner') || + utils.deepAccess(slot, 'mediaTypes.banner') || (!slot.mediaType && !slot.mediaTypes)) { var sizes = slot.sizes || slot.mediaTypes.banner.sizes; return { @@ -167,26 +165,16 @@ function mapBanner(slot) { * @returns {object} Site by OpenRTB 2.5 §3.2.13 */ function mapSite(slot, bidderRequest) { - let pubId = 'unknown'; - let channel = null; - if (slot && slot.length > 0) { - pubId = slot[0].params.publisherId; - channel = slot[0].params.channel && - slot[0].params.channel - .toString() - .slice(0, 50); - } - let siteData = { + const pubId = slot && slot.length > 0 + ? slot[0].params.publisherId + : 'unknown'; + return { publisher: { id: pubId.toString(), }, page: bidderRequest.refererInfo.referer, - name: getOrigin() - }; - if (channel) { - siteData.channel = channel; + name: utils.getOrigin() } - return siteData; } /** @@ -210,7 +198,7 @@ function mapSchain(schain) { return null; } if (!validateSchain(schain)) { - logError('RTB House: required schain params missing'); + utils.logError('RTB House: required schain params missing'); return null; } return schain; @@ -235,7 +223,7 @@ function validateSchain(schain) { * @returns {object} Request by OpenRTB Native Ads 1.1 §4 */ function mapNative(slot) { - if (slot.mediaType === 'native' || deepAccess(slot, 'mediaTypes.native')) { + if (slot.mediaType === 'native' || utils.deepAccess(slot, 'mediaTypes.native')) { return { request: { assets: mapNativeAssets(slot) @@ -250,7 +238,7 @@ function mapNative(slot) { * @returns {array} Request Assets by OpenRTB Native Ads 1.1 §4.2 */ function mapNativeAssets(slot) { - const params = slot.nativeParams || deepAccess(slot, 'mediaTypes.native'); + const params = slot.nativeParams || utils.deepAccess(slot, 'mediaTypes.native'); const assets = []; if (params.title) { assets.push({ diff --git a/modules/rtbsapeBidAdapter.js b/modules/rtbsapeBidAdapter.js index d58b3a1f240..f5c648d5234 100644 --- a/modules/rtbsapeBidAdapter.js +++ b/modules/rtbsapeBidAdapter.js @@ -1,8 +1,9 @@ -import { deepAccess, triggerPixel } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {OUTSTREAM} from '../src/video.js'; import {Renderer} from '../src/Renderer.js'; +import {triggerPixel} from '../src/utils.js'; const BIDDER_CODE = 'rtbsape'; const ENDPOINT = 'https://ssp-rtb.sape.ru/prebid'; @@ -67,7 +68,7 @@ export const spec = { .filter(bid => typeof (bid.meta || {}).advertiserDomains !== 'undefined') .map(bid => { let requestBid = bids[bid.requestId]; - let context = deepAccess(requestBid, 'mediaTypes.video.context'); + let context = utils.deepAccess(requestBid, 'mediaTypes.video.context'); if (context === OUTSTREAM && (bid.vastUrl || bid.vastXml)) { let renderer = Renderer.install({ @@ -76,7 +77,7 @@ export const spec = { loaded: false }); - let muted = deepAccess(requestBid, 'params.video.playerMuted'); + let muted = utils.deepAccess(requestBid, 'params.video.playerMuted'); if (typeof muted === 'undefined') { muted = true; } diff --git a/modules/rtdModule/index.js b/modules/rtdModule/index.js index 381059c68f7..e235868f791 100644 --- a/modules/rtdModule/index.js +++ b/modules/rtdModule/index.js @@ -36,17 +36,16 @@ * @param {string[]} adUnitsCodes * @param {SubmoduleConfig} config * @param {UserConsentData} userConsent - * @param {auction} auction */ /** * @function? * @summary modify bid request data * @name RtdSubmodule#getBidRequestData - * @param {Object} reqBidsConfigObj - * @param {function} callback * @param {SubmoduleConfig} config * @param {UserConsentData} userConsent + * @param {Object} reqBidsConfigObj + * @param {function} callback */ /** @@ -99,15 +98,6 @@ * @param {UserConsentData} userConsent */ -/** - * @function? - * @summary on bid requested event - * @name RtdSubmodule#onBidRequestEvent - * @param {Object} data - * @param {SubmoduleConfig} config - * @param {UserConsentData} userConsent - */ - /** * @interface ModuleConfig */ @@ -153,11 +143,11 @@ import {config} from '../../src/config.js'; import {module} from '../../src/hook.js'; -import {logError, logInfo, logWarn} from '../../src/utils.js'; -import * as events from '../../src/events.js'; +import * as utils from '../../src/utils.js'; +import events from '../../src/events.js'; import CONSTANTS from '../../src/constants.json'; import {gdprDataHandler, uspDataHandler} from '../../src/adapterManager.js'; -import {find} from '../../src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; import {getGlobal} from '../../src/prebidGlobal.js'; /** @type {string} */ @@ -174,55 +164,17 @@ let _dataProviders = []; let _userConsent; /** - * Register a RTD submodule. - * + * enable submodule in User ID * @param {RtdSubmodule} submodule - * @returns {function()} a de-registration function that will unregister the module when called. */ export function attachRealTimeDataProvider(submodule) { registeredSubModules.push(submodule); - return function detach() { - const idx = registeredSubModules.indexOf(submodule) - if (idx >= 0) { - registeredSubModules.splice(idx, 1); - initSubModules(); - } - } } -/** - * call each sub module event function by config order - */ -const setEventsListeners = (function () { - let registered = false; - return function setEventsListeners() { - if (!registered) { - Object.entries({ - [CONSTANTS.EVENTS.AUCTION_INIT]: ['onAuctionInitEvent'], - [CONSTANTS.EVENTS.AUCTION_END]: ['onAuctionEndEvent', getAdUnitTargeting], - [CONSTANTS.EVENTS.BID_RESPONSE]: ['onBidResponseEvent'], - [CONSTANTS.EVENTS.BID_REQUESTED]: ['onBidRequestEvent'] - }).forEach(([ev, [handler, preprocess]]) => { - events.on(ev, (args) => { - preprocess && preprocess(args); - subModules.forEach(sm => { - try { - sm[handler] && sm[handler](args, sm.config, _userConsent) - } catch (e) { - logError(`RTD provider '${sm.name}': error in '${handler}':`, e); - } - }); - }) - }); - registered = true; - } - } -})(); - export function init(config) { const confListener = config.getConfig(MODULE_NAME, ({realTimeData}) => { if (!realTimeData.dataProviders) { - logError('missing parameters for real time module'); + utils.logError('missing parameters for real time module'); return; } confListener(); // unsubscribe config listener @@ -257,7 +209,22 @@ function initSubModules() { } }); subModules = subModulesByOrder; - logInfo(`Real time data module enabled, using submodules: ${subModules.map((m) => m.name).join(', ')}`); +} + +/** + * call each sub module event function by config order + */ +function setEventsListeners() { + events.on(CONSTANTS.EVENTS.AUCTION_INIT, (args) => { + subModules.forEach(sm => { sm.onAuctionInitEvent && sm.onAuctionInitEvent(args, sm.config, _userConsent) }) + }); + events.on(CONSTANTS.EVENTS.AUCTION_END, (args) => { + getAdUnitTargeting(args); + subModules.forEach(sm => { sm.onAuctionEndEvent && sm.onAuctionEndEvent(args, sm.config, _userConsent) }) + }); + events.on(CONSTANTS.EVENTS.BID_RESPONSE, (args) => { + subModules.forEach(sm => { sm.onBidResponseEvent && sm.onBidResponseEvent(args, sm.config, _userConsent) }) + }); } /** @@ -292,12 +259,18 @@ export function setBidRequestsData(fn, reqBidsConfigObj) { return exitHook(); } - waitTimeout = setTimeout(exitHook, shouldDelayAuction ? _moduleConfig.auctionDelay : 0); + if (shouldDelayAuction) { + waitTimeout = setTimeout(exitHook, _moduleConfig.auctionDelay); + } relevantSubModules.forEach(sm => { sm.getBidRequestData(reqBidsConfigObj, onGetBidRequestDataCallback.bind(sm), sm.config, _userConsent) }); + if (!shouldDelayAuction) { + return exitHook(); + } + function onGetBidRequestDataCallback() { if (isDone) { return; @@ -305,15 +278,12 @@ export function setBidRequestsData(fn, reqBidsConfigObj) { if (this.config && this.config.waitForIt) { callbacksExpected--; } - if (callbacksExpected === 0) { - setTimeout(exitHook, 0); + if (callbacksExpected <= 0) { + return exitHook(); } } function exitHook() { - if (isDone) { - return; - } isDone = true; clearTimeout(waitTimeout); fn.call(this, reqBidsConfigObj); @@ -340,11 +310,11 @@ export function getAdUnitTargeting(auction) { } let targeting = []; for (let i = relevantSubModules.length - 1; i >= 0; i--) { - const smTargeting = relevantSubModules[i].getTargetingData(adUnitCodes, relevantSubModules[i].config, _userConsent, auction); + const smTargeting = relevantSubModules[i].getTargetingData(adUnitCodes, relevantSubModules[i].config, _userConsent); if (smTargeting && typeof smTargeting === 'object') { targeting.push(smTargeting); } else { - logWarn('invalid getTargetingData response for sub module', relevantSubModules[i].name); + utils.logWarn('invalid getTargetingData response for sub module', relevantSubModules[i].name); } } // place data on auction adUnits @@ -354,7 +324,6 @@ export function getAdUnitTargeting(auction) { if (!kv) { return } - logInfo('RTD set ad unit targeting of', kv, 'for', adUnit); adUnit[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = Object.assign(adUnit[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] || {}, kv); }); return auction.adUnits; diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index 69335ff33a8..0d47bee235f 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -1,18 +1,17 @@ -import { generateUUID, mergeDeep, deepAccess, parseUrl, logError, pick, isEmpty, logWarn, debugTurnedOn, parseQS, getWindowLocation, isAdUnitCodeMatchingSlot, isNumber, isGptPubadsDefined, _each, deepSetValue, deepClone, logInfo } from '../src/utils.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; import { ajax } from '../src/ajax.js'; import { config } from '../src/config.js'; +import * as utils from '../src/utils.js'; import { getGlobal } from '../src/prebidGlobal.js'; import { getStorageManager } from '../src/storageManager.js'; const RUBICON_GVL_ID = 52; -export const storage = getStorageManager({gvlid: RUBICON_GVL_ID, moduleName: 'rubicon'}); +export const storage = getStorageManager(RUBICON_GVL_ID, 'rubicon'); const COOKIE_NAME = 'rpaSession'; const LAST_SEEN_EXPIRE_TIME = 1800000; // 30 mins const END_EXPIRE_TIME = 21600000; // 6 hours -const MODULE_NAME = 'Rubicon Analytics'; const pbsErrorMap = { 1: 'timeout-error', @@ -32,8 +31,7 @@ const { BIDDER_DONE, BID_TIMEOUT, BID_WON, - SET_TARGETING, - BILLABLE_EVENT + SET_TARGETING }, STATUS: { GOOD, @@ -45,7 +43,7 @@ const { } = CONSTANTS; let serverConfig; -config.getConfig('s2sConfig', ({ s2sConfig }) => { +config.getConfig('s2sConfig', ({s2sConfig}) => { serverConfig = s2sConfig; }); @@ -57,34 +55,28 @@ const cache = { targeting: {}, timeouts: {}, gpt: {}, - billing: {} }; const BID_REJECTED_IPF = 'rejected-ipf'; export let rubiConf = { - pvid: generateUUID().slice(0, 8), - analyticsEventDelay: 0, - dmBilling: { - enabled: false, - vendors: [], - waitForAuction: true - } + pvid: utils.generateUUID().slice(0, 8), + analyticsEventDelay: 0 }; // we are saving these as global to this module so that if a pub accidentally overwrites the entire // rubicon object, then we do not lose other data config.getConfig('rubicon', config => { - mergeDeep(rubiConf, config.rubicon); - if (deepAccess(config, 'rubicon.updatePageView') === true) { - rubiConf.pvid = generateUUID().slice(0, 8) + utils.mergeDeep(rubiConf, config.rubicon); + if (utils.deepAccess(config, 'rubicon.updatePageView') === true) { + rubiConf.pvid = utils.generateUUID().slice(0, 8) } }); export function getHostNameFromReferer(referer) { try { - rubiconAdapter.referrerHostname = parseUrl(referer, { noDecodeWholeURL: true }).hostname; + rubiconAdapter.referrerHostname = utils.parseUrl(referer, {noDecodeWholeURL: true}).hostname; } catch (e) { - logError(`${MODULE_NAME}: Unable to parse hostname from supplied url: `, referer, e); + utils.logError('Rubicon Analytics: Unable to parse hostname from supplied url: ', referer, e); rubiconAdapter.referrerHostname = ''; } return rubiconAdapter.referrerHostname @@ -98,7 +90,7 @@ function stringProperties(obj) { } else if (typeof value !== 'string') { value = String(value); } - newObj[prop] = value || undefined; + newObj[prop] = value; return newObj; }, {}); } @@ -123,61 +115,12 @@ function formatSource(src) { return src.toLowerCase(); } -function getBillingPayload(event) { - // for now we are mapping all events to type "general", later we will expand support for specific types - let billingEvent = deepClone(event); - billingEvent.type = 'general'; - billingEvent.accountId = accountId; - // mark as sent - deepSetValue(cache.billing, `${event.vendor}.${event.billingId}`, true); - return billingEvent; -} - -function sendBillingEvent(event) { - let message = getBasicEventDetails(undefined, 'soloBilling'); - message.billableEvents = [getBillingPayload(event)]; - ajax( - rubiconAdapter.getUrl(), - null, - JSON.stringify(message), - { - contentType: 'application/json' - } - ); -} - -function getBasicEventDetails(auctionId, trigger) { - let auctionCache = cache.auctions[auctionId]; - let referrer = config.getConfig('pageUrl') || pageReferer || (auctionCache && auctionCache.referrer); - let message = { - timestamps: { - prebidLoaded: rubiconAdapter.MODULE_INITIALIZED_TIME, - auctionEnded: auctionCache ? auctionCache.endTs : undefined, - eventTime: Date.now() - }, - trigger, - integration: rubiConf.int_type || DEFAULT_INTEGRATION, - version: '$prebid.version$', - referrerUri: referrer, - referrerHostname: rubiconAdapter.referrerHostname || getHostNameFromReferer(referrer), - channel: 'web', - }; - if (rubiConf.wrapperName) { - message.wrapper = { - name: rubiConf.wrapperName, - family: rubiConf.wrapperFamily, - rule: rubiConf.rule_name - } - } - return message; -} - function sendMessage(auctionId, bidWonId, trigger) { function formatBid(bid) { - return pick(bid, [ + return utils.pick(bid, [ 'bidder', 'bidderDetail', - 'bidId', bidId => deepAccess(bid, 'bidResponse.pbsBidId') || deepAccess(bid, 'bidResponse.seatBidId') || bidId, + 'bidId', bidId => utils.deepAccess(bid, 'bidResponse.pbsBidId') || utils.deepAccess(bid, 'bidResponse.seatBidId') || bidId, 'status', 'error', 'source', (source, bid) => { @@ -190,7 +133,7 @@ function sendMessage(auctionId, bidWonId, trigger) { 'clientLatencyMillis', 'serverLatencyMillis', 'params', - 'bidResponse', bidResponse => bidResponse ? pick(bidResponse, [ + 'bidResponse', bidResponse => bidResponse ? utils.pick(bidResponse, [ 'bidPriceUSD', 'dealId', 'dimensions', @@ -203,13 +146,13 @@ function sendMessage(auctionId, bidWonId, trigger) { ]); } function formatBidWon(bid) { - return Object.assign(formatBid(bid), pick(bid.adUnit, [ + return Object.assign(formatBid(bid), utils.pick(bid.adUnit, [ 'adUnitCode', 'transactionId', 'videoAdFormat', () => bid.videoAdFormat, 'mediaTypes' ]), { - adserverTargeting: !isEmpty(cache.targeting[bid.adUnit.adUnitCode]) ? stringProperties(cache.targeting[bid.adUnit.adUnitCode]) : undefined, + adserverTargeting: !utils.isEmpty(cache.targeting[bid.adUnit.adUnitCode]) ? stringProperties(cache.targeting[bid.adUnit.adUnitCode]) : undefined, bidwonStatus: 'success', // hard-coded for now accountId, siteId: bid.siteId, @@ -217,22 +160,41 @@ function sendMessage(auctionId, bidWonId, trigger) { samplingFactor }); } - let message = getBasicEventDetails(auctionId, trigger); let auctionCache = cache.auctions[auctionId]; + let referrer = config.getConfig('pageUrl') || (auctionCache && auctionCache.referrer); + let message = { + timestamps: { + prebidLoaded: rubiconAdapter.MODULE_INITIALIZED_TIME, + auctionEnded: auctionCache.endTs, + eventTime: Date.now() + }, + trigger, + integration: rubiConf.int_type || DEFAULT_INTEGRATION, + version: '$prebid.version$', + referrerUri: referrer, + referrerHostname: rubiconAdapter.referrerHostname || getHostNameFromReferer(referrer), + channel: 'web', + }; + if (rubiConf.wrapperName) { + message.wrapper = { + name: rubiConf.wrapperName, + family: rubiConf.wrapperFamily, + rule: rubiConf.rule_name + } + } if (auctionCache && !auctionCache.sent) { let adUnitMap = Object.keys(auctionCache.bids).reduce((adUnits, bidId) => { let bid = auctionCache.bids[bidId]; let adUnit = adUnits[bid.adUnit.adUnitCode]; if (!adUnit) { - adUnit = adUnits[bid.adUnit.adUnitCode] = pick(bid.adUnit, [ + adUnit = adUnits[bid.adUnit.adUnitCode] = utils.pick(bid.adUnit, [ 'adUnitCode', 'transactionId', 'mediaTypes', 'dimensions', - 'adserverTargeting', () => !isEmpty(cache.targeting[bid.adUnit.adUnitCode]) ? stringProperties(cache.targeting[bid.adUnit.adUnitCode]) : undefined, - 'gam', gam => !isEmpty(gam) ? gam : undefined, + 'adserverTargeting', () => !utils.isEmpty(cache.targeting[bid.adUnit.adUnitCode]) ? stringProperties(cache.targeting[bid.adUnit.adUnitCode]) : undefined, + 'gam', gam => !utils.isEmpty(gam) ? gam : undefined, 'pbAdSlot', - 'gpid', 'pattern' ]); adUnit.bids = []; @@ -241,10 +203,10 @@ function sendMessage(auctionId, bidWonId, trigger) { // Add site and zone id if not there and if we found a rubicon bidder if ((!adUnit.siteId || !adUnit.zoneId) && rubiconAliases.indexOf(bid.bidder) !== -1) { - if (deepAccess(bid, 'params.accountId') == accountId) { + if (utils.deepAccess(bid, 'params.accountId') == accountId) { adUnit.accountId = parseInt(accountId); - adUnit.siteId = parseInt(deepAccess(bid, 'params.siteId')); - adUnit.zoneId = parseInt(deepAccess(bid, 'params.zoneId')); + adUnit.siteId = parseInt(utils.deepAccess(bid, 'params.siteId')); + adUnit.zoneId = parseInt(utils.deepAccess(bid, 'params.zoneId')); } } @@ -267,14 +229,11 @@ function sendMessage(auctionId, bidWonId, trigger) { // This allows the bidWon events to have these params even in the case of a delayed render Object.keys(auctionCache.bids).forEach(function (bidId) { let adCode = auctionCache.bids[bidId].adUnit.adUnitCode; - Object.assign(auctionCache.bids[bidId], pick(adUnitMap[adCode], ['accountId', 'siteId', 'zoneId'])); + Object.assign(auctionCache.bids[bidId], utils.pick(adUnitMap[adCode], ['accountId', 'siteId', 'zoneId'])); }); let auction = { clientTimeoutMillis: auctionCache.timeout, - auctionStart: auctionCache.timestamp, - auctionEnd: auctionCache.endTs, - bidderOrder: auctionCache.bidderOrder, samplingFactor, accountId, adUnits: Object.keys(adUnitMap).map(i => adUnitMap[i]), @@ -284,20 +243,20 @@ function sendMessage(auctionId, bidWonId, trigger) { // pick our of top level floor data we want to send! if (auctionCache.floorData) { if (auctionCache.floorData.location === 'noData') { - auction.floors = pick(auctionCache.floorData, [ + auction.floors = utils.pick(auctionCache.floorData, [ 'location', 'fetchStatus', 'floorProvider as provider' ]); } else { - auction.floors = pick(auctionCache.floorData, [ + auction.floors = utils.pick(auctionCache.floorData, [ 'location', 'modelVersion as modelName', 'modelWeight', 'modelTimestamp', 'skipped', - 'enforcement', () => deepAccess(auctionCache.floorData, 'enforcements.enforceJS'), - 'dealsEnforced', () => deepAccess(auctionCache.floorData, 'enforcements.floorDeals'), + 'enforcement', () => utils.deepAccess(auctionCache.floorData, 'enforcements.enforceJS'), + 'dealsEnforced', () => utils.deepAccess(auctionCache.floorData, 'enforcements.floorDeals'), 'skipRate', 'fetchStatus', 'floorMin', @@ -308,7 +267,7 @@ function sendMessage(auctionId, bidWonId, trigger) { // gather gdpr info if (auctionCache.gdprConsent) { - auction.gdpr = pick(auctionCache.gdprConsent, [ + auction.gdpr = utils.pick(auctionCache.gdprConsent, [ 'gdprApplies as applies', 'consentString', 'apiVersion as version' @@ -317,13 +276,13 @@ function sendMessage(auctionId, bidWonId, trigger) { // gather session info if (auctionCache.session) { - message.session = pick(auctionCache.session, [ + message.session = utils.pick(auctionCache.session, [ 'id', 'pvid', 'start', 'expires' ]); - if (!isEmpty(auctionCache.session.fpkvs)) { + if (!utils.isEmpty(auctionCache.session.fpkvs)) { message.fpkvs = Object.keys(auctionCache.session.fpkvs).map(key => { return { key, value: auctionCache.session.fpkvs[key] }; }); @@ -335,7 +294,7 @@ function sendMessage(auctionId, bidWonId, trigger) { } if (auctionCache.userIds.length) { - auction.user = { ids: auctionCache.userIds }; + auction.user = {ids: auctionCache.userIds}; } message.auctions = [auction]; @@ -359,12 +318,6 @@ function sendMessage(auctionId, bidWonId, trigger) { ]; } - // if we have not sent any billingEvents send them - const pendingBillingEvents = getPendingBillingEvents(auctionCache); - if (pendingBillingEvents && pendingBillingEvents.length) { - message.billableEvents = pendingBillingEvents; - } - ajax( this.getUrl(), null, @@ -375,26 +328,15 @@ function sendMessage(auctionId, bidWonId, trigger) { ); } -function getPendingBillingEvents(auctionCache) { - if (auctionCache && auctionCache.billing && auctionCache.billing.length) { - return auctionCache.billing.reduce((accum, billingEvent) => { - if (deepAccess(cache.billing, `${billingEvent.vendor}.${billingEvent.billingId}`) === false) { - accum.push(getBillingPayload(billingEvent)); - } - return accum; - }, []); - } -} - function adUnitIsOnlyInstream(adUnit) { - return adUnit.mediaTypes && Object.keys(adUnit.mediaTypes).length === 1 && deepAccess(adUnit, 'mediaTypes.video.context') === 'instream'; + return adUnit.mediaTypes && Object.keys(adUnit.mediaTypes).length === 1 && utils.deepAccess(adUnit, 'mediaTypes.video.context') === 'instream'; } function getBidPrice(bid) { // get the cpm from bidResponse let cpm; let currency; - if (bid.status === BID_REJECTED && deepAccess(bid, 'floorData.cpmAfterAdjustments')) { + if (bid.status === BID_REJECTED && utils.deepAccess(bid, 'floorData.cpmAfterAdjustments')) { // if bid was rejected and bid.floorData.cpmAfterAdjustments use it cpm = bid.floorData.cpmAfterAdjustments; currency = bid.floorData.floorCurrency; @@ -414,7 +356,7 @@ function getBidPrice(bid) { try { return Number(prebidGlobal.convertCurrency(cpm, currency, 'USD')); } catch (err) { - logWarn(`${MODULE_NAME}: Could not determine the bidPriceUSD of the bid `, bid); + utils.logWarn('Rubicon Analytics Adapter: Could not determine the bidPriceUSD of the bid ', bid); } } @@ -425,7 +367,7 @@ export function parseBidResponse(bid, previousBidResponse, auctionFloorData) { if (previousBidResponse && previousBidResponse.bidPriceUSD > responsePrice) { return previousBidResponse; } - return pick(bid, [ + return utils.pick(bid, [ 'bidPriceUSD', () => responsePrice, 'dealId', 'status', @@ -433,18 +375,17 @@ export function parseBidResponse(bid, previousBidResponse, auctionFloorData) { 'dimensions', () => { const width = bid.width || bid.playerWidth; const height = bid.height || bid.playerHeight; - return (width && height) ? { width, height } : undefined; + return (width && height) ? {width, height} : undefined; }, // Handling use case where pbs sends back 0 or '0' bidIds - 'pbsBidId', pbsBidId => pbsBidId == 0 ? generateUUID() : pbsBidId, - 'seatBidId', seatBidId => seatBidId == 0 ? generateUUID() : seatBidId, - 'floorValue', () => deepAccess(bid, 'floorData.floorValue'), - 'floorRuleValue', () => deepAccess(bid, 'floorData.floorRuleValue'), - 'floorRule', () => debugTurnedOn() ? deepAccess(bid, 'floorData.floorRule') : undefined, + 'pbsBidId', pbsBidId => pbsBidId == 0 ? utils.generateUUID() : pbsBidId, + 'seatBidId', seatBidId => seatBidId == 0 ? utils.generateUUID() : seatBidId, + 'floorValue', () => utils.deepAccess(bid, 'floorData.floorValue'), + 'floorRuleValue', () => utils.deepAccess(bid, 'floorData.floorRuleValue'), + 'floorRule', () => utils.debugTurnedOn() ? utils.deepAccess(bid, 'floorData.floorRule') : undefined, 'adomains', () => { - const adomains = deepAccess(bid, 'meta.advertiserDomains'); - const validAdomains = Array.isArray(adomains) && adomains.filter(domain => typeof domain === 'string'); - return validAdomains && validAdomains.length > 0 ? validAdomains.slice(0, 10) : undefined + let adomains = utils.deepAccess(bid, 'meta.advertiserDomains'); + return Array.isArray(adomains) && adomains.length > 0 ? adomains.slice(0, 10) : undefined } ]); } @@ -456,7 +397,7 @@ function getUtmParams() { let search; try { - search = parseQS(getWindowLocation().search); + search = utils.parseQS(utils.getWindowLocation().search); } catch (e) { search = {}; } @@ -504,7 +445,7 @@ function getRpaCookie() { try { return JSON.parse(window.atob(encodedCookie)); } catch (e) { - logError(`${MODULE_NAME}: Unable to decode ${COOKIE_NAME} value: `, e); + utils.logError(`Rubicon Analytics: Unable to decode ${COOKIE_NAME} value: `, e); } } return {}; @@ -514,7 +455,7 @@ function setRpaCookie(decodedCookie) { try { storage.setDataInLocalStorage(COOKIE_NAME, window.btoa(JSON.stringify(decodedCookie))); } catch (e) { - logError(`${MODULE_NAME}: Unable to encode ${COOKIE_NAME} value: `, e); + utils.logError(`Rubicon Analytics: Unable to encode ${COOKIE_NAME} value: `, e); } } @@ -527,7 +468,7 @@ function updateRpaCookie() { decodedRpaCookie.expires < currentTime ) { decodedRpaCookie = { - id: generateUUID(), + id: utils.generateUUID(), start: currentTime, expires: currentTime + END_EXPIRE_TIME, // six hours later, } @@ -535,7 +476,7 @@ function updateRpaCookie() { // possible that decodedRpaCookie is undefined, and if it is, we probably are blocked by storage or some other exception if (Object.keys(decodedRpaCookie).length) { decodedRpaCookie.lastSeen = currentTime; - decodedRpaCookie.fpkvs = { ...decodedRpaCookie.fpkvs, ...getFpkvs() }; + decodedRpaCookie.fpkvs = {...decodedRpaCookie.fpkvs, ...getFpkvs()}; decodedRpaCookie.pvid = rubiConf.pvid; setRpaCookie(decodedRpaCookie) } @@ -544,34 +485,25 @@ function updateRpaCookie() { function subscribeToGamSlots() { window.googletag.pubads().addEventListener('slotRenderEnded', event => { - const isMatchingAdSlot = isAdUnitCodeMatchingSlot(event.slot); + const isMatchingAdSlot = utils.isAdUnitCodeMatchingSlot(event.slot); // loop through auctions and adUnits and mark the info - // only mark first auction which finds a match - let hasMatch = false; - Object.keys(cache.auctions).find(auctionId => { + Object.keys(cache.auctions).forEach(auctionId => { (Object.keys(cache.auctions[auctionId].bids) || []).forEach(bidId => { let bid = cache.auctions[auctionId].bids[bidId]; // if this slot matches this bids adUnit, add the adUnit info - // only mark it if it already has not been marked - if (!bid.adUnit.gamRendered && isMatchingAdSlot(bid.adUnit.adUnitCode)) { + if (isMatchingAdSlot(bid.adUnit.adUnitCode)) { // mark this adUnit as having been rendered by gam cache.auctions[auctionId].gamHasRendered[bid.adUnit.adUnitCode] = true; - // this current auction has an adunit that matched the slot, so mark it as matched so next auciton is skipped - hasMatch = true; - - bid.adUnit.gam = pick(event, [ + bid.adUnit.gam = utils.pick(event, [ // these come in as `null` from Gpt, which when stringified does not get removed // so set explicitly to undefined when not a number - 'advertiserId', advertiserId => isNumber(advertiserId) ? advertiserId : undefined, - 'creativeId', creativeId => isNumber(event.sourceAgnosticCreativeId) ? event.sourceAgnosticCreativeId : isNumber(creativeId) ? creativeId : undefined, - 'lineItemId', lineItemId => isNumber(event.sourceAgnosticLineItemId) ? event.sourceAgnosticLineItemId : isNumber(lineItemId) ? lineItemId : undefined, + 'advertiserId', advertiserId => utils.isNumber(advertiserId) ? advertiserId : undefined, + 'creativeId', creativeId => utils.isNumber(event.sourceAgnosticCreativeId) ? event.sourceAgnosticCreativeId : utils.isNumber(creativeId) ? creativeId : undefined, + 'lineItemId', lineItemId => utils.isNumber(event.sourceAgnosticLineItemId) ? event.sourceAgnosticLineItemId : utils.isNumber(lineItemId) ? lineItemId : undefined, 'adSlot', () => event.slot.getAdUnitPath(), 'isSlotEmpty', () => event.isEmpty || undefined ]); - - // this lets us know next iteration not to check this bids adunit - bid.adUnit.gamRendered = true; } }); // Now if all adUnits have gam rendered, send the payload @@ -584,36 +516,11 @@ function subscribeToGamSlots() { sendMessage.call(rubiconAdapter, auctionId, undefined, 'gam') } } - return hasMatch; }); }); } -let pageReferer; - -const isBillingEventValid = event => { - // vendor is whitelisted - const isWhitelistedVendor = rubiConf.dmBilling.vendors.includes(event.vendor); - // event is not duplicated - const isNotDuplicate = typeof deepAccess(cache.billing, `${event.vendor}.${event.billingId}`) !== 'boolean'; - // billingId is defined and a string - return typeof event.billingId === 'string' && isWhitelistedVendor && isNotDuplicate; -} - -const sendOrAddEventToQueue = event => { - // if any auction is not sent yet, then add it to the auction queue - const pendingAuction = Object.keys(cache.auctions).find(auctionId => !cache.auctions[auctionId].sent); - - if (rubiConf.dmBilling.waitForAuction && pendingAuction) { - cache.auctions[pendingAuction].billing = cache.auctions[pendingAuction].billing || []; - cache.auctions[pendingAuction].billing.push(event); - } else { - // send it - sendBillingEvent(event); - } -} - -let baseAdapter = adapter({ analyticsType: 'endpoint' }); +let baseAdapter = adapter({analyticsType: 'endpoint'}); let rubiconAdapter = Object.assign({}, baseAdapter, { MODULE_INITIALIZED_TIME: Date.now(), referrerHostname: '', @@ -628,7 +535,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { if (config.options.endpoint) { this.getUrl = () => config.options.endpoint; } else { - logError(`${MODULE_NAME}: required endpoint missing`); + utils.logError('required endpoint missing from rubicon analytics'); error = true; } if (typeof config.options.sampling !== 'undefined') { @@ -636,7 +543,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { } if (typeof config.options.samplingFactor !== 'undefined') { if (typeof config.options.sampling !== 'undefined') { - logWarn(`${MODULE_NAME}: Both options.samplingFactor and options.sampling enabled defaulting to samplingFactor`); + utils.logWarn('Both options.samplingFactor and options.sampling enabled in rubicon analytics, defaulting to samplingFactor'); } samplingFactor = parseFloat(config.options.samplingFactor); config.options.sampling = 1 / samplingFactor; @@ -646,10 +553,10 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { let validSamplingFactors = [1, 10, 20, 40, 100]; if (validSamplingFactors.indexOf(samplingFactor) === -1) { error = true; - logError(`${MODULE_NAME}: invalid samplingFactor ${samplingFactor} - must be one of ${validSamplingFactors.join(', ')}`); + utils.logError('invalid samplingFactor for rubicon analytics: ' + samplingFactor + ', must be one of ' + validSamplingFactors.join(', ')); } else if (!accountId) { error = true; - logError(`${MODULE_NAME}: required accountId missing for rubicon analytics`); + utils.logError('required accountId missing for rubicon analytics'); } if (!error) { @@ -661,48 +568,45 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { accountId = undefined; rubiConf = {}; cache.gpt.registered = false; - cache.billing = {}; baseAdapter.disableAnalytics.apply(this, arguments); }, - track({ eventType, args }) { + track({eventType, args}) { switch (eventType) { case AUCTION_INIT: // set the rubicon aliases setRubiconAliases(adapterManager.aliasRegistry); - let cacheEntry = pick(args, [ + let cacheEntry = utils.pick(args, [ 'timestamp', 'timeout' ]); cacheEntry.bids = {}; cacheEntry.bidsWon = {}; cacheEntry.gamHasRendered = {}; - cacheEntry.referrer = pageReferer = deepAccess(args, 'bidderRequests.0.refererInfo.referer'); - cacheEntry.bidderOrder = []; - const floorData = deepAccess(args, 'bidderRequests.0.bids.0.floorData'); + cacheEntry.referrer = utils.deepAccess(args, 'bidderRequests.0.refererInfo.referer'); + const floorData = utils.deepAccess(args, 'bidderRequests.0.bids.0.floorData'); if (floorData) { - cacheEntry.floorData = { ...floorData }; + cacheEntry.floorData = {...floorData}; } - cacheEntry.gdprConsent = deepAccess(args, 'bidderRequests.0.gdprConsent'); + cacheEntry.gdprConsent = utils.deepAccess(args, 'bidderRequests.0.gdprConsent'); cacheEntry.session = storage.localStorageIsEnabled() && updateRpaCookie(); - cacheEntry.userIds = Object.keys(deepAccess(args, 'bidderRequests.0.bids.0.userId', {})).map(id => { - return { provider: id, hasId: true } + cacheEntry.userIds = Object.keys(utils.deepAccess(args, 'bidderRequests.0.bids.0.userId', {})).map(id => { + return {provider: id, hasId: true} }); cache.auctions[args.auctionId] = cacheEntry; // register to listen to gpt events if not done yet - if (!cache.gpt.registered && isGptPubadsDefined()) { + if (!cache.gpt.registered && utils.isGptPubadsDefined()) { subscribeToGamSlots(); cache.gpt.registered = true; } else if (!cache.gpt.registered) { cache.gpt.registered = true; window.googletag = window.googletag || {}; window.googletag.cmd = window.googletag.cmd || []; - window.googletag.cmd.push(function () { + window.googletag.cmd.push(function() { subscribeToGamSlots(); }); } break; case BID_REQUESTED: - cache.auctions[args.auctionId].bidderOrder.push(args.bidderCode); Object.assign(cache.auctions[args.auctionId].bids, args.bids.reduce((memo, bid) => { // mark adUnits we expect bidWon events for cache.auctions[args.auctionId].bidsWon[bid.adUnitCode] = false; @@ -711,7 +615,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { cache.auctions[args.auctionId].gamHasRendered[bid.adUnitCode] = false; } - memo[bid.bidId] = pick(bid, [ + memo[bid.bidId] = utils.pick(bid, [ 'bidder', bidder => bidder.toLowerCase(), 'bidId', 'status', () => 'no-bid', // default a bid to no-bid until response is recieved or bid is timed out @@ -720,7 +624,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { switch (bid.bidder) { // specify bidder params we want here case 'rubicon': - return pick(params, [ + return utils.pick(params, [ 'accountId', 'siteId', 'zoneId' @@ -736,9 +640,9 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { 204: 'mid-roll', 205: 'post-roll', 207: 'vertical' - })[deepAccess(bid, 'params.video.size_id')]; + })[utils.deepAccess(bid, 'params.video.size_id')]; } else { - let startdelay = parseInt(deepAccess(bid, 'params.video.startdelay'), 10); + let startdelay = parseInt(utils.deepAccess(bid, 'params.video.startdelay'), 10); if (!isNaN(startdelay)) { if (startdelay > 0) { return 'mid-roll'; @@ -751,7 +655,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { } } }, - 'adUnit', () => pick(bid, [ + 'adUnit', () => utils.pick(bid, [ 'adUnitCode', 'transactionId', 'sizes as dimensions', sizes => sizes.map(sizeToDimensions), @@ -765,7 +669,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { if (typeof types === 'object') { if (!bid.sizes) { bid.dimensions = []; - _each(types, (type) => + utils._each(types, (type) => bid.dimensions = bid.dimensions.concat( type.sizes.map(sizeToDimensions) ) @@ -776,13 +680,12 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { return ['banner']; }, 'gam', () => { - if (deepAccess(bid, 'ortb2Imp.ext.data.adserver.name') === 'gam') { - return { adSlot: bid.ortb2Imp.ext.data.adserver.adslot } + if (utils.deepAccess(bid, 'ortb2Imp.ext.data.adserver.name') === 'gam') { + return {adSlot: bid.ortb2Imp.ext.data.adserver.adslot} } }, - 'pbAdSlot', () => deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'), - 'pattern', () => deepAccess(bid, 'ortb2Imp.ext.data.aupname'), - 'gpid', () => deepAccess(bid, 'ortb2Imp.ext.gpid') + 'pbAdSlot', () => utils.deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'), + 'pattern', () => utils.deepAccess(bid, 'ortb2Imp.ext.data.aupname') ]) ]); return memo; @@ -792,22 +695,22 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { let auctionEntry = cache.auctions[args.auctionId]; if (!auctionEntry.bids[args.requestId] && args.originalRequestId) { - auctionEntry.bids[args.requestId] = { ...auctionEntry.bids[args.originalRequestId] }; + auctionEntry.bids[args.requestId] = {...auctionEntry.bids[args.originalRequestId]}; auctionEntry.bids[args.requestId].bidId = args.requestId; auctionEntry.bids[args.requestId].bidderDetail = args.targetingBidder; } let bid = auctionEntry.bids[args.requestId]; // If floor resolved gptSlot but we have not yet, then update the adUnit to have the adSlot name - if (!deepAccess(bid, 'adUnit.gam.adSlot') && deepAccess(args, 'floorData.matchedFields.gptSlot')) { - deepSetValue(bid, 'adUnit.gam.adSlot', args.floorData.matchedFields.gptSlot); + if (!utils.deepAccess(bid, 'adUnit.gam.adSlot') && utils.deepAccess(args, 'floorData.matchedFields.gptSlot')) { + utils.deepSetValue(bid, 'adUnit.gam.adSlot', args.floorData.matchedFields.gptSlot); } // if we have not set enforcements yet set it - if (!deepAccess(auctionEntry, 'floorData.enforcements') && deepAccess(args, 'floorData.enforcements')) { - auctionEntry.floorData.enforcements = { ...args.floorData.enforcements }; + if (!utils.deepAccess(auctionEntry, 'floorData.enforcements') && utils.deepAccess(args, 'floorData.enforcements')) { + auctionEntry.floorData.enforcements = {...args.floorData.enforcements}; } if (!bid) { - logError(`${MODULE_NAME}: Could not find associated bid request for bid response with requestId: `, args.requestId); + utils.logError('Rubicon Anlytics Adapter Error: Could not find associated bid request for bid response with requestId: ', args.requestId); break; } bid.source = formatSource(bid.source || args.source); @@ -830,7 +733,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { bid.bidResponse = parseBidResponse(args, bid.bidResponse); break; case BIDDER_DONE: - const serverError = deepAccess(args, 'serverErrors.0'); + const serverError = utils.deepAccess(args, 'serverErrors.0'); const serverResponseTimeMs = args.serverResponseTimeMs; args.bids.forEach(bid => { let cachedBid = cache.auctions[bid.auctionId].bids[bid.bidId || bid.requestId]; @@ -878,12 +781,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { break; case AUCTION_END: // see how long it takes for the payload to come fire - let auctionData = cache.auctions[args.auctionId]; - // if for some reason the auction did not do its normal thing, this could be undefied so bail - if (!auctionData) { - break; - } - auctionData.endTs = Date.now(); + cache.auctions[args.auctionId].endTs = Date.now(); const isOnlyInstreamAuction = args.adUnits && args.adUnits.every(adUnit => adUnitIsOnlyInstream(adUnit)); // If only instream, do not wait around, just send payload @@ -905,19 +803,11 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { bid.status = 'error'; bid.error = { code: 'timeout-error', - description: 'prebid.js timeout' // will help us diff if timeout was set by PBS or PBJS + message: 'marked by prebid.js as timeout' // will help us diff if timeout was set by PBS or PBJS }; } }); break; - case BILLABLE_EVENT: - if (rubiConf.dmBilling.enabled && isBillingEventValid(args)) { - // add to the map indicating it has not been sent yet - deepSetValue(cache.billing, `${args.vendor}.${args.billingId}`, false); - sendOrAddEventToQueue(args); - } else { - logInfo(`${MODULE_NAME}: Billing event ignored`, args); - } } } }); diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index afb95d56d69..354289a1823 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -1,35 +1,21 @@ -import { - _each, - convertTypes, - deepAccess, - deepSetValue, - formatQS, - isArray, - isNumber, - isStr, - logError, - logMessage, - logWarn, - mergeDeep, - parseSizesInput -} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {find} from '../src/polyfill.js'; -import {Renderer} from '../src/Renderer.js'; -import {getGlobal} from '../src/prebidGlobal.js'; +import find from 'core-js-pure/features/array/find.js'; +import { Renderer } from '../src/Renderer.js'; +import { getGlobal } from '../src/prebidGlobal.js'; const DEFAULT_INTEGRATION = 'pbjs_lite'; const DEFAULT_PBS_INTEGRATION = 'pbjs'; -const DEFAULT_RENDERER_URL = 'https://video-outstream.rubiconproject.com/apex-2.2.1.js'; +const DEFAULT_RENDERER_URL = 'https://video-outstream.rubiconproject.com/apex-2.0.0.js'; // renderer code at https://github.com/rubicon-project/apex2 let rubiConf = {}; // we are saving these as global to this module so that if a pub accidentally overwrites the entire // rubicon object, then we do not lose other data config.getConfig('rubicon', config => { - mergeDeep(rubiConf, config.rubicon); + utils.mergeDeep(rubiConf, config.rubicon); }); const GVLID = 52; @@ -124,19 +110,9 @@ var sizeMap = { 548: '500x1000', 550: '980x480', 552: '300x200', - 558: '640x640', - 562: '300x431', - 564: '320x431', - 566: '320x300', - 568: '300x150', - 570: '300x125', - 572: '250x350', - 574: '620x891', - 576: '610x877', - 578: '980x552', - 580: '505x656' + 558: '640x640' }; -_each(sizeMap, (item, key) => sizeMap[item] = key); +utils._each(sizeMap, (item, key) => sizeMap[item] = key); export const spec = { code: 'rubicon', @@ -154,7 +130,7 @@ export const spec = { for (let i = 0, props = ['accountId', 'siteId', 'zoneId']; i < props.length; i++) { bid.params[props[i]] = parseInt(bid.params[props[i]]) if (isNaN(bid.params[props[i]])) { - logError('Rubicon: wrong format of accountId or siteId or zoneId.') + utils.logError('Rubicon: wrong format of accountId or siteId or zoneId.') return false } } @@ -194,7 +170,7 @@ export const spec = { ext: { [bidRequest.bidder]: bidRequest.params }, - video: deepAccess(bidRequest, 'mediaTypes.video') || {} + video: utils.deepAccess(bidRequest, 'mediaTypes.video') || {} }], ext: { prebid: { @@ -231,7 +207,7 @@ export const spec = { let modules = (getGlobal()).installedModules; if (modules && (!modules.length || modules.indexOf('rubiconAnalyticsAdapter') !== -1)) { - deepSetValue(data, 'ext.prebid.analytics', {'rubicon': {'client-analytics': true}}); + utils.deepSetValue(data, 'ext.prebid.analytics', {'rubicon': {'client-analytics': true}}); } let bidFloor; @@ -244,11 +220,11 @@ export const spec = { size: parseSizes(bidRequest, 'video') }); } catch (e) { - logError('Rubicon: getFloor threw an error: ', e); + utils.logError('Rubicon: getFloor threw an error: ', e); } bidFloor = typeof floorInfo === 'object' && floorInfo.currency === 'USD' && !isNaN(parseInt(floorInfo.floor)) ? parseFloat(floorInfo.floor) : undefined; } else { - bidFloor = parseFloat(deepAccess(bidRequest, 'params.floor')); + bidFloor = parseFloat(utils.deepAccess(bidRequest, 'params.floor')); } if (!isNaN(bidFloor)) { data.imp[0].bidfloor = bidFloor; @@ -267,36 +243,36 @@ export const spec = { gdprApplies = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; } - deepSetValue(data, 'regs.ext.gdpr', gdprApplies); - deepSetValue(data, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(data, 'regs.ext.gdpr', gdprApplies); + utils.deepSetValue(data, 'user.ext.consent', bidderRequest.gdprConsent.consentString); } if (bidderRequest.uspConsent) { - deepSetValue(data, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(data, 'regs.ext.us_privacy', bidderRequest.uspConsent); } - const eids = deepAccess(bidderRequest, 'bids.0.userIdAsEids'); + const eids = utils.deepAccess(bidderRequest, 'bids.0.userIdAsEids'); if (eids && eids.length) { - deepSetValue(data, 'user.ext.eids', eids); + utils.deepSetValue(data, 'user.ext.eids', eids); } // set user.id value from config value const configUserId = config.getConfig('user.id'); if (configUserId) { - deepSetValue(data, 'user.id', configUserId); + utils.deepSetValue(data, 'user.id', configUserId); } if (config.getConfig('coppa') === true) { - deepSetValue(data, 'regs.coppa', 1); + utils.deepSetValue(data, 'regs.coppa', 1); } if (bidRequest.schain && hasValidSupplyChainParams(bidRequest.schain)) { - deepSetValue(data, 'source.ext.schain', bidRequest.schain); + utils.deepSetValue(data, 'source.ext.schain', bidRequest.schain); } const multibid = config.getConfig('multibid'); if (multibid) { - deepSetValue(data, 'ext.prebid.multibid', multibid.reduce((result, i) => { + utils.deepSetValue(data, 'ext.prebid.multibid', multibid.reduce((result, i) => { let obj = {}; Object.keys(i).forEach(key => { @@ -313,11 +289,11 @@ export const spec = { // if storedAuctionResponse has been set, pass SRID if (bidRequest.storedAuctionResponse) { - deepSetValue(data.imp[0], 'ext.prebid.storedauctionresponse.id', bidRequest.storedAuctionResponse.toString()); + utils.deepSetValue(data.imp[0], 'ext.prebid.storedauctionresponse.id', bidRequest.storedAuctionResponse.toString()); } // set ext.prebid.auctiontimestamp using auction time - deepSetValue(data.imp[0], 'ext.prebid.auctiontimestamp', bidderRequest.auctionStart); + utils.deepSetValue(data.imp[0], 'ext.prebid.auctiontimestamp', bidderRequest.auctionStart); return { method: 'POST', @@ -336,14 +312,14 @@ export const spec = { url: `https://${rubiConf.bannerHost || 'fastlane'}.rubiconproject.com/a/api/fastlane.json`, data: spec.getOrderedParams(bidParams).reduce((paramString, key) => { const propValue = bidParams[key]; - return ((isStr(propValue) && propValue !== '') || isNumber(propValue)) ? `${paramString}${encodeParam(key, propValue)}&` : paramString; + return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${encodeParam(key, propValue)}&` : paramString; }, '') + `slots=1&rand=${Math.random()}`, bidRequest }; })); } else { // single request requires bids to be grouped by site id into a single request - // note: groupBy wasn't used because deep property access was needed + // note: utils.groupBy wasn't used because deep property access was needed const nonVideoRequests = bidRequests.filter(bidRequest => bidType(bidRequest) === 'banner'); const groupedBidRequests = nonVideoRequests.reduce((groupedBids, bid) => { (groupedBids[bid.params['siteId']] = groupedBids[bid.params['siteId']] || []).push(bid); @@ -367,7 +343,7 @@ export const spec = { url: `https://${rubiConf.bannerHost || 'fastlane'}.rubiconproject.com/a/api/fastlane.json`, data: spec.getOrderedParams(combinedSlotParams).reduce((paramString, key) => { const propValue = combinedSlotParams[key]; - return ((isStr(propValue) && propValue !== '') || isNumber(propValue)) ? `${paramString}${encodeParam(key, propValue)}&` : paramString; + return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${encodeParam(key, propValue)}&` : paramString; }, '') + `slots=${bidsInGroup.length}&rand=${Math.random()}`, bidRequest: bidsInGroup }); @@ -407,7 +383,6 @@ export const spec = { .concat([ 'tk_flint', 'x_source.tid', - 'l_pb_bid_id', 'x_source.pchain', 'p_screen_res', 'rp_floor', @@ -481,7 +456,6 @@ export const spec = { 'rp_secure': '1', 'tk_flint': `${rubiConf.int_type || DEFAULT_INTEGRATION}_v$prebid.version$`, 'x_source.tid': bidRequest.transactionId, - 'l_pb_bid_id': bidRequest.bidId, 'x_source.pchain': params.pchain, 'p_screen_res': _getScreenResolution(), 'tk_user_key': params.userId, @@ -501,7 +475,7 @@ export const spec = { size: '*' }); } catch (e) { - logError('Rubicon: getFloor threw an error: ', e); + utils.logError('Rubicon: getFloor threw an error: ', e); } data['rp_hard_floor'] = typeof floorInfo === 'object' && floorInfo.currency === 'USD' && !isNaN(parseInt(floorInfo.floor)) ? floorInfo.floor : undefined; } @@ -509,7 +483,7 @@ export const spec = { // add p_pos only if specified and valid // For SRA we need to explicitly put empty semi colons so AE treats it as empty, instead of copying the latter value let posMapping = {1: 'atf', 3: 'btf'}; - let pos = posMapping[deepAccess(bidRequest, 'mediaTypes.banner.pos')] || ''; + let pos = posMapping[utils.deepAccess(bidRequest, 'mediaTypes.banner.pos')] || ''; data['p_pos'] = (params.position === 'atf' || params.position === 'btf') ? params.position : pos; // pass publisher provided userId if configured @@ -548,7 +522,7 @@ export const spec = { } } } catch (e) { - logWarn('Rubicon: error reading eid:', eid, e); + utils.logWarn('Rubicon: error reading eid:', eid, e); } }); } @@ -621,9 +595,9 @@ export const spec = { // video response from PBS Java openRTB if (responseObj.seatbid) { - const responseErrors = deepAccess(responseObj, 'ext.errors.rubicon'); + const responseErrors = utils.deepAccess(responseObj, 'ext.errors.rubicon'); if (Array.isArray(responseErrors) && responseErrors.length > 0) { - logWarn('Rubicon: Error in video response'); + utils.logWarn('Rubicon: Error in video response'); } const bids = []; responseObj.seatbid.forEach(seatbid => { @@ -636,8 +610,8 @@ export const spec = { bidderCode: seatbid.seat, ttl: 300, netRevenue: rubiConf.netRevenue !== false, // If anything other than false, netRev is true - width: bid.w || deepAccess(bidRequest, 'mediaTypes.video.w') || deepAccess(bidRequest, 'params.video.playerWidth'), - height: bid.h || deepAccess(bidRequest, 'mediaTypes.video.h') || deepAccess(bidRequest, 'params.video.playerHeight'), + width: bid.w || utils.deepAccess(bidRequest, 'mediaTypes.video.w') || utils.deepAccess(bidRequest, 'params.video.playerWidth'), + height: bid.h || utils.deepAccess(bidRequest, 'mediaTypes.video.h') || utils.deepAccess(bidRequest, 'params.video.playerHeight'), }; if (bid.id) { @@ -649,22 +623,22 @@ export const spec = { } if (bid.adomain) { - deepSetValue(bidObject, 'meta.advertiserDomains', Array.isArray(bid.adomain) ? bid.adomain : [bid.adomain]); + utils.deepSetValue(bidObject, 'meta.advertiserDomains', Array.isArray(bid.adomain) ? bid.adomain : [bid.adomain]); } - if (deepAccess(bid, 'ext.bidder.rp.advid')) { - deepSetValue(bidObject, 'meta.advertiserId', bid.ext.bidder.rp.advid); + if (utils.deepAccess(bid, 'ext.bidder.rp.advid')) { + utils.deepSetValue(bidObject, 'meta.advertiserId', bid.ext.bidder.rp.advid); } - let serverResponseTimeMs = deepAccess(responseObj, 'ext.responsetimemillis.rubicon'); + let serverResponseTimeMs = utils.deepAccess(responseObj, 'ext.responsetimemillis.rubicon'); if (bidRequest && serverResponseTimeMs) { bidRequest.serverResponseTimeMs = serverResponseTimeMs; } - if (deepAccess(bid, 'ext.prebid.type') === VIDEO) { + if (utils.deepAccess(bid, 'ext.prebid.type') === VIDEO) { bidObject.mediaType = VIDEO; - deepSetValue(bidObject, 'meta.mediaType', VIDEO); - const extPrebidTargeting = deepAccess(bid, 'ext.prebid.targeting'); + utils.deepSetValue(bidObject, 'meta.mediaType', VIDEO); + const extPrebidTargeting = utils.deepAccess(bid, 'ext.prebid.targeting'); // If ext.prebid.targeting exists, add it as a property value named 'adserverTargeting' if (extPrebidTargeting && typeof extPrebidTargeting === 'object') { @@ -686,12 +660,12 @@ export const spec = { if (bid.nurl) { bidObject.vastUrl = bid.nurl; } if (!bidObject.vastUrl && bid.nurl) { bidObject.vastUrl = bid.nurl; } - const videoContext = deepAccess(bidRequest, 'mediaTypes.video.context'); + const videoContext = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); if (videoContext.toLowerCase() === 'outstream') { bidObject.renderer = outstreamRenderer(bidObject); } } else { - logWarn('Rubicon: video response received non-video media type'); + utils.logWarn('Rubicon: video response received non-video media type'); } bids.push(bidObject); @@ -770,7 +744,7 @@ export const spec = { bids.push(bid); } else { - logError(`Rubicon: bidRequest undefined at index position:${i}`, bidRequest, responseObj); + utils.logError(`Rubicon: bidRequest undefined at index position:${i}`, bidRequest, responseObj); } return bids; @@ -781,23 +755,21 @@ export const spec = { getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent) { if (!hasSynced && syncOptions.iframeEnabled) { // data is only assigned if params are available to pass to syncEndpoint - let params = {}; + let params = ''; - if (gdprConsent) { + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + // add 'gdpr' only if 'gdprApplies' is defined if (typeof gdprConsent.gdprApplies === 'boolean') { - params['gdpr'] = Number(gdprConsent.gdprApplies); - } - if (typeof gdprConsent.consentString === 'string') { - params['gdpr_consent'] = gdprConsent.consentString; + params += `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { + params += `?gdpr_consent=${gdprConsent.consentString}`; } } if (uspConsent) { - params['us_privacy'] = encodeURIComponent(uspConsent); + params += `${params ? '&' : '?'}us_privacy=${encodeURIComponent(uspConsent)}`; } - params = Object.keys(params).length ? `?${formatQS(params)}` : ''; - hasSynced = true; return { type: 'iframe', @@ -812,7 +784,7 @@ export const spec = { * @return {Object} params bid params */ transformBidParams: function(params, isOpenRtb) { - return convertTypes({ + return utils.convertTypes({ 'accountId': 'number', 'siteId': 'number', 'zoneId': 'number' @@ -880,7 +852,7 @@ function renderBid(bid) { height: bid.height, vastUrl: bid.vastUrl, placement: { - attachTo: adUnitElement, + attachTo: `#${bid.adUnitCode}`, align: config.align || 'center', position: config.position || 'append' }, @@ -903,7 +875,7 @@ function outstreamRenderer(rtbBid) { try { renderer.setRender(renderBid); } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); + utils.logWarn('Prebid Error calling setRender on renderer', err); } return renderer; @@ -918,7 +890,7 @@ function parseSizes(bid, mediaType) { params.video.playerWidth, params.video.playerHeight ]; - } else if (Array.isArray(deepAccess(bid, 'mediaTypes.video.playerSize')) && bid.mediaTypes.video.playerSize.length === 1) { + } else if (Array.isArray(utils.deepAccess(bid, 'mediaTypes.video.playerSize')) && bid.mediaTypes.video.playerSize.length === 1) { size = bid.mediaTypes.video.playerSize[0]; } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0 && Array.isArray(bid.sizes[0]) && bid.sizes[0].length > 1) { size = bid.sizes[0]; @@ -930,12 +902,12 @@ function parseSizes(bid, mediaType) { let sizes = []; if (Array.isArray(params.sizes)) { sizes = params.sizes; - } else if (typeof deepAccess(bid, 'mediaTypes.banner.sizes') !== 'undefined') { + } else if (typeof utils.deepAccess(bid, 'mediaTypes.banner.sizes') !== 'undefined') { sizes = mapSizes(bid.mediaTypes.banner.sizes); } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) { sizes = mapSizes(bid.sizes) } else { - logWarn('Rubicon: no sizes are setup or found'); + utils.logWarn('Rubicon: no sizes are setup or found'); } return masSizeOrdering(sizes); @@ -964,11 +936,7 @@ function appendSiteAppDevice(data, bidRequest, bidderRequest) { if (bidRequest.params.video.language) { ['site', 'device'].forEach(function(param) { if (data[param]) { - if (param === 'site') { - data[param].content = Object.assign({language: bidRequest.params.video.language}, data[param].content) - } else { - data[param] = Object.assign({language: bidRequest.params.video.language}, data[param]) - } + data[param].content = Object.assign({language: bidRequest.params.video.language}, data[param].content) } }); } @@ -1006,18 +974,16 @@ function applyFPD(bidRequest, mediaType, data) { site: {ext: {data: {...bidRequest.params.inventory}}} }; - if (bidRequest.params.keywords) BID_FPD.site.keywords = (isArray(bidRequest.params.keywords)) ? bidRequest.params.keywords.join(',') : bidRequest.params.keywords; - - let fpd = mergeDeep({}, config.getConfig('ortb2') || {}, BID_FPD); - let impData = deepAccess(bidRequest.ortb2Imp, 'ext.data') || {}; + if (bidRequest.params.keywords) BID_FPD.site.keywords = (utils.isArray(bidRequest.params.keywords)) ? bidRequest.params.keywords.join(',') : bidRequest.params.keywords; - const gpid = deepAccess(bidRequest, 'ortb2Imp.ext.gpid'); + let fpd = utils.mergeDeep({}, config.getConfig('ortb2') || {}, BID_FPD); + let impData = utils.deepAccess(bidRequest.ortb2Imp, 'ext.data') || {}; const SEGTAX = {user: [4], site: [1, 2, 5, 6]}; const MAP = {user: 'tg_v.', site: 'tg_i.', adserver: 'tg_i.dfp_ad_unit_code', pbadslot: 'tg_i.pbadslot', keywords: 'kw'}; const validate = function(prop, key, parentName) { if (key === 'data' && Array.isArray(prop)) { - return prop.filter(name => name.segment && deepAccess(name, 'ext.segtax') && SEGTAX[parentName] && - SEGTAX[parentName].indexOf(deepAccess(name, 'ext.segtax')) !== -1).map(value => { + return prop.filter(name => name.segment && utils.deepAccess(name, 'ext.segtax') && SEGTAX[parentName] && + SEGTAX[parentName].indexOf(utils.deepAccess(name, 'ext.segtax')) !== -1).map(value => { let segments = value.segment.filter(obj => obj.id).reduce((result, obj) => { result.push(obj.id); return result; @@ -1025,12 +991,12 @@ function applyFPD(bidRequest, mediaType, data) { if (segments.length > 0) return segments.toString(); }).toString(); } else if (typeof prop === 'object' && !Array.isArray(prop)) { - logWarn('Rubicon: Filtered FPD key: ', key, ': Expected value to be string, integer, or an array of strings/ints'); + utils.logWarn('Rubicon: Filtered FPD key: ', key, ': Expected value to be string, integer, or an array of strings/ints'); } else if (typeof prop !== 'undefined') { return (Array.isArray(prop)) ? prop.filter(value => { if (typeof value !== 'object' && typeof value !== 'undefined') return value.toString(); - logWarn('Rubicon: Filtered value: ', value, 'for key', key, ': Expected value to be string, integer, or an array of strings/ints'); + utils.logWarn('Rubicon: Filtered value: ', value, 'for key', key, ': Expected value to be string, integer, or an array of strings/ints'); }).toString() : prop.toString(); } }; @@ -1040,6 +1006,16 @@ function applyFPD(bidRequest, mediaType, data) { data[loc] = (data[loc]) ? data[loc].concat(',', val) : val; } + Object.keys(impData).forEach((key) => { + if (key === 'adserver') { + ['name', 'adslot'].forEach(prop => { + if (impData[key][prop]) impData[key][prop] = impData[key][prop].toString().replace(/^\/+/, ''); + }); + } else if (key === 'pbadslot') { + impData[key] = impData[key].toString().replace(/^\/+/, ''); + } + }); + if (mediaType === BANNER) { ['site', 'user'].forEach(name => { Object.keys(fpd[name]).forEach((key) => { @@ -1055,32 +1031,14 @@ function applyFPD(bidRequest, mediaType, data) { }); }); Object.keys(impData).forEach((key) => { - if (key !== 'adserver') { - addBannerData(impData[key], 'site', key); - } else if (impData[key].name === 'gam') { - addBannerData(impData[key].adslot, name, key) - } + (key === 'adserver') ? addBannerData(impData[key].adslot, name, key) : addBannerData(impData[key], 'site', key); }); - - // add in gpid - if (gpid) { - data['p_gpid'] = gpid; - } - - // only send one of pbadslot or dfp adunit code (prefer pbadslot) - if (data['tg_i.pbadslot']) { - delete data['tg_i.dfp_ad_unit_code']; - } } else { if (Object.keys(impData).length) { - mergeDeep(data.imp[0].ext, {data: impData}); - } - // add in gpid - if (gpid) { - data.imp[0].ext.gpid = gpid; + utils.mergeDeep(data.imp[0].ext, {data: impData}); } - mergeDeep(data, fpd); + utils.mergeDeep(data, fpd); } } @@ -1089,7 +1047,7 @@ function applyFPD(bidRequest, mediaType, data) { * @returns {*} */ function mapSizes(sizes) { - return parseSizesInput(sizes) + return utils.parseSizesInput(sizes) // map sizes while excluding non-matches .reduce((result, size) => { let mappedSize = parseInt(sizeMap[size], 10); @@ -1107,10 +1065,10 @@ function mapSizes(sizes) { * @returns {boolean} */ export function hasVideoMediaType(bidRequest) { - if (typeof deepAccess(bidRequest, 'params.video') !== 'object') { + if (typeof utils.deepAccess(bidRequest, 'params.video') !== 'object') { return false; } - return (typeof deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'); + return (typeof utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'); } /** @@ -1124,9 +1082,9 @@ function bidType(bid, log = false) { if (hasVideoMediaType(bid)) { // Removed legacy mediaType support. new way using mediaTypes.video object is now required // We require either context as instream or outstream - if (['outstream', 'instream'].indexOf(deepAccess(bid, `mediaTypes.${VIDEO}.context`)) === -1) { + if (['outstream', 'instream'].indexOf(utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`)) === -1) { if (log) { - logError('Rubicon: mediaTypes.video.context must be outstream or instream'); + utils.logError('Rubicon: mediaTypes.video.context must be outstream or instream'); } return; } @@ -1134,13 +1092,13 @@ function bidType(bid, log = false) { // we require playerWidth and playerHeight to come from one of params.playerWidth/playerHeight or mediaTypes.video.playerSize or adUnit.sizes if (parseSizes(bid, 'video').length < 2) { if (log) { - logError('Rubicon: could not determine the playerSize of the video'); + utils.logError('Rubicon: could not determine the playerSize of the video'); } return; } if (log) { - logMessage('Rubicon: making video request for adUnit', bid.adUnitCode); + utils.logMessage('Rubicon: making video request for adUnit', bid.adUnitCode); } return 'video'; } else { @@ -1148,14 +1106,14 @@ function bidType(bid, log = false) { // if we cannot determine them, we reject it! if (parseSizes(bid, 'banner').length === 0) { if (log) { - logError('Rubicon: could not determine the sizes for banner request'); + utils.logError('Rubicon: could not determine the sizes for banner request'); } return; } // everything looks good for banner so lets do it if (log) { - logMessage('Rubicon: making banner request for adUnit', bid.adUnitCode); + utils.logMessage('Rubicon: making banner request for adUnit', bid.adUnitCode); } return 'banner'; } @@ -1187,13 +1145,13 @@ export function masSizeOrdering(sizes) { export function determineRubiconVideoSizeId(bid) { // If we have size_id in the bid then use it - let rubiconSizeId = parseInt(deepAccess(bid, 'params.video.size_id')); + let rubiconSizeId = parseInt(utils.deepAccess(bid, 'params.video.size_id')); if (!isNaN(rubiconSizeId)) { return rubiconSizeId; } // otherwise 203 for outstream and 201 for instream // When this function is used we know it has to be one of outstream or instream - return deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'outstream' ? 203 : 201; + return utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'outstream' ? 203 : 201; } /** @@ -1236,9 +1194,9 @@ export function hasValidVideoParams(bid) { } // loop through each param and verify it has the correct Object.keys(requiredParams).forEach(function(param) { - if (Object.prototype.toString.call(deepAccess(bid, 'mediaTypes.video.' + param)) !== requiredParams[param]) { + if (Object.prototype.toString.call(utils.deepAccess(bid, 'mediaTypes.video.' + param)) !== requiredParams[param]) { isValid = false; - logError('Rubicon: mediaTypes.video.' + param + ' is required and must be of type: ' + requiredParams[param]); + utils.logError('Rubicon: mediaTypes.video.' + param + ' is required and must be of type: ' + requiredParams[param]); } }) return isValid; @@ -1257,7 +1215,7 @@ export function hasValidSupplyChainParams(schain) { if (!status) return status; return requiredFields.every(field => node.hasOwnProperty(field)); }, true); - if (!isValid) logError('Rubicon: required schain params missing'); + if (!isValid) utils.logError('Rubicon: required schain params missing'); return isValid; } diff --git a/modules/s2sTesting.js b/modules/s2sTesting.js index 8e9628c8810..1f2bb473174 100644 --- a/modules/s2sTesting.js +++ b/modules/s2sTesting.js @@ -1,12 +1,12 @@ -import {PARTITIONS, partitionBidders, filterBidsForAdUnit, getS2SBidderSet} from '../src/adapterManager.js'; -import {find} from '../src/polyfill.js'; -import {getBidderCodes, logWarn} from '../src/utils.js'; +import { setS2STestingModule } from '../src/adapterManager.js'; -const {CLIENT, SERVER} = PARTITIONS; -export const s2sTesting = { - ...PARTITIONS, - clientTestBidders: new Set() -}; +let s2sTesting = {}; + +const SERVER = 'server'; +const CLIENT = 'client'; + +s2sTesting.SERVER = SERVER; +s2sTesting.CLIENT = CLIENT; s2sTesting.bidSource = {}; // store bidder sources determined from s2sConfig bidderControl s2sTesting.globalRand = Math.random(); // if 10% of bidderA and 10% of bidderB should be server-side, make it the same 10% @@ -40,7 +40,7 @@ s2sTesting.getSourceBidderMap = function(adUnits = [], allS2SBidders = []) { [SERVER]: Object.keys(sourceBidders[SERVER]), [CLIENT]: Object.keys(sourceBidders[CLIENT]) }; -} +}; /** * @function calculateBidSources determines the source for each s2s bidder based on bidderControl weightings. these can be overridden at the adUnit level @@ -53,7 +53,7 @@ s2sTesting.calculateBidSources = function(s2sConfig = {}) { (s2sConfig.bidders || []).forEach((bidder) => { s2sTesting.bidSource[bidder] = s2sTesting.getSource(bidderControl[bidder] && bidderControl[bidder].bidSource) || SERVER; // default to server }); -} +}; /** * @function getSource() gets a random source based on the given sourceWeights (export just for testing) @@ -76,59 +76,10 @@ s2sTesting.getSource = function(sourceWeights = {}, bidSources = [SERVER, CLIENT // choose the first source with an incremental weight > random weight if (rndWeight < srcIncWeight[source]) return source; } -} - -function doingS2STesting(s2sConfig) { - return s2sConfig && s2sConfig.enabled && s2sConfig.testing; -} - -function isTestingServerOnly(s2sConfig) { - return Boolean(doingS2STesting(s2sConfig) && s2sConfig.testServerOnly); -} - -const adUnitsContainServerRequests = (adUnits, s2sConfig) => Boolean( - find(adUnits, adUnit => find(adUnit.bids, bid => ( - bid.bidSource || - (s2sConfig.bidderControl && s2sConfig.bidderControl[bid.bidder]) - ) && bid.finalSource === SERVER)) -); - -partitionBidders.before(function (next, adUnits, s2sConfigs) { - const serverBidders = getS2SBidderSet(s2sConfigs); - let serverOnly = false; - - s2sConfigs.forEach((s2sConfig) => { - if (doingS2STesting(s2sConfig)) { - s2sTesting.calculateBidSources(s2sConfig); - const bidderMap = s2sTesting.getSourceBidderMap(adUnits, [...serverBidders]); - // get all adapters doing client testing - bidderMap[CLIENT].forEach((bidder) => s2sTesting.clientTestBidders.add(bidder)) - } - if (isTestingServerOnly(s2sConfig) && adUnitsContainServerRequests(adUnits, s2sConfig)) { - logWarn('testServerOnly: True. All client requests will be suppressed.'); - serverOnly = true; - } - }); - - next.bail(getBidderCodes(adUnits).reduce((memo, bidder) => { - if (serverBidders.has(bidder)) { - memo[SERVER].push(bidder); - } - if (!serverOnly && (!serverBidders.has(bidder) || s2sTesting.clientTestBidders.has(bidder))) { - memo[CLIENT].push(bidder); - } - return memo; - }, {[CLIENT]: [], [SERVER]: []})); -}); +}; -filterBidsForAdUnit.before(function(next, bids, s2sConfig) { - if (s2sConfig == null) { - next.bail(bids.filter((bid) => !s2sTesting.clientTestBidders.size || bid.finalSource !== SERVER)); - } else { - const serverBidders = getS2SBidderSet(s2sConfig); - next.bail(bids.filter((bid) => serverBidders.has(bid.bidder) && - (!doingS2STesting(s2sConfig) || bid.finalSource !== CLIENT))); - } -}); +// inject the s2sTesting module into the adapterManager rather than importing it +// importing it causes the packager to include it even when it's not explicitly included in the build +setS2STestingModule(s2sTesting); export default s2sTesting; diff --git a/modules/saambaaBidAdapter.js b/modules/saambaaBidAdapter.js deleted file mode 100644 index 36ab50bfddd..00000000000 --- a/modules/saambaaBidAdapter.js +++ /dev/null @@ -1,419 +0,0 @@ -import {deepAccess, generateUUID, isEmpty, isFn, parseSizesInput, parseUrl} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {find, includes} from '../src/polyfill.js'; - -const ADAPTER_VERSION = '1.0'; -const BIDDER_CODE = 'saambaa'; - -export const VIDEO_ENDPOINT = 'https://nep.advangelists.com/xp/get?pubid='; -export const BANNER_ENDPOINT = 'https://nep.advangelists.com/xp/get?pubid='; -export const OUTSTREAM_SRC = 'https://player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js'; -export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration', 'skip', 'playerSize', 'context']; -export const DEFAULT_MIMES = ['video/mp4', 'application/javascript']; - -let pubid = ''; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO], - - isBidRequestValid(bidRequest) { - if (typeof bidRequest != 'undefined') { - if (bidRequest.bidder !== BIDDER_CODE && typeof bidRequest.params === 'undefined') { return false; } - if (bidRequest === '' || bidRequest.params.placement === '' || bidRequest.params.pubid === '') { return false; } - return true; - } else { return false; } - }, - - buildRequests(bids, bidderRequest) { - let requests = []; - let videoBids = bids.filter(bid => isVideoBidValid(bid)); - let bannerBids = bids.filter(bid => isBannerBidValid(bid)); - videoBids.forEach(bid => { - pubid = getVideoBidParam(bid, 'pubid'); - requests.push({ - method: 'POST', - url: VIDEO_ENDPOINT + pubid, - data: createVideoRequestData(bid, bidderRequest), - bidRequest: bid - }); - }); - - bannerBids.forEach(bid => { - pubid = getBannerBidParam(bid, 'pubid'); - - requests.push({ - method: 'POST', - url: BANNER_ENDPOINT + pubid, - data: createBannerRequestData(bid, bidderRequest), - bidRequest: bid - }); - }); - return requests; - }, - - interpretResponse(serverResponse, {bidRequest}) { - let response = serverResponse.body; - if (response !== null && isEmpty(response) == false) { - if (isVideoBid(bidRequest)) { - let bidResponse = { - requestId: response.id, - bidderCode: BIDDER_CODE, - cpm: response.seatbid[0].bid[0].price, - width: response.seatbid[0].bid[0].w, - height: response.seatbid[0].bid[0].h, - ttl: response.seatbid[0].bid[0].ttl || 60, - creativeId: response.seatbid[0].bid[0].crid, - currency: response.cur, - meta: { 'advertiserDomains': response.seatbid[0].bid[0].adomain }, - mediaType: VIDEO, - netRevenue: true - } - - if (response.seatbid[0].bid[0].adm) { - bidResponse.vastXml = response.seatbid[0].bid[0].adm; - bidResponse.adResponse = { - content: response.seatbid[0].bid[0].adm - }; - } else { - bidResponse.vastUrl = response.seatbid[0].bid[0].nurl; - } - - return bidResponse; - } else { - return { - requestId: response.id, - bidderCode: BIDDER_CODE, - cpm: response.seatbid[0].bid[0].price, - width: response.seatbid[0].bid[0].w, - height: response.seatbid[0].bid[0].h, - ad: response.seatbid[0].bid[0].adm, - ttl: response.seatbid[0].bid[0].ttl || 60, - creativeId: response.seatbid[0].bid[0].crid, - currency: response.cur, - meta: { 'advertiserDomains': response.seatbid[0].bid[0].adomain }, - mediaType: BANNER, - netRevenue: true - } - } - } - } -}; - -function isBannerBid(bid) { - return deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid); -} - -function isVideoBid(bid) { - return deepAccess(bid, 'mediaTypes.video'); -} - -function getBannerBidFloor(bid) { - let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'banner', size: '*' }) : {}; - return floorInfo.floor || getBannerBidParam(bid, 'bidfloor'); -} - -function getVideoBidFloor(bid) { - let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'video', size: '*' }) : {}; - return floorInfo.floor || getVideoBidParam(bid, 'bidfloor'); -} - -function isVideoBidValid(bid) { - return isVideoBid(bid) && getVideoBidParam(bid, 'pubid') && getVideoBidParam(bid, 'placement'); -} - -function isBannerBidValid(bid) { - return isBannerBid(bid) && getBannerBidParam(bid, 'pubid') && getBannerBidParam(bid, 'placement'); -} - -function getVideoBidParam(bid, key) { - return deepAccess(bid, 'params.video.' + key) || deepAccess(bid, 'params.' + key); -} - -function getBannerBidParam(bid, key) { - return deepAccess(bid, 'params.banner.' + key) || deepAccess(bid, 'params.' + key); -} - -function isMobile() { - return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent); -} - -function isConnectedTV() { - return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent); -} - -function getDoNotTrack() { - return navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.msDoNoTrack === '1' || navigator.doNotTrack === 'yes'; -} - -function findAndFillParam(o, key, value) { - try { - if (typeof value === 'function') { - o[key] = value(); - } else { - o[key] = value; - } - } catch (ex) {} -} - -function getOsVersion() { - let clientStrings = [ - { s: 'Android', r: /Android/ }, - { s: 'iOS', r: /(iPhone|iPad|iPod)/ }, - { s: 'Mac OS X', r: /Mac OS X/ }, - { s: 'Mac OS', r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ }, - { s: 'Linux', r: /(Linux|X11)/ }, - { s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ }, - { s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ }, - { s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ }, - { s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ }, - { s: 'Windows Vista', r: /Windows NT 6.0/ }, - { s: 'Windows Server 2003', r: /Windows NT 5.2/ }, - { s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ }, - { s: 'UNIX', r: /UNIX/ }, - { s: 'Search Bot', r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ } - ]; - let cs = find(clientStrings, cs => cs.r.test(navigator.userAgent)); - return cs ? cs.s : 'unknown'; -} - -function getFirstSize(sizes) { - return (sizes && sizes.length) ? sizes[0] : { w: undefined, h: undefined }; -} - -function parseSizes(sizes) { - return parseSizesInput(sizes).map(size => { - let [ width, height ] = size.split('x'); - return { - w: parseInt(width, 10) || undefined, - h: parseInt(height, 10) || undefined - }; - }); -} - -function getVideoSizes(bid) { - return parseSizes(deepAccess(bid, 'mediaTypes.video.playerSize') || bid.sizes); -} - -function getBannerSizes(bid) { - return parseSizes(deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes); -} - -function getTopWindowReferrer() { - try { - return window.top.document.referrer; - } catch (e) { - return ''; - } -} - -function getVideoTargetingParams(bid) { - const result = {}; - const excludeProps = ['playerSize', 'context', 'w', 'h']; - Object.keys(Object(bid.mediaTypes.video)) - .filter(key => !includes(excludeProps, key)) - .forEach(key => { - result[ key ] = bid.mediaTypes.video[ key ]; - }); - Object.keys(Object(bid.params.video)) - .filter(key => includes(VIDEO_TARGETING, key)) - .forEach(key => { - result[ key ] = bid.params.video[ key ]; - }); - return result; -} - -function createVideoRequestData(bid, bidderRequest) { - let topLocation = getTopWindowLocation(bidderRequest); - let topReferrer = getTopWindowReferrer(); - - // if size is explicitly given via adapter params - let paramSize = getVideoBidParam(bid, 'size'); - let sizes = []; - let coppa = config.getConfig('coppa'); - - if (typeof paramSize !== 'undefined' && paramSize != '') { - sizes = parseSizes(paramSize); - } else { - sizes = getVideoSizes(bid); - } - const firstSize = getFirstSize(sizes); - let floor = (getVideoBidFloor(bid) == null || typeof getVideoBidFloor(bid) == 'undefined') ? 0.5 : getVideoBidFloor(bid); - let video = getVideoTargetingParams(bid); - const o = { - 'device': { - 'langauge': (global.navigator.language).split('-')[0], - 'dnt': (global.navigator.doNotTrack === 1 ? 1 : 0), - 'devicetype': isMobile() ? 4 : isConnectedTV() ? 3 : 2, - 'js': 1, - 'os': getOsVersion() - }, - 'at': 2, - 'site': {}, - 'tmax': 3000, - 'cur': ['USD'], - 'id': bid.bidId, - 'imp': [], - 'regs': { - 'ext': { - } - }, - 'user': { - 'ext': { - } - } - }; - - o.site['page'] = topLocation.href; - o.site['domain'] = topLocation.hostname; - o.site['search'] = topLocation.search; - o.site['domain'] = topLocation.hostname; - o.site['ref'] = topReferrer; - o.site['mobile'] = isMobile() ? 1 : 0; - const secure = topLocation.protocol.indexOf('https') === 0 ? 1 : 0; - - o.device['dnt'] = getDoNotTrack() ? 1 : 0; - - findAndFillParam(o.site, 'name', function() { - return global.top.document.title; - }); - - findAndFillParam(o.device, 'h', function() { - return global.screen.height; - }); - findAndFillParam(o.device, 'w', function() { - return global.screen.width; - }); - - let placement = getVideoBidParam(bid, 'placement'); - - for (let j = 0; j < sizes.length; j++) { - o.imp.push({ - 'id': '' + j, - 'displaymanager': '' + BIDDER_CODE, - 'displaymanagerver': '' + ADAPTER_VERSION, - 'tagId': placement, - 'bidfloor': floor, - 'bidfloorcur': 'USD', - 'secure': secure, - 'video': Object.assign({ - 'id': generateUUID(), - 'pos': 0, - 'w': firstSize.w, - 'h': firstSize.h, - 'mimes': DEFAULT_MIMES - }, video) - - }); - } - if (coppa) { - o.regs.ext = {'coppa': 1}; - } - if (bidderRequest && bidderRequest.gdprConsent) { - let { gdprApplies, consentString } = bidderRequest.gdprConsent; - o.regs.ext = {'gdpr': gdprApplies ? 1 : 0}; - o.user.ext = {'consent': consentString}; - } - - return o; -} - -function getTopWindowLocation(bidderRequest) { - let url = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; - return parseUrl(config.getConfig('pageUrl') || url, { decodeSearchAsString: true }); -} - -function createBannerRequestData(bid, bidderRequest) { - let topLocation = getTopWindowLocation(bidderRequest); - let topReferrer = getTopWindowReferrer(); - - // if size is explicitly given via adapter params - - let paramSize = getBannerBidParam(bid, 'size'); - let sizes = []; - let coppa = config.getConfig('coppa'); - if (typeof paramSize !== 'undefined' && paramSize != '') { - sizes = parseSizes(paramSize); - } else { - sizes = getBannerSizes(bid); - } - - let floor = (getBannerBidFloor(bid) == null || typeof getBannerBidFloor(bid) == 'undefined') ? 0.1 : getBannerBidFloor(bid); - const o = { - 'device': { - 'langauge': (global.navigator.language).split('-')[0], - 'dnt': (global.navigator.doNotTrack === 1 ? 1 : 0), - 'devicetype': isMobile() ? 4 : isConnectedTV() ? 3 : 2, - 'js': 1 - }, - 'at': 2, - 'site': {}, - 'tmax': 3000, - 'cur': ['USD'], - 'id': bid.bidId, - 'imp': [], - 'regs': { - 'ext': { - } - }, - 'user': { - 'ext': { - } - } - }; - - o.site['page'] = topLocation.href; - o.site['domain'] = topLocation.hostname; - o.site['search'] = topLocation.search; - o.site['domain'] = topLocation.hostname; - o.site['ref'] = topReferrer; - o.site['mobile'] = isMobile() ? 1 : 0; - const secure = topLocation.protocol.indexOf('https') === 0 ? 1 : 0; - - o.device['dnt'] = getDoNotTrack() ? 1 : 0; - - findAndFillParam(o.site, 'name', function() { - return global.top.document.title; - }); - - findAndFillParam(o.device, 'h', function() { - return global.screen.height; - }); - findAndFillParam(o.device, 'w', function() { - return global.screen.width; - }); - - let placement = getBannerBidParam(bid, 'placement'); - for (let j = 0; j < sizes.length; j++) { - let size = sizes[j]; - - o.imp.push({ - 'id': '' + j, - 'displaymanager': '' + BIDDER_CODE, - 'displaymanagerver': '' + ADAPTER_VERSION, - 'tagId': placement, - 'bidfloor': floor, - 'bidfloorcur': 'USD', - 'secure': secure, - 'banner': { - 'id': generateUUID(), - 'pos': 0, - 'w': size['w'], - 'h': size['h'] - } - }); - } - if (coppa) { - o.regs.ext = {'coppa': 1}; - } - if (bidderRequest && bidderRequest.gdprConsent) { - let { gdprApplies, consentString } = bidderRequest.gdprConsent; - o.regs.ext = {'gdpr': gdprApplies ? 1 : 0}; - o.user.ext = {'consent': consentString}; - } - - return o; -} -registerBidder(spec); diff --git a/modules/saambaaBidAdapter.md b/modules/saambaaBidAdapter.md index d58e3f0abfa..2d391da7628 100755 --- a/modules/saambaaBidAdapter.md +++ b/modules/saambaaBidAdapter.md @@ -1,66 +1,69 @@ -# Overview - -``` -Module Name: Saambaa Bidder Adapter -Module Type: Bidder Adapter -Maintainer: matt.voigt@saambaa.com -``` - -# Description - -Connects to Saambaa exchange for bids. - -Saambaa bid adapter supports Banner and Video ads currently. - -For more informatio - -# Sample Display Ad Unit: For Publishers -```javascript - -var displayAdUnit = [ -{ - code: 'display', - mediaTypes: { - banner: { - sizes: [[300, 250],[320, 50]] - } - } - bids: [{ - bidder: 'saambaa', - params: { - pubid: '121ab139faf7ac67428a23f1d0a9a71b', - placement: 1234, - size: '320x50' - } - }] -}]; -``` - -# Sample Video Ad Unit: For Publishers -```javascript - -var videoAdUnit = { - code: 'video', - sizes: [320,480], - mediaTypes: { - video: { - playerSize : [[320, 480]], - context: 'instream', - skip: 1, - mimes : ['video/mp4', 'application/javascript'], - playbackmethod : [2,6], - maxduration: 30 - } - }, - bids: [ - { - bidder: 'saambaa', - params: { - pubid: '121ab139faf7ac67428a23f1d0a9a71b', - placement: 1234, - size: "320x480" - } - } - ] - }; +# Overview + +``` +Module Name: Saambaa Bidder Adapter +Module Type: Bidder Adapter +Maintainer: matt.voigt@saambaa.com +``` + +# Description + +Connects to Saambaa exchange for bids. + +Saambaa bid adapter supports Banner and Video ads currently. + +For more informatio + +# Sample Display Ad Unit: For Publishers +```javascript + +var displayAdUnit = [ +{ + code: 'display', + mediaTypes: { + banner: { + sizes: [[300, 250],[320, 50]] + } + } + bids: [{ + bidder: 'saambaa', + params: { + pubid: '121ab139faf7ac67428a23f1d0a9a71b', + placement: 1234, + size: '320x50' + } + }] +}]; +``` + +# Sample Video Ad Unit: For Publishers +```javascript + +var videoAdUnit = { + code: 'video', + sizes: [320,480], + mediaTypes: { + video: { + playerSize : [[320, 480]], + context: 'instream' + } + }, + bids: [ + { + bidder: 'saambaa', + params: { + pubid: '121ab139faf7ac67428a23f1d0a9a71b', + placement: 1234, + size: "320x480", + video: { + id: 123, + skip: 1, + mimes : ['video/mp4', 'application/javascript'], + playbackmethod : [2,6], + maxduration: 30 + } + } + } + ] + }; ``` \ No newline at end of file diff --git a/modules/scaleableAnalyticsAdapter.js b/modules/scaleableAnalyticsAdapter.js index d7379462e0d..955a08c065a 100644 --- a/modules/scaleableAnalyticsAdapter.js +++ b/modules/scaleableAnalyticsAdapter.js @@ -4,7 +4,7 @@ import { ajax } from '../src/ajax.js'; import CONSTANTS from '../src/constants.json'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; -import { logMessage } from '../src/utils.js'; +import * as utils from '../src/utils.js'; // Object.entries polyfill const entries = Object.entries || function(obj) { @@ -62,7 +62,7 @@ scaleableAnalytics.enableAnalytics = config => { scaleableAnalytics.originEnableAnalytics(config); scaleableAnalytics.enableAnalytics = function _enable() { - return logMessage(`Analytics adapter for "${global}" already enabled, unnecessary call to \`enableAnalytics\`.`); + return utils.logMessage(`Analytics adapter for "${global}" already enabled, unnecessary call to \`enableAnalytics\`.`); }; } diff --git a/modules/seedingAllianceBidAdapter.js b/modules/seedingAllianceBidAdapter.js deleted file mode 100755 index a071cdfea80..00000000000 --- a/modules/seedingAllianceBidAdapter.js +++ /dev/null @@ -1,235 +0,0 @@ -// jshint esversion: 6, es3: false, node: true -'use strict'; - -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { NATIVE } from '../src/mediaTypes.js'; -import { _map, deepSetValue, isEmpty, deepAccess } from '../src/utils.js'; -import { config } from '../src/config.js'; - -const BIDDER_CODE = 'seedingAlliance'; -const DEFAULT_CUR = 'EUR'; -const ENDPOINT_URL = 'https://b.nativendo.de/cds/rtb/bid?format=openrtb2.5&ssp=pb'; - -const NATIVE_ASSET_IDS = {0: 'title', 1: 'body', 2: 'sponsoredBy', 3: 'image', 4: 'cta', 5: 'icon'}; - -const NATIVE_PARAMS = { - title: { - id: 0, - name: 'title' - }, - - body: { - id: 1, - name: 'data', - type: 2 - }, - - sponsoredBy: { - id: 2, - name: 'data', - type: 1 - }, - - image: { - id: 3, - type: 3, - name: 'img' - }, - - cta: { - id: 4, - type: 12, - name: 'data' - }, - - icon: { - id: 5, - type: 1, - name: 'img' - } -}; - -export const spec = { - code: BIDDER_CODE, - - supportedMediaTypes: [NATIVE], - - isBidRequestValid: function(bid) { - return !!bid.params.adUnitId; - }, - - buildRequests: (validBidRequests, bidderRequest) => { - const pt = setOnAny(validBidRequests, 'params.pt') || setOnAny(validBidRequests, 'params.priceType') || 'net'; - const tid = validBidRequests[0].transactionId; - const cur = [config.getConfig('currency.adServerCurrency') || DEFAULT_CUR]; - let url = bidderRequest.refererInfo.referer; - - const imp = validBidRequests.map((bid, id) => { - const assets = _map(bid.nativeParams, (bidParams, key) => { - const props = NATIVE_PARAMS[key]; - - const asset = { - required: bidParams.required & 1 - }; - - if (props) { - asset.id = props.id; - - let w, h; - - if (bidParams.sizes) { - w = bidParams.sizes[0]; - h = bidParams.sizes[1]; - } - - asset[props.name] = { - len: bidParams.len, - type: props.type, - w, - h - }; - - return asset; - } - }) - .filter(Boolean); - - if (bid.params.url) { - url = bid.params.url; - } - - return { - id: String(id + 1), - tagid: bid.params.adUnitId, - tid: tid, - pt: pt, - native: { - request: { - assets - } - } - }; - }); - - const request = { - id: bidderRequest.auctionId, - site: { - page: url - }, - device: { - ua: navigator.userAgent - }, - cur, - imp, - user: {}, - regs: { - ext: { - gdpr: 0, - pb_ver: '$prebid.version$' - } - } - }; - - if (bidderRequest && bidderRequest.gdprConsent) { - deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(request, 'regs.ext.gdpr', (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean' && bidderRequest.gdprConsent.gdprApplies) ? 1 : 0); - } - - return { - method: 'POST', - url: ENDPOINT_URL, - data: JSON.stringify(request), - options: { - contentType: 'application/json' - }, - bids: validBidRequests - }; - }, - - interpretResponse: function(serverResponse, { bids }) { - if (isEmpty(serverResponse.body)) { - return []; - } - - const { seatbid, cur } = serverResponse.body; - - const bidResponses = (typeof seatbid != 'undefined') ? flatten(seatbid.map(seat => seat.bid)).reduce((result, bid) => { - result[bid.impid - 1] = bid; - return result; - }, []) : []; - - return bids - .map((bid, id) => { - const bidResponse = bidResponses[id]; - - if (bidResponse) { - return { - requestId: bid.bidId, - cpm: bidResponse.price, - creativeId: bidResponse.crid, - ttl: 1000, - netRevenue: (!bid.netRevenue || bid.netRevenue === 'net'), - currency: cur, - mediaType: NATIVE, - bidderCode: BIDDER_CODE, - native: parseNative(bidResponse), - meta: { - advertiserDomains: bidResponse.adomain && bidResponse.adomain.length > 0 ? bidResponse.adomain : [] - } - }; - } - }) - .filter(Boolean); - } -}; - -registerBidder(spec); - -function parseNative(bid) { - const {assets, link, imptrackers} = bid.adm.native; - - let clickUrl = link.url.replace(/\$\{AUCTION_PRICE\}/g, bid.price); - - if (link.clicktrackers) { - link.clicktrackers.forEach(function (clicktracker, index) { - link.clicktrackers[index] = clicktracker.replace(/\$\{AUCTION_PRICE\}/g, bid.price); - }); - } - - if (imptrackers) { - imptrackers.forEach(function (imptracker, index) { - imptrackers[index] = imptracker.replace(/\$\{AUCTION_PRICE\}/g, bid.price); - }); - } - - const result = { - url: clickUrl, - clickUrl: clickUrl, - clickTrackers: link.clicktrackers || undefined, - impressionTrackers: imptrackers || undefined - }; - - assets.forEach(asset => { - const kind = NATIVE_ASSET_IDS[asset.id]; - const content = kind && asset[NATIVE_PARAMS[kind].name]; - - if (content) { - result[kind] = content.text || content.value || { url: content.url, width: content.w, height: content.h }; - } - }); - - return result; -} - -function setOnAny(collection, key) { - for (let i = 0, result; i < collection.length; i++) { - result = deepAccess(collection[i], key); - if (result) { - return result; - } - } -} - -function flatten(arr) { - return [].concat(...arr); -} diff --git a/modules/seedtagBidAdapter.js b/modules/seedtagBidAdapter.js index 2f61e0bc56a..8b7629df211 100644 --- a/modules/seedtagBidAdapter.js +++ b/modules/seedtagBidAdapter.js @@ -1,4 +1,4 @@ -import { isArray, _map, triggerPixel } from '../src/utils.js'; +import * as utils from '../src/utils.js' import { registerBidder } from '../src/adapters/bidderFactory.js' import { VIDEO, BANNER } from '../src/mediaTypes.js' @@ -13,11 +13,6 @@ const ALLOWED_PLACEMENTS = { banner: true, video: true } - -// Global Vendor List Id -// https://iabeurope.eu/vendor-list-tcf-v2-0/ -const GVLID = 157; - const mediaTypesMap = { [BANNER]: 'display', [VIDEO]: 'video' @@ -67,13 +62,13 @@ function hasMandatoryVideoParams(bid) { const videoParams = getVideoParams(bid) return hasVideoMediaType(bid) && !!videoParams.playerSize && - isArray(videoParams.playerSize) && + utils.isArray(videoParams.playerSize) && videoParams.playerSize.length > 0; } function buildBidRequest(validBidRequest) { const params = validBidRequest.params; - const mediaTypes = _map( + const mediaTypes = utils._map( Object.keys(validBidRequest.mediaTypes), function (pbjsType) { return mediaTypesMap[pbjsType]; @@ -150,23 +145,19 @@ function buildBidResponse(seedtagBid) { export function getTimeoutUrl (data) { let queryParams = ''; if ( - isArray(data) && data[0] && - isArray(data[0].params) && data[0].params[0] + utils.isArray(data) && data[0] && + utils.isArray(data[0].params) && data[0].params[0] ) { const params = data[0].params[0]; - const timeout = data[0].timeout - queryParams = '?publisherToken=' + params.publisherId + - '&adUnitId=' + params.adUnitId + - '&timeout=' + timeout; + '&adUnitId=' + params.adUnitId; } return SEEDTAG_SSP_ONTIMEOUT_ENDPOINT + queryParams; } export const spec = { code: BIDDER_CODE, - gvlid: GVLID, aliases: [SEEDTAG_ALIAS], supportedMediaTypes: [BANNER, VIDEO], /** @@ -195,7 +186,7 @@ export const spec = { timeout: bidderRequest.timeout, version: '$prebid.version$', connectionType: getConnectionType(), - bidRequests: _map(validBidRequests, buildBidRequest) + bidRequests: utils._map(validBidRequests, buildBidRequest) }; if (payload.cmp) { @@ -220,8 +211,8 @@ export const spec = { */ interpretResponse: function(serverResponse) { const serverBody = serverResponse.body; - if (serverBody && serverBody.bids && isArray(serverBody.bids)) { - return _map(serverBody.bids, function(bid) { + if (serverBody && serverBody.bids && utils.isArray(serverBody.bids)) { + return utils._map(serverBody.bids, function(bid) { return buildBidResponse(bid); }); } else { @@ -252,7 +243,7 @@ export const spec = { */ onTimeout(data) { const url = getTimeoutUrl(data); - triggerPixel(url); + utils.triggerPixel(url); }, /** @@ -261,7 +252,7 @@ export const spec = { */ onBidWon: function (bid) { if (bid && bid.nurl) { - triggerPixel(bid.nurl); + utils.triggerPixel(bid.nurl); } } } diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 656b62815c7..2e3abd6b1a2 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -5,13 +5,13 @@ * @requires module:modules/userId */ -import { parseUrl, buildUrl, triggerPixel, logInfo, hasDeviceAccess, generateUUID } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {submodule} from '../src/hook.js'; import { coppaDataHandler } from '../src/adapterManager.js'; import {getStorageManager} from '../src/storageManager.js'; const GVLID = 887; -export const storage = getStorageManager({gvlid: GVLID, moduleName: 'pubCommonId'}); +const storage = getStorageManager(GVLID, 'pubCommonId'); const COOKIE = 'cookie'; const LOCAL_STORAGE = 'html5'; const OPTOUT_NAME = '_pubcid_optout'; @@ -53,12 +53,12 @@ function queuePixelCallback(pixelUrl, id = '', callback) { } // Use pubcid as a cache buster - const urlInfo = parseUrl(pixelUrl); + const urlInfo = utils.parseUrl(pixelUrl); urlInfo.search.id = encodeURIComponent('pubcid:' + id); - const targetUrl = buildUrl(urlInfo); + const targetUrl = utils.buildUrl(urlInfo); return function () { - triggerPixel(targetUrl); + utils.triggerPixel(targetUrl); }; } @@ -89,10 +89,10 @@ export const sharedIdSystemSubmodule = { */ decode(value, config) { if (hasOptedOut()) { - logInfo('PubCommonId decode: Has opted-out'); + utils.logInfo('PubCommonId decode: Has opted-out'); return undefined; } - logInfo(' Decoded value PubCommonId ' + value); + utils.logInfo(' Decoded value PubCommonId ' + value); const idObj = {'pubcid': value}; return idObj; }, @@ -106,13 +106,13 @@ export const sharedIdSystemSubmodule = { */ getId: function (config = {}, consentData, storedId) { if (hasOptedOut()) { - logInfo('PubCommonId: Has opted-out'); + utils.logInfo('PubCommonId: Has opted-out'); return; } const coppa = coppaDataHandler.getCoppa(); if (coppa) { - logInfo('PubCommonId: IDs not provided for coppa requests, exiting PubCommonId'); + utils.logInfo('PubCommonId: IDs not provided for coppa requests, exiting PubCommonId'); return; } const {params: {create = true, pixelUrl} = {}} = config; @@ -126,7 +126,7 @@ export const sharedIdSystemSubmodule = { } catch (e) { } - if (!newId) newId = (create && hasDeviceAccess()) ? generateUUID() : undefined; + if (!newId) newId = (create && utils.hasDeviceAccess()) ? utils.generateUUID() : undefined; } const pixelCallback = queuePixelCallback(pixelUrl, newId); @@ -153,12 +153,12 @@ export const sharedIdSystemSubmodule = { */ extendId: function(config = {}, consentData, storedId) { if (hasOptedOut()) { - logInfo('PubCommonId: Has opted-out'); + utils.logInfo('PubCommonId: Has opted-out'); return {id: undefined}; } const coppa = coppaDataHandler.getCoppa(); if (coppa) { - logInfo('PubCommonId: IDs not provided for coppa requests, exiting PubCommonId'); + utils.logInfo('PubCommonId: IDs not provided for coppa requests, exiting PubCommonId'); return; } const {params: {extend = false, pixelUrl} = {}} = config; @@ -171,33 +171,7 @@ export const sharedIdSystemSubmodule = { return {id: storedId}; } } - }, - - domainOverride: function () { - const domainElements = document.domain.split('.'); - const cookieName = `_gd${Date.now()}`; - for (let i = 0, topDomain, testCookie; i < domainElements.length; i++) { - const nextDomain = domainElements.slice(i).join('.'); - - // write test cookie - storage.setCookie(cookieName, '1', undefined, undefined, nextDomain); - - // read test cookie to verify domain was valid - testCookie = storage.getCookie(cookieName); - - // delete test cookie - storage.setCookie(cookieName, '', 'Thu, 01 Jan 1970 00:00:01 GMT', undefined, nextDomain); - - if (testCookie === '1') { - // cookie was written successfully using test domain so the topDomain is updated - topDomain = nextDomain; - } else { - // cookie failed to write using test domain so exit by returning the topDomain - return topDomain; - } - } } - }; submodule('userId', sharedIdSystemSubmodule); diff --git a/modules/sharethroughAnalyticsAdapter.js b/modules/sharethroughAnalyticsAdapter.js index 4f065cbca23..5147b2a4275 100644 --- a/modules/sharethroughAnalyticsAdapter.js +++ b/modules/sharethroughAnalyticsAdapter.js @@ -1,6 +1,6 @@ -import { tryAppendQueryString } from '../src/utils.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; +const utils = require('../src/utils.js'); const emptyUrl = ''; const analyticsType = 'endpoint'; @@ -42,18 +42,18 @@ var sharethroughAdapter = Object.assign(adapter( fireLoseBeacon(winningBidderCode, winningCPM, arid, type) { let loseBeaconUrl = this.STR_BEACON_HOST; - loseBeaconUrl = tryAppendQueryString(loseBeaconUrl, 'winnerBidderCode', winningBidderCode); - loseBeaconUrl = tryAppendQueryString(loseBeaconUrl, 'winnerCpm', winningCPM); - loseBeaconUrl = tryAppendQueryString(loseBeaconUrl, 'arid', arid); - loseBeaconUrl = tryAppendQueryString(loseBeaconUrl, 'type', type); + loseBeaconUrl = utils.tryAppendQueryString(loseBeaconUrl, 'winnerBidderCode', winningBidderCode); + loseBeaconUrl = utils.tryAppendQueryString(loseBeaconUrl, 'winnerCpm', winningCPM); + loseBeaconUrl = utils.tryAppendQueryString(loseBeaconUrl, 'arid', arid); + loseBeaconUrl = utils.tryAppendQueryString(loseBeaconUrl, 'type', type); loseBeaconUrl = this.appendEnvFields(loseBeaconUrl); this.fireBeacon(loseBeaconUrl); }, appendEnvFields(url) { - url = tryAppendQueryString(url, 'hbVersion', '$prebid.version$'); - url = tryAppendQueryString(url, 'strVersion', STR_VERSION); - url = tryAppendQueryString(url, 'hbSource', 'prebid'); + url = utils.tryAppendQueryString(url, 'hbVersion', '$prebid.version$'); + url = utils.tryAppendQueryString(url, 'strVersion', STR_VERSION); + url = utils.tryAppendQueryString(url, 'hbSource', 'prebid'); return url; }, diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index 1dd95812e12..967d8194607 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -1,183 +1,123 @@ -import { deepAccess, generateUUID, inIframe } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; -import { createEidsArray } from './userId/eids.js'; -const VERSION = '4.1.0'; +const VERSION = '3.4.1'; const BIDDER_CODE = 'sharethrough'; -const SUPPLY_ID = 'WYu2BXv1'; - -const STR_ENDPOINT = `https://btlr.sharethrough.com/universal/v1?supply_id=${SUPPLY_ID}`; +const STR_ENDPOINT = 'https://btlr.sharethrough.com/WYu2BXv1/v1'; +const DEFAULT_SIZE = [1, 1]; // this allows stubbing of utility function that is used internally by the sharethrough adapter export const sharethroughInternal = { - getProtocol, + b64EncodeUnicode, + handleIframe, + isLockedInFrame, + getProtocol }; export const sharethroughAdapterSpec = { code: BIDDER_CODE, - supportedMediaTypes: [VIDEO, BANNER], - gvlid: 80, + isBidRequestValid: bid => !!bid.params.pkey && bid.bidder === BIDDER_CODE, buildRequests: (bidRequests, bidderRequest) => { - const timeout = config.getConfig('bidderTimeout'); - const firstPartyData = config.getConfig('ortb2') || {}; - - const nonHttp = sharethroughInternal.getProtocol().indexOf('http') < 0; - const secure = nonHttp || (sharethroughInternal.getProtocol().indexOf('https') > -1); - - const req = { - id: generateUUID(), - at: 1, - cur: ['USD'], - tmax: timeout, - site: { - domain: window.location.hostname, - page: window.location.href, - ref: deepAccess(bidderRequest, 'refererInfo.referer'), - ...firstPartyData.site, - }, - device: { - ua: navigator.userAgent, - language: navigator.language, - js: 1, - dnt: navigator.doNotTrack === '1' ? 1 : 0, - h: window.screen.height, - w: window.screen.width, - }, - regs: { - coppa: config.getConfig('coppa') === true ? 1 : 0, - ext: {}, - }, - source: { - ext: { - version: '$prebid.version$', - str: VERSION, - schain: bidRequests[0].schain, - }, - }, - bcat: bidRequests[0].params.bcat || [], - badv: bidRequests[0].params.badv || [], - test: 0, - }; - - req.user = nullish(firstPartyData.user, {}); - if (!req.user.ext) req.user.ext = {}; - req.user.ext.eids = userIdAsEids(bidRequests[0]); - - if (bidderRequest.gdprConsent) { - const gdprApplies = bidderRequest.gdprConsent.gdprApplies === true; - req.regs.ext.gdpr = gdprApplies ? 1 : 0; - if (gdprApplies) { - req.user.ext.consent = bidderRequest.gdprConsent.consentString; + return bidRequests.map(bidRequest => { + let query = { + placement_key: bidRequest.params.pkey, + bidId: bidRequest.bidId, + consent_required: false, + instant_play_capable: canAutoPlayHTML5Video(), + hbSource: 'prebid', + hbVersion: '$prebid.version$', + strVersion: VERSION, + }; + + const gpid = utils.deepAccess(bidRequest, 'ortb2Imp.ext.data.pbadslot'); + if (gpid) { + query.gpid = gpid; } - } - if (bidderRequest.uspConsent) { - req.regs.ext.us_privacy = bidderRequest.uspConsent; - } + Object.assign(query, handleUniversalIds(bidRequest)); - const imps = bidRequests.map(bidReq => { - const impression = {}; + const nonHttp = sharethroughInternal.getProtocol().indexOf('http') < 0; + query.secure = nonHttp || (sharethroughInternal.getProtocol().indexOf('https') > -1); - const gpid = deepAccess(bidReq, 'ortb2Imp.ext.data.pbadslot'); - if (gpid) { - impression.ext = { gpid: gpid }; + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString) { + query.consent_string = bidderRequest.gdprConsent.consentString; } - const videoRequest = deepAccess(bidReq, 'mediaTypes.video'); - - if (videoRequest) { - // default playerSize, only change this if we know width and height are properly defined in the request - let [w, h] = [640, 360]; - if (videoRequest.playerSize && videoRequest.playerSize[0] && videoRequest.playerSize[1]) { - [w, h] = videoRequest.playerSize; - } - - impression.video = { - pos: nullish(videoRequest.pos, 0), - topframe: inIframe() ? 0 : 1, - skip: nullish(videoRequest.skip, 0), - linearity: nullish(videoRequest.linearity, 1), - minduration: nullish(videoRequest.minduration, 5), - maxduration: nullish(videoRequest.maxduration, 60), - playbackmethod: videoRequest.playbackmethod || [2], - api: getVideoApi(videoRequest), - mimes: videoRequest.mimes || ['video/mp4'], - protocols: getVideoProtocols(videoRequest), - w, - h, - startdelay: nullish(videoRequest.startdelay, 0), - skipmin: nullish(videoRequest.skipmin, 0), - skipafter: nullish(videoRequest.skipafter, 0), - placement: videoRequest.context === 'instream' ? 1 : +deepAccess(videoRequest, 'placement', 4), - }; - - if (videoRequest.delivery) impression.video.delivery = videoRequest.delivery; - if (videoRequest.companiontype) impression.video.companiontype = videoRequest.companiontype; - if (videoRequest.companionad) impression.video.companionad = videoRequest.companionad; - } else { - impression.banner = { - pos: deepAccess(bidReq, 'mediaTypes.banner.pos', 0), - topframe: inIframe() ? 0 : 1, - format: bidReq.sizes.map(size => ({ w: +size[0], h: +size[1] })), - }; + if (bidderRequest && bidderRequest.gdprConsent) { + query.consent_required = !!bidderRequest.gdprConsent.gdprApplies; } - return { - id: bidReq.bidId, - tagid: String(bidReq.params.pkey), - secure: secure ? 1 : 0, - bidfloor: getBidRequestFloor(bidReq), - ...impression, + if (bidderRequest && bidderRequest.uspConsent) { + query.us_privacy = bidderRequest.uspConsent + } + + if (config.getConfig('coppa') === true) { + query.coppa = true + } + + if (bidRequest.schain) { + query.schain = JSON.stringify(bidRequest.schain); + } + + const floor = getFloor(bidRequest); + if (floor) { + query.bidfloor = floor; + } + + if (bidRequest.params.badv) { + query.badv = bidRequest.params.badv; + } + + if (bidRequest.params.bcat) { + query.bcat = bidRequest.params.bcat; + } + + // Data that does not need to go to the server, + // but we need as part of interpretResponse() + const strData = { + skipIframeBusting: bidRequest.params.iframe, + iframeSize: bidRequest.params.iframeSize, + sizes: bidRequest.sizes }; - }).filter(imp => !!imp); - return imps.map(impression => { return { method: 'POST', url: STR_ENDPOINT, - data: { - ...req, - imp: [impression], - }, + data: query, + strData: strData }; - }); + }) }, interpretResponse: ({ body }, req) => { - if (!body || !body.seatbid || body.seatbid.length === 0 || !body.seatbid[0].bid || body.seatbid[0].bid.length === 0) { + if (!body || !body.creatives || !body.creatives.length) { return []; } - return body.seatbid[0].bid.map(bid => { - const response = { - requestId: bid.impid, - width: +bid.w, - height: +bid.h, - cpm: +bid.price, - creativeId: bid.crid, - dealId: bid.dealid || null, - mediaType: req.data.imp[0].video ? VIDEO : BANNER, - currency: body.cur || 'USD', - netRevenue: true, - ttl: 360, - ad: bid.adm, - nurl: bid.nurl, - meta: { - advertiserDomains: bid.adomain || [], - }, - }; - - if (response.mediaType === VIDEO) { - response.ttl = 3600; - response.vastXml = bid.adm; - } + const creative = body.creatives[0]; + let size = DEFAULT_SIZE; + if (req.strData.iframeSize || req.strData.sizes.length) { + size = req.strData.iframeSize + ? req.strData.iframeSize + : getLargestSize(req.strData.sizes); + } - return response; - }); + return [{ + requestId: req.data.bidId, + width: size[0], + height: size[1], + cpm: creative.cpm, + creativeId: creative.creative.creative_key, + dealId: creative.creative.deal_id, + currency: 'USD', + netRevenue: true, + ttl: 360, + meta: { advertiserDomains: creative.creative && creative.creative.adomain ? creative.creative.adomain : [] }, + ad: generateAd(body, req) + }]; }, getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { @@ -198,73 +138,175 @@ export const sharethroughAdapterSpec = { }, // Empty implementation for prebid core to be able to find it - onTimeout: (data) => { - }, + onTimeout: (data) => {}, // Empty implementation for prebid core to be able to find it - onBidWon: (bid) => { - }, + onBidWon: (bid) => {}, // Empty implementation for prebid core to be able to find it - onSetTargeting: (bid) => { - }, + onSetTargeting: (bid) => {} }; -function getVideoApi({ api }) { - let defaultValue = [2]; - if (api && Array.isArray(api) && api.length > 0) { - return api; - } else { - return defaultValue; +function handleUniversalIds(bidRequest) { + if (!bidRequest.userId) return {}; + + const universalIds = {}; + + const ttd = utils.deepAccess(bidRequest, 'userId.tdid'); + if (ttd) universalIds.ttduid = ttd; + + const pubc = utils.deepAccess(bidRequest, 'userId.pubcid') || utils.deepAccess(bidRequest, 'crumbs.pubcid'); + if (pubc) universalIds.pubcid = pubc; + + const idl = utils.deepAccess(bidRequest, 'userId.idl_env'); + if (idl) universalIds.idluid = idl; + + const id5 = utils.deepAccess(bidRequest, 'userId.id5id.uid'); + if (id5) { + universalIds.id5uid = { id: id5 }; + const id5link = utils.deepAccess(bidRequest, 'userId.id5id.ext.linkType'); + if (id5link) universalIds.id5uid.linkType = id5link; } + + const lipb = utils.deepAccess(bidRequest, 'userId.lipb.lipbid'); + if (lipb) universalIds.liuid = lipb; + + return universalIds; } -function getVideoProtocols({ protocols }) { - let defaultValue = [2, 3, 5, 6, 7, 8]; - if (protocols && Array.isArray(protocols) && protocols.length > 0) { - return protocols; +function getLargestSize(sizes) { + function area(size) { + return size[0] * size[1]; + } + + return sizes.reduce((prev, current) => { + if (area(current) > area(prev)) { + return current + } else { + return prev + } + }); +} + +function generateAd(body, req) { + const strRespId = `str_response_${req.data.bidId}`; + + let adMarkup = ` +
+
+ + `; + + if (req.strData.skipIframeBusting) { + // Don't break out of iframe + adMarkup = adMarkup + ``; } else { - return defaultValue; + // Add logic to the markup that detects whether or not in top level document is accessible + // this logic will deploy sfp.js and/or iframe buster script(s) as appropriate + adMarkup = adMarkup + ` + + `; } + + return adMarkup; } -function getBidRequestFloor(bid) { - let floor = null; - if (typeof bid.getFloor === 'function') { - const floorInfo = bid.getFloor({ - currency: 'USD', - mediaType: bid.mediaTypes && bid.mediaTypes.video ? 'video' : 'banner', - size: bid.sizes.map(size => ({ w: size[0], h: size[1] })), - }); - if (typeof floorInfo === 'object' && floorInfo.currency === 'USD' && !isNaN(parseFloat(floorInfo.floor))) { - floor = parseFloat(floorInfo.floor); +function handleIframe () { + // only load iframe buster JS if we can access the top level document + // if we are 'locked in' to this frame then no point trying to bust out: we may as well render in the frame instead + var iframeBusterLoaded = false; + if (!window.lockedInFrame) { + var sfpIframeBusterJs = document.createElement('script'); + sfpIframeBusterJs.src = 'https://native.sharethrough.com/assets/sfp-set-targeting.js'; + sfpIframeBusterJs.type = 'text/javascript'; + try { + window.document.getElementsByTagName('body')[0].appendChild(sfpIframeBusterJs); + iframeBusterLoaded = true; + } catch (e) { + utils.logError('Trouble writing frame buster script, error details:', e); } } - return floor !== null ? floor : bid.params.floor; -} -function userIdAsEids(bidRequest) { - const eids = createEidsArray(deepAccess(bidRequest, 'userId')) || []; + var clientJsLoaded = (!iframeBusterLoaded) ? !!(window.STR && window.STR.Tag) : !!(window.top.STR && window.top.STR.Tag); + if (!clientJsLoaded) { + var sfpJs = document.createElement('script'); + sfpJs.src = 'https://native.sharethrough.com/assets/sfp.js'; + sfpJs.type = 'text/javascript'; - const flocData = deepAccess(bidRequest, 'userId.flocId'); - const isFlocIdValid = flocData && flocData.id && flocData.version; - if (isFlocIdValid) { - eids.push({ - source: 'chrome.com', - uids: [{ id: flocData.id, atype: 1, ext: { ver: flocData.version } }], - }); + // only add sfp js to window.top if iframe busting successfully loaded; otherwise, add to iframe + try { + if (iframeBusterLoaded) { + window.top.document.getElementsByTagName('body')[0].appendChild(sfpJs); + } else { + window.document.getElementsByTagName('body')[0].appendChild(sfpJs); + } + } catch (e) { + utils.logError('Trouble writing sfp script, error details:', e); + } } +} - return eids; +// determines if we are capable of busting out of the iframe we are in +// if we catch a DOMException when trying to access top-level document, it means we're stuck in the frame we're in +function isLockedInFrame () { + window.lockedInFrame = false; + try { + window.lockedInFrame = !window.top.document; + } catch (e) { + window.lockedInFrame = (e instanceof DOMException); + } +} + +// See https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem +function b64EncodeUnicode(str) { + return btoa( + encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, + function toSolidBytes(match, p1) { + return String.fromCharCode('0x' + p1); + })); +} + +function canAutoPlayHTML5Video() { + const userAgent = navigator.userAgent; + if (!userAgent) return false; + + const isAndroid = /Android/i.test(userAgent); + const isiOS = /iPhone|iPad|iPod/i.test(userAgent); + const chromeVersion = parseInt((/Chrome\/([0-9]+)/.exec(userAgent) || [0, 0])[1]); + const chromeiOSVersion = parseInt((/CriOS\/([0-9]+)/.exec(userAgent) || [0, 0])[1]); + const safariVersion = parseInt((/Version\/([0-9]+)/.exec(userAgent) || [0, 0])[1]); + + if ( + (isAndroid && chromeVersion >= 53) || + (isiOS && (safariVersion >= 10 || chromeiOSVersion >= 53)) || + !(isAndroid || isiOS) + ) { + return true; + } else { + return false; + } } function getProtocol() { - return window.location.protocol; + return document.location.protocol; } -// stub for ?? operator -function nullish(input, def) { - return input === null || input === undefined ? def : input; +function getFloor(bid) { + if (utils.isFn(bid.getFloor)) { + const floorInfo = bid.getFloor({ + currency: 'USD', + mediaType: 'banner', + size: bid.sizes.map(size => ({ w: size[0], h: size[1] })) + }); + if (utils.isPlainObject(floorInfo) && !isNaN(floorInfo.floor) && floorInfo.currency === 'USD') { + return parseFloat(floorInfo.floor); + } + } + return null; } registerBidder(sharethroughAdapterSpec); diff --git a/modules/sharethroughBidAdapter.md b/modules/sharethroughBidAdapter.md index 218ef353d4e..396b8164577 100644 --- a/modules/sharethroughBidAdapter.md +++ b/modules/sharethroughBidAdapter.md @@ -23,74 +23,22 @@ Module that connects to Sharethrough's demand sources // REQUIRED - The placement key pkey: 'LuB3vxGGFrBZJa6tifXW4xgK', + // OPTIONAL - Render Sharethrough creative in an iframe, defaults to false + iframe: true, + + // OPTIONAL - If iframeSize is provided, we'll use this size for the iframe + // otherwise we'll grab the largest size from the sizes array + // This is ignored if iframe: false + iframeSize: [250, 250], + // OPTIONAL - Blocked Advertiser Domains badv: ['domain1.com', 'domain2.com'], // OPTIONAL - Blocked Categories (IAB codes) bcat: ['IAB1-1', 'IAB1-2'], - - // OPTIONAL - default bid floor, if not specified in bid request (USD) - floor: 0.1, } } ] } ]; ``` - -# Sample Instream Video Ad Unit: For Publishers -``` -var adVideoAdUnits = [ -{ - code: 'test-div-video', - mediaTypes: { - video: { - // CANNOT be 'outstream' - context: 'instream', - placement: 1, - delivery: 1, - companiontype: 'companion type', - companionad: 'companion ad', - // default values shown below this point - pos: 0, - skip: 0, - linearity: 1, - minduration: 5, - maxduration: 60, - playbackmethod: [2], - api: [2], - mimes: ['video/mp4'], - protocols: [2, 3, 5, 6, 7, 8], - playerSize: [640, 360], - startdelay: 0, - skipmin: 0, - skipafter: 0, - }, - }, - bids: [{ - bidder: 'sharethrough', - params: { - pkey: 'pkey1' - } - }] -}] -``` - -# Sample Banner Ad Unit: For Publishers -``` -var adUnits = [ -{ - code: 'test-div-video', - mediaTypes: { - banner: { - pos: 0, // default - }, - }, - bids: [{ - bidder: 'sharethrough', - params: { - pkey: 'pkey1' - } - }] -}] -``` diff --git a/modules/showheroes-bsBidAdapter.js b/modules/showheroes-bsBidAdapter.js index 4c8fb812edc..8d94a8e508b 100644 --- a/modules/showheroes-bsBidAdapter.js +++ b/modules/showheroes-bsBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, getBidIdParameter, getWindowTop, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { Renderer } from '../src/Renderer.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; @@ -32,18 +32,18 @@ export const spec = { let adUnits = []; const pageURL = validBidRequests[0].params.contentPageUrl || bidderRequest.refererInfo.referer; const isStage = !!validBidRequests[0].params.stage; - const isOutstream = deepAccess(validBidRequests[0], 'mediaTypes.video.context') === 'outstream'; - const isCustomRender = deepAccess(validBidRequests[0], 'params.outstreamOptions.customRender'); - const isNodeRender = deepAccess(validBidRequests[0], 'params.outstreamOptions.slot') || deepAccess(validBidRequests[0], 'params.outstreamOptions.iframe'); - const isNativeRender = deepAccess(validBidRequests[0], 'renderer'); - const outstreamOptions = deepAccess(validBidRequests[0], 'params.outstreamOptions'); + const isOutstream = utils.deepAccess(validBidRequests[0], 'mediaTypes.video.context') === 'outstream'; + const isCustomRender = utils.deepAccess(validBidRequests[0], 'params.outstreamOptions.customRender'); + const isNodeRender = utils.deepAccess(validBidRequests[0], 'params.outstreamOptions.slot') || utils.deepAccess(validBidRequests[0], 'params.outstreamOptions.iframe'); + const isNativeRender = utils.deepAccess(validBidRequests[0], 'renderer'); + const outstreamOptions = utils.deepAccess(validBidRequests[0], 'params.outstreamOptions'); const isBanner = !!validBidRequests[0].mediaTypes.banner || (isOutstream && !(isCustomRender || isNativeRender || isNodeRender)); const defaultSchain = validBidRequests[0].schain || {}; validBidRequests.forEach((bid) => { const videoSizes = getVideoSizes(bid); const bannerSizes = getBannerSizes(bid); - const vpaidMode = getBidIdParameter('vpaidMode', bid.params); + const vpaidMode = utils.getBidIdParameter('vpaidMode', bid.params); const makeBids = (type, size) => { let context = ''; @@ -52,7 +52,7 @@ export const spec = { if (type === BANNER) { streamType = 5; } else { - context = deepAccess(bid, 'mediaTypes.video.context'); + context = utils.deepAccess(bid, 'mediaTypes.video.context'); if (vpaidMode && context === 'instream') { streamType = 1; } @@ -61,24 +61,15 @@ export const spec = { } } - const consentData = bidderRequest.gdprConsent || {}; - - const gdprConsent = { - apiVersion: consentData.apiVersion || 2, - gdprApplies: consentData.gdprApplies || 0, - consentString: consentData.consentString || '', - } - return { type: streamType, - adUnitCode: bid.adUnitCode, bidId: bid.bidId, mediaType: type, context: context, - playerId: getBidIdParameter('playerId', bid.params), + playerId: utils.getBidIdParameter('playerId', bid.params), auctionId: bidderRequest.auctionId, bidderCode: BIDDER_CODE, - gdprConsent: gdprConsent, + gdprConsent: bidderRequest.gdprConsent, start: +new Date(), timeout: 3000, size: { @@ -109,7 +100,7 @@ export const spec = { 'adapterVersion': 2, 'pageURL': encodeURIComponent(pageURL), 'vastCacheEnabled': (!!config.getConfig('cache') && !isBanner && !outstreamOptions) || false, - 'isDesktop': getWindowTop().document.documentElement.clientWidth > 700, + 'isDesktop': utils.getWindowTop().document.documentElement.clientWidth > 700, 'xmlAndTag': !!(isOutstream && isCustomRender) || false, 'stage': isStage || undefined }, @@ -168,7 +159,6 @@ function createBids(bidRes, reqData) { let bidUnit = {}; bidUnit.cpm = bid.cpm; bidUnit.requestId = bid.bidId; - bidUnit.adUnitCode = reqBid.adUnitCode; bidUnit.currency = bid.currency; bidUnit.mediaType = bid.mediaType || VIDEO; bidUnit.ttl = TTL; @@ -193,8 +183,7 @@ function createBids(bidRes, reqData) { } else if (bid.context === 'outstream') { const renderer = Renderer.install({ id: bid.bidId, - url: 'https://static.showheroes.com/renderer.js', - adUnitCode: reqBid.adUnitCode, + url: '//', config: { playerId: reqBid.playerId, width: bid.size.width, @@ -203,9 +192,9 @@ function createBids(bidRes, reqData) { vastXml: bid.vastXml, debug: reqData.debug, isStage: !!reqData.meta.stage, - customRender: getBidIdParameter('customRender', currentBidParams.outstreamOptions), - slot: getBidIdParameter('slot', currentBidParams.outstreamOptions), - iframe: getBidIdParameter('iframe', currentBidParams.outstreamOptions), + customRender: utils.getBidIdParameter('customRender', currentBidParams.outstreamOptions), + slot: utils.getBidIdParameter('slot', currentBidParams.outstreamOptions), + iframe: utils.getBidIdParameter('iframe', currentBidParams.outstreamOptions), } }); renderer.setRender(outstreamRender); @@ -223,7 +212,7 @@ function outstreamRender(bid) { bid.renderer.config.customRender(bid, embedCode); } else { try { - const inIframe = getBidIdParameter('iframe', bid.renderer.config); + const inIframe = utils.getBidIdParameter('iframe', bid.renderer.config); if (inIframe && window.document.getElementById(inIframe).nodeName === 'IFRAME') { const iframe = window.document.getElementById(inIframe); let framedoc = iframe.contentDocument || (iframe.contentWindow && iframe.contentWindow.document); @@ -231,20 +220,20 @@ function outstreamRender(bid) { return; } - const slot = getBidIdParameter('slot', bid.renderer.config) || bid.adUnitCode; + const slot = utils.getBidIdParameter('slot', bid.renderer.config) || bid.adUnitCode; if (slot && window.document.getElementById(slot)) { window.document.getElementById(slot).appendChild(embedCode); } else if (slot) { - logError('[ShowHeroes][renderer] Error: spot not found'); + utils.logError('[ShowHeroes][renderer] Error: spot not found'); } } catch (err) { - logError('[ShowHeroes][renderer] Error:' + err.message) + utils.logError('[ShowHeroes][renderer] Error:' + err.message) } } } function createOutstreamEmbedCode(bid) { - const isStage = getBidIdParameter('isStage', bid.renderer.config); + const isStage = utils.getBidIdParameter('isStage', bid.renderer.config); const urls = getEnvURLs(isStage); const fragment = window.document.createDocumentFragment(); @@ -256,9 +245,9 @@ function createOutstreamEmbedCode(bid) { const spot = window.document.createElement('div'); spot.setAttribute('class', 'showheroes-spot'); - spot.setAttribute('data-player', getBidIdParameter('playerId', bid.renderer.config)); - spot.setAttribute('data-debug', getBidIdParameter('debug', bid.renderer.config)); - spot.setAttribute('data-ad-vast-tag', getBidIdParameter('vastUrl', bid.renderer.config)); + spot.setAttribute('data-player', utils.getBidIdParameter('playerId', bid.renderer.config)); + spot.setAttribute('data-debug', utils.getBidIdParameter('debug', bid.renderer.config)); + spot.setAttribute('data-ad-vast-tag', utils.getBidIdParameter('vastUrl', bid.renderer.config)); spot.setAttribute('data-stream-type', 'outstream'); fragment.appendChild(spot); @@ -286,11 +275,11 @@ function getBannerHtml (bid, reqBid, reqData) { } function getVideoSizes(bidRequest) { - return formatSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize') || []); + return formatSizes(utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize') || []); } function getBannerSizes(bidRequest) { - return formatSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes') || []); + return formatSizes(utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes') || []); } function formatSizes(sizes) { diff --git a/modules/sigmoidAnalyticsAdapter.js b/modules/sigmoidAnalyticsAdapter.js index a0521bd5297..303fbbc8995 100644 --- a/modules/sigmoidAnalyticsAdapter.js +++ b/modules/sigmoidAnalyticsAdapter.js @@ -1,14 +1,15 @@ /* Sigmoid Analytics Adapter for prebid.js v1.1.0-pre Updated : 2018-03-28 */ -import {includes} from '../src/polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js'; import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {generateUUID, logError, logInfo} from '../src/utils.js'; +import { getStorageManager } from '../src/storageManager.js'; const storage = getStorageManager(); +const utils = require('../src/utils.js'); + const url = 'https://kinesis.us-east-1.amazonaws.com/'; const analyticsType = 'endpoint'; @@ -55,7 +56,7 @@ function buildSessionIdTimeoutLocalStorageKey() { function updateSessionId() { if (isSessionIdTimeoutExpired()) { - let newSessionId = generateUUID(); + let newSessionId = utils.generateUUID(); storage.setDataInLocalStorage(buildSessionIdLocalStorageKey(), newSessionId); } initOptions.sessionId = getSessionId(); @@ -205,7 +206,7 @@ sigmoidAdapter.originEnableAnalytics = sigmoidAdapter.enableAnalytics; sigmoidAdapter.enableAnalytics = function (config) { initOptions = config.options; initOptions.utmTagData = this.buildUtmTagData(); - logInfo('Sigmoid Analytics enabled with config', initOptions); + utils.logInfo('Sigmoid Analytics enabled with config', initOptions); sigmoidAdapter.originEnableAnalytics(config); }; @@ -245,7 +246,7 @@ function send(eventType, data, sendDataType) { AWS.config.credentials.get(function(err) { // attach event listener if (err) { - logError(err); + utils.logError(err); return; } // create kinesis service object diff --git a/modules/sirdataRtdProvider.js b/modules/sirdataRtdProvider.js index 182ff384fef..373468b2f14 100644 --- a/modules/sirdataRtdProvider.js +++ b/modules/sirdataRtdProvider.js @@ -7,12 +7,12 @@ * @requires module:modules/realTimeData */ import {getGlobal} from '../src/prebidGlobal.js'; -import {deepAccess, deepEqual, deepSetValue, isEmpty, logError, mergeDeep} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {submodule} from '../src/hook.js'; import {ajax} from '../src/ajax.js'; -import {findIndex} from '../src/polyfill.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import {config} from '../src/config.js'; +import findIndex from 'core-js-pure/features/array/find-index.js'; +import { getRefererInfo } from '../src/refererDetection.js'; +import { config } from '../src/config.js'; /** @type {string} */ const MODULE_NAME = 'realTimeData'; @@ -44,7 +44,7 @@ export function getSegmentsAndCategories(reqBidsConfigObj, onDone, moduleConfig, } // default global endpoint is cookie-based if no rules falls into cookieless or consent has been given or GDPR doesn't apply - if (!sirdataDomain || !gdprApplies || (deepAccess(userConsent, 'gdpr.vendorData.vendor.consents') && userConsent.gdpr.vendorData.vendor.consents[53] && userConsent.gdpr.vendorData.purpose.consents[1] && userConsent.gdpr.vendorData.purpose.consents[4])) { + if (!sirdataDomain || !gdprApplies || (utils.deepAccess(userConsent, 'gdpr.vendorData.vendor.consents') && userConsent.gdpr.vendorData.vendor.consents[53] && userConsent.gdpr.vendorData.purpose.consents[1] && userConsent.gdpr.vendorData.purpose.consents[4])) { sirdataDomain = 'sddan.com'; sendWithCredentials = true; } @@ -64,7 +64,7 @@ export function getSegmentsAndCategories(reqBidsConfigObj, onDone, moduleConfig, } } catch (e) { onDone(); - logError('unable to parse Sirdata data' + e); + utils.logError('unable to parse Sirdata data' + e); } } else if (req.status === 204) { onDone(); @@ -72,7 +72,7 @@ export function getSegmentsAndCategories(reqBidsConfigObj, onDone, moduleConfig, }, error: function () { onDone(); - logError('unable to get Sirdata data'); + utils.logError('unable to get Sirdata data'); } }, null, @@ -89,18 +89,18 @@ export function setGlobalOrtb2(segments, categories) { try { let addOrtb2 = {}; let testGlobal = getGlobal().getConfig('ortb2') || {}; - if (!deepAccess(testGlobal, 'user.ext.data.sd_rtd') || !deepEqual(testGlobal.user.ext.data.sd_rtd, segments)) { - deepSetValue(addOrtb2, 'user.ext.data.sd_rtd', segments || {}); + if (!utils.deepAccess(testGlobal, 'user.ext.data.sd_rtd') || !utils.deepEqual(testGlobal.user.ext.data.sd_rtd, segments)) { + utils.deepSetValue(addOrtb2, 'user.ext.data.sd_rtd', segments || {}); } - if (!deepAccess(testGlobal, 'site.ext.data.sd_rtd') || !deepEqual(testGlobal.site.ext.data.sd_rtd, categories)) { - deepSetValue(addOrtb2, 'site.ext.data.sd_rtd', categories || {}); + if (!utils.deepAccess(testGlobal, 'site.ext.data.sd_rtd') || !utils.deepEqual(testGlobal.site.ext.data.sd_rtd, categories)) { + utils.deepSetValue(addOrtb2, 'site.ext.data.sd_rtd', categories || {}); } - if (!isEmpty(addOrtb2)) { - let ortb2 = {ortb2: mergeDeep({}, testGlobal, addOrtb2)}; + if (!utils.isEmpty(addOrtb2)) { + let ortb2 = {ortb2: utils.mergeDeep({}, testGlobal, addOrtb2)}; getGlobal().setConfig(ortb2); } } catch (e) { - logError(e) + utils.logError(e) } return true; @@ -109,19 +109,19 @@ export function setGlobalOrtb2(segments, categories) { export function setBidderOrtb2(bidder, segments, categories) { try { let addOrtb2 = {}; - let testBidder = deepAccess(config.getBidderConfig(), bidder + '.ortb2') || {}; - if (!deepAccess(testBidder, 'user.ext.data.sd_rtd') || !deepEqual(testBidder.user.ext.data.sd_rtd, segments)) { - deepSetValue(addOrtb2, 'user.ext.data.sd_rtd', segments || {}); + let testBidder = utils.deepAccess(config.getBidderConfig(), bidder + '.ortb2') || {}; + if (!utils.deepAccess(testBidder, 'user.ext.data.sd_rtd') || !utils.deepEqual(testBidder.user.ext.data.sd_rtd, segments)) { + utils.deepSetValue(addOrtb2, 'user.ext.data.sd_rtd', segments || {}); } - if (!deepAccess(testBidder, 'site.ext.data.sd_rtd') || !deepEqual(testBidder.site.ext.data.sd_rtd, categories)) { - deepSetValue(addOrtb2, 'site.ext.data.sd_rtd', categories || {}); + if (!utils.deepAccess(testBidder, 'site.ext.data.sd_rtd') || !utils.deepEqual(testBidder.site.ext.data.sd_rtd, categories)) { + utils.deepSetValue(addOrtb2, 'site.ext.data.sd_rtd', categories || {}); } - if (!isEmpty(addOrtb2)) { - let ortb2 = {ortb2: mergeDeep({}, testBidder, addOrtb2)}; + if (!utils.isEmpty(addOrtb2)) { + let ortb2 = {ortb2: utils.mergeDeep({}, testBidder, addOrtb2)}; getGlobal().setBidderConfig({ bidders: [bidder], config: ortb2 }); } } catch (e) { - logError(e) + utils.logError(e) } return true; @@ -132,7 +132,7 @@ export function loadCustomFunction (todo, adUnit, list, data, bid) { if (typeof todo == 'function') { todo(adUnit, list, data, bid); } - } catch (e) { logError(e); } + } catch (e) { utils.logError(e); } return true; } @@ -148,14 +148,14 @@ export function getSegAndCatsArray(data, minScore) { } } } - } catch (e) { logError(e); } + } catch (e) { utils.logError(e); } try { if (data && data.segments) { for (let segId in data.segments) { sirdataData.segments.push(data.segments[segId].toString()); } } - } catch (e) { logError(e); } + } catch (e) { utils.logError(e); } return sirdataData; } @@ -165,7 +165,7 @@ export function addSegmentData(adUnits, data, moduleConfig, onDone) { const globalMinScore = moduleConfig.params.hasOwnProperty('contextualMinRelevancyScore') ? moduleConfig.params.contextualMinRelevancyScore : 30; var sirdataData = getSegAndCatsArray(data, globalMinScore); - if (!sirdataData || (sirdataData.segments.length < 1 && sirdataData.categories.length < 1)) { logError('no cats'); onDone(); return adUnits; } + if (!sirdataData || (sirdataData.segments.length < 1 && sirdataData.categories.length < 1)) { utils.logError('no cats'); onDone(); return adUnits; } const sirdataList = sirdataData.segments.concat(sirdataData.categories); @@ -191,7 +191,7 @@ export function addSegmentData(adUnits, data, moduleConfig, onDone) { n.setTargeting('sd_rtd', sirdataList.concat(curationData.segments).concat(curationData.categories)); } }) - } catch (e) { logError(e); } + } catch (e) { utils.logError(e); } } // Bid targeting level for FPD non-generic biders @@ -199,8 +199,8 @@ export function addSegmentData(adUnits, data, moduleConfig, onDone) { var indexFound = false; adUnits.forEach(adUnit => { - if (!biddersParamsExist && !deepAccess(adUnit, 'ortb2Imp.ext.data.sd_rtd')) { - deepSetValue(adUnit, 'ortb2Imp.ext.data.sd_rtd', sirdataList); + if (!biddersParamsExist && !utils.deepAccess(adUnit, 'ortb2Imp.ext.data.sd_rtd')) { + utils.deepSetValue(adUnit, 'ortb2Imp.ext.data.sd_rtd', sirdataList); } adUnit.hasOwnProperty('bids') && adUnit.bids.forEach(bid => { @@ -236,7 +236,7 @@ export function addSegmentData(adUnits, data, moduleConfig, onDone) { if (indexFound && moduleConfig.params.bidders[bidderIndex].hasOwnProperty('customFunction')) { loadCustomFunction(moduleConfig.params.bidders[bidderIndex].customFunction, adUnit, sirdataList.concat(curationData.segments).concat(curationData.categories), data, bid); } else { - deepSetValue(bid, 'params.keywords.sd_rtd', sirdataList.concat(curationData.segments).concat(curationData.categories)); + utils.deepSetValue(bid, 'params.keywords.sd_rtd', sirdataList.concat(curationData.segments).concat(curationData.categories)); } break; @@ -259,7 +259,7 @@ export function addSegmentData(adUnits, data, moduleConfig, onDone) { target.push('sd_rtd=' + entry); } }); - deepSetValue(bid, 'params.target', target.join(';')); + utils.deepSetValue(bid, 'params.target', target.join(';')); } break; @@ -313,7 +313,7 @@ export function addSegmentData(adUnits, data, moduleConfig, onDone) { if (indexFound && moduleConfig.params.bidders[bidderIndex].hasOwnProperty('customFunction')) { loadCustomFunction(moduleConfig.params.bidders[bidderIndex].customFunction, adUnit, sirdataList.concat(curationData.segments).concat(curationData.categories), data, bid); } else { - deepSetValue(bid, 'ortb2.user.ext.data', {segments: sirdataData.segments.concat(curationData.segments), contextual_categories: {...data.contextual_categories, ...data.shared_taxonomy[curationId].contextual_categories}}); + utils.deepSetValue(bid, 'ortb2.user.ext.data', {segments: sirdataData.segments.concat(curationData.segments), contextual_categories: {...data.contextual_categories, ...data.shared_taxonomy[curationId].contextual_categories}}); } break; @@ -372,16 +372,16 @@ export function addSegmentData(adUnits, data, moduleConfig, onDone) { default: if (!biddersParamsExist || indexFound) { - if (!deepAccess(bid, 'ortb2.site.ext.data.sd_rtd')) { - deepSetValue(bid, 'ortb2.site.ext.data.sd_rtd', sirdataData.categories); + if (!utils.deepAccess(bid, 'ortb2.site.ext.data.sd_rtd')) { + utils.deepSetValue(bid, 'ortb2.site.ext.data.sd_rtd', sirdataData.categories); } - if (!deepAccess(bid, 'ortb2.user.ext.data.sd_rtd')) { - deepSetValue(bid, 'ortb2.user.ext.data.sd_rtd', sirdataData.segments); + if (!utils.deepAccess(bid, 'ortb2.user.ext.data.sd_rtd')) { + utils.deepSetValue(bid, 'ortb2.user.ext.data.sd_rtd', sirdataData.segments); } } } } - } catch (e) { logError(e) } + } catch (e) { utils.logError(e) } }) }); diff --git a/modules/sizeMappingV2.js b/modules/sizeMappingV2.js index 405799813eb..ffd242e57ac 100644 --- a/modules/sizeMappingV2.js +++ b/modules/sizeMappingV2.js @@ -4,19 +4,12 @@ * rendering. Read full API documentation on Prebid.org, http://prebid.org/dev-docs/modules/sizeMappingV2.html */ -import { - deepClone, - getWindowTop, - isArray, - isArrayOfNums, - isValidMediaTypes, - logError, - logInfo, - logWarn -} from '../src/utils.js'; -import {includes} from '../src/polyfill.js'; -import {getHook} from '../src/hook.js'; -import {adUnitSetupChecks} from '../src/prebid.js'; +import * as utils from '../src/utils.js'; +import { processNativeAdUnitParams } from '../src/native.js'; +import { adunitCounter } from '../src/adUnits.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import { getHook } from '../src/hook.js'; +import { adUnitSetupChecks } from '../src/prebid.js'; // Allows for stubbing of these functions while writing unit tests. export const internal = { @@ -28,33 +21,61 @@ export const internal = { isLabelActivated }; -const V2_ADUNITS = new WeakMap(); +/* + 'sizeMappingInternalStore' contains information on, whether a particular auction is using size mapping V2 (the new size mapping spec), + and it also contains additional information on each adUnit, such as, mediaTypes, activeViewport, etc. This information is required by + the 'getBids' function. +*/ + +export const sizeMappingInternalStore = createSizeMappingInternalStore(); + +function createSizeMappingInternalStore() { + const sizeMappingInternalStore = {}; + + return { + initializeStore: function (auctionId, isUsingSizeMappingBool) { + sizeMappingInternalStore[auctionId] = { + usingSizeMappingV2: isUsingSizeMappingBool, + adUnits: [] + }; + }, + getAuctionDetail: function (auctionId) { + return sizeMappingInternalStore[auctionId]; + }, + setAuctionDetail: function (auctionId, adUnitDetail) { + sizeMappingInternalStore[auctionId].adUnits.push(adUnitDetail); + } + } +} /* Returns "true" if at least one of the adUnits in the adUnits array is using an Ad Unit and/or Bidder level sizeConfig, otherwise, returns "false." */ export function isUsingNewSizeMapping(adUnits) { - return !!adUnits.find(adUnit => { - if (V2_ADUNITS.has(adUnit)) return V2_ADUNITS.get(adUnit); + let isUsingSizeMappingBool = false; + adUnits.forEach(adUnit => { if (adUnit.mediaTypes) { // checks for the presence of sizeConfig property at the adUnit.mediaTypes object - for (let mediaType of Object.keys(adUnit.mediaTypes)) { + Object.keys(adUnit.mediaTypes).forEach(mediaType => { if (adUnit.mediaTypes[mediaType].sizeConfig) { - V2_ADUNITS.set(adUnit, true); - return true; + if (isUsingSizeMappingBool === false) { + isUsingSizeMappingBool = true; + } } - } - for (let bid of adUnit.bids && isArray(adUnit.bids) ? adUnit.bids : []) { - if (bid.sizeConfig) { - V2_ADUNITS.set(adUnit, true); - return true; + }); + + // checks for the presence of sizeConfig property at the adUnit.bids[].bidder object + adUnit.bids && utils.isArray(adUnit.bids) && adUnit.bids.forEach(bidder => { + if (bidder.sizeConfig) { + if (isUsingSizeMappingBool === false) { + isUsingSizeMappingBool = true; + } } - } - V2_ADUNITS.set(adUnit, false); - return false; + }); } }); + return isUsingSizeMappingBool; } /** @@ -87,7 +108,7 @@ export function checkAdUnitSetupHook(adUnits) { If they do not, return 'false'. */ if (!(includes(keys, 'minViewPort') && includes(keys, propertyName))) { - logError(`Ad unit ${adUnitCode}: Missing required property 'minViewPort' or 'sizes' from 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`); + utils.logError(`Ad unit ${adUnitCode}: Missing required property 'minViewPort' or 'sizes' from 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`); isValid = false; return; } @@ -96,8 +117,8 @@ export function checkAdUnitSetupHook(adUnits) { Verify that 'config.minViewPort' property is in [width, height] format. If not, return false. */ - if (!isArrayOfNums(config.minViewPort, 2)) { - logError(`Ad unit ${adUnitCode}: Invalid declaration of 'minViewPort' in 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`); + if (!utils.isArrayOfNums(config.minViewPort, 2)) { + utils.logError(`Ad unit ${adUnitCode}: Invalid declaration of 'minViewPort' in 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`); isValid = false return; } @@ -120,7 +141,7 @@ export function checkAdUnitSetupHook(adUnits) { showError = true; } if (showError) { - logError(`Ad unit ${adUnitCode}: Invalid declaration of '${propertyName}' in 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`); + utils.logError(`Ad unit ${adUnitCode}: Invalid declaration of '${propertyName}' in 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`); return; } } @@ -131,13 +152,13 @@ export function checkAdUnitSetupHook(adUnits) { */ if (mediaType === 'native') { if (typeof config[propertyName] !== 'boolean') { - logError(`Ad unit ${adUnitCode}: Invalid declaration of 'active' in 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`); + utils.logError(`Ad unit ${adUnitCode}: Invalid declaration of 'active' in 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`); isValid = false; } } }); } else { - logError(`Ad unit ${adUnitCode}: Invalid declaration of 'sizeConfig' in 'mediaTypes.${mediaType}.sizeConfig'. ${conditionalLogMessages[mediaType]}`); + utils.logError(`Ad unit ${adUnitCode}: Invalid declaration of 'sizeConfig' in 'mediaTypes.${mediaType}.sizeConfig'. ${conditionalLogMessages[mediaType]}`); isValid = false; return isValid; } @@ -147,19 +168,26 @@ export function checkAdUnitSetupHook(adUnits) { } const validatedAdUnits = []; adUnits.forEach(adUnit => { - adUnit = adUnitSetupChecks.validateAdUnit(adUnit); - if (adUnit == null) return; - + const bids = adUnit.bids; const mediaTypes = adUnit.mediaTypes; let validatedBanner, validatedVideo, validatedNative; + if (!bids || !utils.isArray(bids)) { + utils.logError(`Detected adUnit.code '${adUnit.code}' did not have 'adUnit.bids' defined or 'adUnit.bids' is not an array. Removing adUnit from auction.`); + return; + } + + if (!mediaTypes || Object.keys(mediaTypes).length === 0) { + utils.logError(`Detected adUnit.code '${adUnit.code}' did not have a 'mediaTypes' object defined. This is a required field for the auction, so this adUnit has been removed.`); + return; + } if (mediaTypes.banner) { if (mediaTypes.banner.sizes) { // Ad unit is using 'mediaTypes.banner.sizes' instead of the new property 'sizeConfig'. Apply the old checks! validatedBanner = adUnitSetupChecks.validateBannerMediaType(adUnit); } else if (mediaTypes.banner.sizeConfig) { // Ad unit is using the 'sizeConfig' property, 'mediaTypes.banner.sizeConfig'. Apply the new checks! - validatedBanner = deepClone(adUnit); + validatedBanner = utils.deepClone(adUnit); const isBannerValid = validateSizeConfig('banner', mediaTypes.banner.sizeConfig, adUnit.code); if (!isBannerValid) { delete validatedBanner.mediaTypes.banner; @@ -176,8 +204,8 @@ export function checkAdUnitSetupHook(adUnits) { } } else { // Ad unit is invalid since it's mediaType property does not have either 'sizes' or 'sizeConfig' declared. - logError(`Ad unit ${adUnit.code}: 'mediaTypes.banner' does not contain either 'sizes' or 'sizeConfig' property. Removing 'mediaTypes.banner' from ad unit.`); - validatedBanner = deepClone(adUnit); + utils.logError(`Ad unit ${adUnit.code}: 'mediaTypes.banner' does not contain either 'sizes' or 'sizeConfig' property. Removing 'mediaTypes.banner' from ad unit.`); + validatedBanner = utils.deepClone(adUnit); delete validatedBanner.mediaTypes.banner; } } @@ -188,7 +216,7 @@ export function checkAdUnitSetupHook(adUnits) { validatedVideo = validatedBanner ? adUnitSetupChecks.validateVideoMediaType(validatedBanner) : adUnitSetupChecks.validateVideoMediaType(adUnit); } else if (mediaTypes.video.sizeConfig) { // Ad unit is using the 'sizeConfig' property, 'mediaTypes.video.sizeConfig'. Apply the new checks! - validatedVideo = validatedBanner || deepClone(adUnit); + validatedVideo = validatedBanner || utils.deepClone(adUnit); const isVideoValid = validateSizeConfig('video', mediaTypes.video.sizeConfig, adUnit.code); if (!isVideoValid) { delete validatedVideo.mediaTypes.video.sizeConfig; @@ -246,7 +274,7 @@ export function checkBidderSizeConfigFormat(sizeConfig) { const keys = Object.keys(config); if ((includes(keys, 'minViewPort') && includes(keys, 'relevantMediaTypes')) && - isArrayOfNums(config.minViewPort, 2) && + utils.isArrayOfNums(config.minViewPort, 2) && Array.isArray(config.relevantMediaTypes) && config.relevantMediaTypes.length > 0 && (config.relevantMediaTypes.length > 1 ? (config.relevantMediaTypes.every(mt => (includes(['banner', 'video', 'native'], mt)))) @@ -262,11 +290,23 @@ export function checkBidderSizeConfigFormat(sizeConfig) { return didCheckPass; } -getHook('setupAdUnitMediaTypes').before(function (fn, adUnits, labels) { - if (isUsingNewSizeMapping(adUnits)) { - return fn.bail(setupAdUnitMediaTypes(adUnits, labels)); +getHook('getBids').before(function (fn, bidderInfo) { + // check if the adUnit is using sizeMappingV2 specs and store the result in _sizeMappingUsageMap. + if (typeof sizeMappingInternalStore.getAuctionDetail(bidderInfo.auctionId) === 'undefined') { + const isUsingSizeMappingBool = isUsingNewSizeMapping(bidderInfo.adUnits); + + // initialize sizeMappingInternalStore for the first time for a particular auction + sizeMappingInternalStore.initializeStore(bidderInfo.auctionId, isUsingSizeMappingBool); + } + if (sizeMappingInternalStore.getAuctionDetail(bidderInfo.auctionId).usingSizeMappingV2) { + // if adUnit is found using sizeMappingV2 specs, run the getBids function which processes the sizeConfig object + // and returns the bids array for a particular bidder. + + const bids = getBids(bidderInfo); + return fn.bail(bids); } else { - return fn.call(this, adUnits, labels); + // if not using sizeMappingV2, default back to the getBids function defined in adapterManager. + return fn.call(this, bidderInfo); } }); @@ -282,14 +322,14 @@ export function isLabelActivated(bidOrAdUnit, activeLabels, adUnitCode, adUnitIn let labelOperator; const labelsFound = Object.keys(bidOrAdUnit).filter(prop => prop === 'labelAny' || prop === 'labelAll'); if (labelsFound && labelsFound.length > 1) { - logWarn(`Size Mapping V2:: ${(bidOrAdUnit.code) + utils.logWarn(`Size Mapping V2:: ${(bidOrAdUnit.code) ? (`Ad Unit: ${bidOrAdUnit.code}(${adUnitInstance}) => Ad unit has multiple label operators. Using the first declared operator: ${labelsFound[0]}`) : (`Ad Unit: ${adUnitCode}(${adUnitInstance}), Bidder: ${bidOrAdUnit.bidder} => Bidder has multiple label operators. Using the first declared operator: ${labelsFound[0]}`)}`); } labelOperator = labelsFound[0]; if (labelOperator && !activeLabels) { - logWarn(`Size Mapping V2:: ${(bidOrAdUnit.code) + utils.logWarn(`Size Mapping V2:: ${(bidOrAdUnit.code) ? (`Ad Unit: ${bidOrAdUnit.code}(${adUnitInstance}) => Found '${labelOperator}' on ad unit, but 'labels' is not set. Did you pass 'labels' to pbjs.requestBids() ?`) : (`Ad Unit: ${adUnitCode}(${adUnitInstance}), Bidder: ${bidOrAdUnit.bidder} => Found '${labelOperator}' on bidder, but 'labels' is not set. Did you pass 'labels' to pbjs.requestBids() ?`)}`); return true; @@ -297,13 +337,13 @@ export function isLabelActivated(bidOrAdUnit, activeLabels, adUnitCode, adUnitIn if (labelOperator === 'labelAll' && Array.isArray(bidOrAdUnit[labelOperator])) { if (bidOrAdUnit.labelAll.length === 0) { - logWarn(`Size Mapping V2:: Ad Unit: ${bidOrAdUnit.code}(${adUnitInstance}) => Ad unit has declared property 'labelAll' with an empty array.`); + utils.logWarn(`Size Mapping V2:: Ad Unit: ${bidOrAdUnit.code}(${adUnitInstance}) => Ad unit has declared property 'labelAll' with an empty array.`); return true; } return bidOrAdUnit.labelAll.every(label => includes(activeLabels, label)); } else if (labelOperator === 'labelAny' && Array.isArray(bidOrAdUnit[labelOperator])) { if (bidOrAdUnit.labelAny.length === 0) { - logWarn(`Size Mapping V2:: Ad Unit: ${bidOrAdUnit.code}(${adUnitInstance}) => Ad unit has declared property 'labelAny' with an empty array.`); + utils.logWarn(`Size Mapping V2:: Ad Unit: ${bidOrAdUnit.code}(${adUnitInstance}) => Ad unit has declared property 'labelAny' with an empty array.`); return true; } return bidOrAdUnit.labelAny.some(label => includes(activeLabels, label)); @@ -323,7 +363,7 @@ export function getFilteredMediaTypes(mediaTypes) { activeViewportHeight, transformedMediaTypes; - transformedMediaTypes = deepClone(mediaTypes); + transformedMediaTypes = utils.deepClone(mediaTypes); let activeSizeBucket = { banner: undefined, @@ -332,10 +372,10 @@ export function getFilteredMediaTypes(mediaTypes) { } try { - activeViewportWidth = getWindowTop().innerWidth; - activeViewportHeight = getWindowTop().innerHeight; + activeViewportWidth = utils.getWindowTop().innerWidth; + activeViewportHeight = utils.getWindowTop().innerHeight; } catch (e) { - logWarn(`SizeMappingv2:: Unfriendly iframe blocks viewport size to be evaluated correctly`); + utils.logWarn(`SizeMappingv2:: Unfriendly iframe blocks viewport size to be evaluated correctly`); activeViewportWidth = window.innerWidth; activeViewportHeight = window.innerHeight; } @@ -384,8 +424,8 @@ export function getFilteredMediaTypes(mediaTypes) { return sizeBucketToSizeMap; }, {}); - return { sizeBucketToSizeMap, activeViewport, transformedMediaTypes }; -} + return { mediaTypes, sizeBucketToSizeMap, activeViewport, transformedMediaTypes }; +}; /** * Evaluates the given sizeConfig object and checks for various properties to determine if the sizeConfig is active or not. For example, @@ -436,87 +476,126 @@ export function getActiveSizeBucket(sizeConfig, activeViewport) { } export function getRelevantMediaTypesForBidder(sizeConfig, activeViewport) { - const mediaTypes = new Set(); if (internal.checkBidderSizeConfigFormat(sizeConfig)) { const activeSizeBucket = internal.getActiveSizeBucket(sizeConfig, activeViewport); - sizeConfig.filter(config => config.minViewPort === activeSizeBucket)[0]['relevantMediaTypes'].forEach((mt) => mediaTypes.add(mt)); + return sizeConfig.filter(config => config.minViewPort === activeSizeBucket)[0]['relevantMediaTypes']; } - return mediaTypes; + return []; } -export function getAdUnitDetail(adUnit, labels, adUnitInstance) { - const isLabelActivated = internal.isLabelActivated(adUnit, labels, adUnit.code, adUnitInstance); - const { sizeBucketToSizeMap, activeViewport, transformedMediaTypes } = isLabelActivated && internal.getFilteredMediaTypes(adUnit.mediaTypes); - isLabelActivated && logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${adUnitInstance}) => Active size buckets after filtration: `, sizeBucketToSizeMap); - return { - activeViewport, - transformedMediaTypes, - isLabelActivated, - }; +// sets sizeMappingInternalStore for a given auctionId with relevant adUnit information returned from the call to 'getFilteredMediaTypes' function +// returns adUnit details object. +export function getAdUnitDetail(auctionId, adUnit, labels) { + // fetch all adUnits for an auction from the sizeMappingInternalStore + const adUnitsForAuction = sizeMappingInternalStore.getAuctionDetail(auctionId).adUnits; + + // check if the adUnit exists already in the sizeMappingInterStore (check for equivalence of 'code' && 'mediaTypes' properties) + const adUnitDetail = adUnitsForAuction.filter(adUnitDetail => adUnitDetail.adUnitCode === adUnit.code && utils.deepEqual(adUnitDetail.mediaTypes, adUnit.mediaTypes)); + + if (adUnitDetail.length > 0) { + adUnitDetail[0].cacheHits++; + return adUnitDetail[0]; + } else { + const identicalAdUnit = adUnitsForAuction.filter(adUnitDetail => adUnitDetail.adUnitCode === adUnit.code); + const adUnitInstance = identicalAdUnit.length > 0 && typeof identicalAdUnit[0].instance === 'number' ? identicalAdUnit[identicalAdUnit.length - 1].instance + 1 : 1; + const isLabelActivated = internal.isLabelActivated(adUnit, labels, adUnit.code, adUnitInstance); + const { mediaTypes = adUnit.mediaTypes, sizeBucketToSizeMap, activeViewport, transformedMediaTypes } = isLabelActivated && internal.getFilteredMediaTypes(adUnit.mediaTypes); + + const adUnitDetail = { + adUnitCode: adUnit.code, + mediaTypes, + sizeBucketToSizeMap, + activeViewport, + transformedMediaTypes, + instance: adUnitInstance, + isLabelActivated, + cacheHits: 0 + }; + + // set adUnitDetail in sizeMappingInternalStore against the correct 'auctionId'. + sizeMappingInternalStore.setAuctionDetail(auctionId, adUnitDetail); + isLabelActivated && utils.logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${adUnitInstance}) => Active size buckets after filtration: `, sizeBucketToSizeMap); + + return adUnitDetail; + } } -export function setupAdUnitMediaTypes(adUnits, labels) { - const duplCounter = {}; +export function getBids({ bidderCode, auctionId, bidderRequestId, adUnits, labels, src }) { return adUnits.reduce((result, adUnit) => { - const instance = (() => { - if (!duplCounter.hasOwnProperty(adUnit.code)) { - duplCounter[adUnit.code] = 1; - } - return duplCounter[adUnit.code]++; - })(); - if (adUnit.mediaTypes && isValidMediaTypes(adUnit.mediaTypes)) { - const { activeViewport, transformedMediaTypes, isLabelActivated } = internal.getAdUnitDetail(adUnit, labels, instance); + if (adUnit.mediaTypes && utils.isValidMediaTypes(adUnit.mediaTypes)) { + const { activeViewport, transformedMediaTypes, instance: adUnitInstance, isLabelActivated, cacheHits } = internal.getAdUnitDetail(auctionId, adUnit, labels); if (isLabelActivated) { + // check if adUnit has any active media types remaining, if not drop the adUnit from auction, + // else proceed to evaluate the bids object. if (Object.keys(transformedMediaTypes).length === 0) { - logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}) => Ad unit disabled since there are no active media types after sizeConfig filtration.`); - } else { - adUnit.mediaTypes = transformedMediaTypes; - adUnit.bids = adUnit.bids.reduce((bids, bid) => { - if (internal.isLabelActivated(bid, labels, adUnit.code, instance)) { - if (bid.sizeConfig) { - const relevantMediaTypes = internal.getRelevantMediaTypesForBidder(bid.sizeConfig, activeViewport); - if (relevantMediaTypes.size === 0) { - logError(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}), Bidder: ${bid.bidder} => 'sizeConfig' is not configured properly. This bidder won't be eligible for sizeConfig checks and will remain active.`); - bids.push(bid); - } else if (!relevantMediaTypes.has('none')) { - let modified = false; - const bidderMediaTypes = Object.fromEntries( - Object.entries(transformedMediaTypes) - .filter(([key, val]) => { - if (!relevantMediaTypes.has(key)) { - modified = true; - return false; - } - return true; - }) - ); - if (Object.keys(bidderMediaTypes).length > 0) { - if (modified) { - bid.mediaTypes = bidderMediaTypes; + cacheHits === 0 && utils.logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${adUnitInstance}) => Ad unit disabled since there are no active media types after sizeConfig filtration.`); + return result; + } + result + .push(adUnit.bids.filter(bid => bid.bidder === bidderCode) + .reduce((bids, bid) => { + if (internal.isLabelActivated(bid, labels, adUnit.code, adUnitInstance)) { + // handle native params + const nativeParams = adUnit.nativeParams || utils.deepAccess(adUnit, 'mediaTypes.native'); + if (nativeParams) { + bid = Object.assign({}, bid, { + nativeParams: processNativeAdUnitParams(nativeParams) + }); + } + + bid = Object.assign({}, bid, utils.getDefinedParams(adUnit, ['mediaType', 'renderer'])); + + if (bid.sizeConfig) { + const relevantMediaTypes = internal.getRelevantMediaTypesForBidder(bid.sizeConfig, activeViewport); + if (relevantMediaTypes.length === 0) { + utils.logError(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${adUnitInstance}), Bidder: ${bidderCode} => 'sizeConfig' is not configured properly. This bidder won't be eligible for sizeConfig checks and will remail active.`); + bid = Object.assign({}, bid); + } else if (relevantMediaTypes[0] !== 'none') { + const bidderMediaTypes = Object + .keys(transformedMediaTypes) + .filter(mt => relevantMediaTypes.indexOf(mt) > -1) + .reduce((mediaTypes, mediaType) => { + mediaTypes[mediaType] = transformedMediaTypes[mediaType]; + return mediaTypes; + }, {}); + + if (Object.keys(bidderMediaTypes).length > 0) { + bid = Object.assign({}, bid, { mediaTypes: bidderMediaTypes }); + } else { + utils.logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${adUnitInstance}), Bidder: ${bid.bidder} => 'relevantMediaTypes' does not match with any of the active mediaTypes at the Ad Unit level. This bidder is disabled.`); + return bids; } - bids.push(bid); } else { - logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}), Bidder: ${bid.bidder} => 'relevantMediaTypes' does not match with any of the active mediaTypes at the Ad Unit level. This bidder is disabled.`); + utils.logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${adUnitInstance}), Bidder: ${bid.bidder} => 'relevantMediaTypes' is set to 'none' in sizeConfig for current viewport size. This bidder is disabled.`); + return bids; } - } else { - logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}), Bidder: ${bid.bidder} => 'relevantMediaTypes' is set to 'none' in sizeConfig for current viewport size. This bidder is disabled.`); } + bids.push(Object.assign({}, bid, { + adUnitCode: adUnit.code, + transactionId: adUnit.transactionId, + sizes: utils.deepAccess(transformedMediaTypes, 'banner.sizes') || utils.deepAccess(transformedMediaTypes, 'video.playerSize') || [], + mediaTypes: bid.mediaTypes || transformedMediaTypes, + bidId: bid.bid_id || utils.getUniqueIdentifierStr(), + bidderRequestId, + auctionId, + src, + bidRequestsCount: adunitCounter.getRequestsCounter(adUnit.code), + bidderRequestsCount: adunitCounter.getBidderRequestsCounter(adUnit.code, bid.bidder), + bidderWinsCount: adunitCounter.getBidderWinsCounter(adUnit.code, bid.bidder) + })); + return bids; } else { - bids.push(bid); + utils.logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${adUnitInstance}), Bidder: ${bid.bidder} => Label check for this bidder has failed. This bidder is disabled.`); + return bids; } - } else { - logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}), Bidder: ${bid.bidder} => Label check for this bidder has failed. This bidder is disabled.`); - } - return bids; - }, []); - result.push(adUnit); - } + }, [])); } else { - logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}) => Ad unit is disabled due to failing label check.`); + cacheHits === 0 && utils.logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${adUnitInstance}) => Ad unit is disabled due to failing label check.`); } } else { - logWarn(`Size Mapping V2:: Ad Unit: ${adUnit.code} => Ad unit has declared invalid 'mediaTypes' or has not declared a 'mediaTypes' property`); + utils.logWarn(`Size Mapping V2:: Ad Unit: ${adUnit.code} => Ad unit has declared invalid 'mediaTypes' or has not declared a 'mediaTypes' property`); + return result; } return result; - }, []) + }, []).reduce(utils.flatten, []).filter(val => val !== ''); } diff --git a/modules/slimcutBidAdapter.js b/modules/slimcutBidAdapter.js deleted file mode 100644 index 2d35e09d777..00000000000 --- a/modules/slimcutBidAdapter.js +++ /dev/null @@ -1,122 +0,0 @@ -import { getValue, parseSizesInput, getBidIdParameter } from '../src/utils.js'; -import { - registerBidder -} from '../src/adapters/bidderFactory.js'; -import { - ajax -} from '../src/ajax.js'; -const BIDDER_CODE = 'slimcut'; -const ENDPOINT_URL = 'https://sb.freeskreen.com/pbr'; -export const spec = { - code: BIDDER_CODE, - gvlid: 52, - aliases: [{ code: 'scm', gvlid: 52 }], - supportedMediaTypes: ['video', 'banner'], - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function(bid) { - let isValid = false; - if (typeof bid.params !== 'undefined' && !isNaN(parseInt(getValue(bid.params, 'placementId'))) && parseInt(getValue(bid.params, 'placementId')) > 0) { - isValid = true; - } - return isValid; - }, - /** - * Make a server request from the list of BidRequests. - * - * @param {validBidRequests[]} an array of bids - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function(validBidRequests, bidderRequest) { - const bids = validBidRequests.map(buildRequestObject); - const payload = { - referrer: getReferrerInfo(bidderRequest), - data: bids, - deviceWidth: screen.width - }; - let gdpr = bidderRequest.gdprConsent; - if (bidderRequest && gdpr) { - let isCmp = (typeof gdpr.gdprApplies === 'boolean') - let isConsentString = (typeof gdpr.consentString === 'string') - payload.gdpr_iab = { - consent: isConsentString ? gdpr.consentString : '', - status: isCmp ? gdpr.gdprApplies : -1 - }; - } - const payloadString = JSON.stringify(payload); - return { - method: 'POST', - url: ENDPOINT_URL, - data: payloadString, - }; - }, - /** - * Unpack the response from the server into a list of bids. - * - * @param {*} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function(serverResponse, request) { - const bidResponses = []; - serverResponse = serverResponse.body; - if (serverResponse.responses) { - serverResponse.responses.forEach(function(bid) { - const bidResponse = { - cpm: bid.cpm, - width: bid.width, - height: bid.height, - currency: bid.currency, - netRevenue: bid.netRevenue, - ttl: bid.ttl, - ad: bid.ad, - requestId: bid.requestId, - creativeId: bid.creativeId, - transactionId: bid.tranactionId, - winUrl: bid.winUrl, - meta: { - advertiserDomains: bid.adomain || [] - } - }; - bidResponses.push(bidResponse); - }); - } - return bidResponses; - }, - getUserSyncs: function(syncOptions, serverResponses) { - if (syncOptions.iframeEnabled) { - return [{ - type: 'iframe', - url: 'https://sb.freeskreen.com/async_usersync.html' - }]; - } - return []; - }, - onBidWon: function(bid) { - ajax(bid.winUrl + bid.cpm, null); - } -} -function buildRequestObject(bid) { - const reqObj = {}; - let placementId = getValue(bid.params, 'placementId'); - reqObj.sizes = parseSizesInput(bid.sizes); - reqObj.bidId = getBidIdParameter('bidId', bid); - reqObj.bidderRequestId = getBidIdParameter('bidderRequestId', bid); - reqObj.placementId = parseInt(placementId); - reqObj.adUnitCode = getBidIdParameter('adUnitCode', bid); - reqObj.auctionId = getBidIdParameter('auctionId', bid); - reqObj.transactionId = getBidIdParameter('transactionId', bid); - return reqObj; -} -function getReferrerInfo(bidderRequest) { - let ref = window.location.href; - if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { - ref = bidderRequest.refererInfo.referer; - } - return ref; -} - -registerBidder(spec); diff --git a/modules/smaatoBidAdapter.js b/modules/smaatoBidAdapter.js index b792983534d..700fcf17785 100644 --- a/modules/smaatoBidAdapter.js +++ b/modules/smaatoBidAdapter.js @@ -1,11 +1,11 @@ -import { deepAccess, getDNT, deepSetValue, logInfo, logError, isEmpty, getAdUnitSizes, fill, chunk, getMaxValueFromArray, getMinValueFromArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; import {ADPOD, BANNER, VIDEO} from '../src/mediaTypes.js'; const BIDDER_CODE = 'smaato'; const SMAATO_ENDPOINT = 'https://prebid.ad.smaato.net/oapi/prebid'; -const SMAATO_CLIENT = 'prebid_js_$prebid.version$_1.6' +const SMAATO_CLIENT = 'prebid_js_$prebid.version$_1.4' const CURRENCY = 'USD'; const buildOpenRtbBidRequest = (bidRequest, bidderRequest) => { @@ -16,6 +16,9 @@ const buildOpenRtbBidRequest = (bidRequest, bidderRequest) => { tmax: bidderRequest.timeout, site: { id: window.location.hostname, + publisher: { + id: utils.deepAccess(bidRequest, 'params.publisherId') + }, domain: window.location.hostname, page: window.location.href, ref: bidderRequest.refererInfo.referer @@ -23,7 +26,7 @@ const buildOpenRtbBidRequest = (bidRequest, bidderRequest) => { device: { language: (navigator && navigator.language) ? navigator.language.split('-')[0] : '', ua: navigator.userAgent, - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, h: screen.height, w: screen.width }, @@ -34,11 +37,6 @@ const buildOpenRtbBidRequest = (bidRequest, bidderRequest) => { user: { ext: {} }, - source: { - ext: { - schain: bidRequest.schain - } - }, ext: { client: SMAATO_CLIENT } @@ -48,37 +46,35 @@ const buildOpenRtbBidRequest = (bidRequest, bidderRequest) => { Object.assign(requestTemplate.user, ortb2.user); Object.assign(requestTemplate.site, ortb2.site); - deepSetValue(requestTemplate, 'site.publisher.id', deepAccess(bidRequest, 'params.publisherId')); - if (bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies === true) { - deepSetValue(requestTemplate, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies ? 1 : 0); - deepSetValue(requestTemplate, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(requestTemplate, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies ? 1 : 0); + utils.deepSetValue(requestTemplate, 'user.ext.consent', bidderRequest.gdprConsent.consentString); } if (bidderRequest.uspConsent !== undefined) { - deepSetValue(requestTemplate, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(requestTemplate, 'regs.ext.us_privacy', bidderRequest.uspConsent); } - if (deepAccess(bidRequest, 'params.app')) { - const geo = deepAccess(bidRequest, 'params.app.geo'); - deepSetValue(requestTemplate, 'device.geo', geo); - const ifa = deepAccess(bidRequest, 'params.app.ifa') - deepSetValue(requestTemplate, 'device.ifa', ifa); + if (utils.deepAccess(bidRequest, 'params.app')) { + const geo = utils.deepAccess(bidRequest, 'params.app.geo'); + utils.deepSetValue(requestTemplate, 'device.geo', geo); + const ifa = utils.deepAccess(bidRequest, 'params.app.ifa') + utils.deepSetValue(requestTemplate, 'device.ifa', ifa); } - const eids = deepAccess(bidRequest, 'userIdAsEids'); + const eids = utils.deepAccess(bidRequest, 'userIdAsEids'); if (eids && eids.length) { - deepSetValue(requestTemplate, 'user.ext.eids', eids); + utils.deepSetValue(requestTemplate, 'user.ext.eids', eids); } let requests = []; - if (deepAccess(bidRequest, 'mediaTypes.banner')) { + if (utils.deepAccess(bidRequest, 'mediaTypes.banner')) { const bannerRequest = Object.assign({}, requestTemplate, createBannerImp(bidRequest)); requests.push(bannerRequest); } - const videoMediaType = deepAccess(bidRequest, 'mediaTypes.video'); + const videoMediaType = utils.deepAccess(bidRequest, 'mediaTypes.video'); if (videoMediaType) { if (videoMediaType.context === ADPOD) { const adPodRequest = Object.assign({}, requestTemplate, createAdPodImp(bidRequest, videoMediaType)); @@ -94,7 +90,7 @@ const buildOpenRtbBidRequest = (bidRequest, bidderRequest) => { } const buildServerRequest = (validBidRequest, data) => { - logInfo('[SMAATO] OpenRTB Request:', data); + utils.logInfo('[SMAATO] OpenRTB Request:', data); return { method: 'POST', url: validBidRequest.params.endpoint || SMAATO_ENDPOINT, @@ -109,7 +105,6 @@ const buildServerRequest = (validBidRequest, data) => { export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER, VIDEO], - gvlid: 82, /** * Determines whether or not the given bid request is valid. @@ -119,47 +114,47 @@ export const spec = { */ isBidRequestValid: (bid) => { if (typeof bid.params !== 'object') { - logError('[SMAATO] Missing params object'); + utils.logError('[SMAATO] Missing params object'); return false; } if (typeof bid.params.publisherId !== 'string') { - logError('[SMAATO] Missing mandatory publisherId param'); + utils.logError('[SMAATO] Missing mandatory publisherId param'); return false; } - if (deepAccess(bid, 'mediaTypes.video.context') === ADPOD) { - logInfo('[SMAATO] Verifying adpod bid request'); + if (utils.deepAccess(bid, 'mediaTypes.video.context') === ADPOD) { + utils.logInfo('[SMAATO] Verifying adpod bid request'); if (typeof bid.params.adbreakId !== 'string') { - logError('[SMAATO] Missing for adpod request mandatory adbreakId param'); + utils.logError('[SMAATO] Missing for adpod request mandatory adbreakId param'); return false; } if (bid.params.adspaceId) { - logError('[SMAATO] The adspaceId param is not allowed in an adpod bid request'); + utils.logError('[SMAATO] The adspaceId param is not allowed in an adpod bid request'); return false; } } else { - logInfo('[SMAATO] Verifying a non adpod bid request'); + utils.logInfo('[SMAATO] Verifying a non adpod bid request'); if (typeof bid.params.adspaceId !== 'string') { - logError('[SMAATO] Missing mandatory adspaceId param'); + utils.logError('[SMAATO] Missing mandatory adspaceId param'); return false; } if (bid.params.adbreakId) { - logError('[SMAATO] The adbreakId param is only allowed in an adpod bid request'); + utils.logError('[SMAATO] The adbreakId param is only allowed in an adpod bid request'); return false; } } - logInfo('[SMAATO] Verification done, all good'); + utils.logInfo('[SMAATO] Verification done, all good'); return true; }, buildRequests: (validBidRequests, bidderRequest) => { - logInfo('[SMAATO] Client version:', SMAATO_CLIENT); + utils.logInfo('[SMAATO] Client version:', SMAATO_CLIENT); return validBidRequests.map((validBidRequest) => { const openRtbBidRequests = buildOpenRtbBidRequest(validBidRequest, bidderRequest); @@ -174,19 +169,19 @@ export const spec = { */ interpretResponse: (serverResponse, bidRequest) => { // response is empty (HTTP 204) - if (isEmpty(serverResponse.body)) { - logInfo('[SMAATO] Empty response body HTTP 204, no bids'); + if (utils.isEmpty(serverResponse.body)) { + utils.logInfo('[SMAATO] Empty response body HTTP 204, no bids'); return []; // no bids } const serverResponseHeaders = serverResponse.headers; const smtExpires = serverResponseHeaders.get('X-SMT-Expires'); - logInfo('[SMAATO] Expires:', smtExpires); + utils.logInfo('[SMAATO] Expires:', smtExpires); const ttlInSec = smtExpires ? Math.floor((smtExpires - Date.now()) / 1000) : 300; const response = serverResponse.body; - logInfo('[SMAATO] OpenRTB Response:', response); + utils.logInfo('[SMAATO] OpenRTB Response:', response); const smtAdType = serverResponseHeaders.get('X-SMT-ADTYPE'); const bids = []; @@ -200,7 +195,7 @@ export const spec = { ttl: ttlInSec, creativeId: bid.crid, dealId: bid.dealid || null, - netRevenue: deepAccess(bid, 'ext.net', true), + netRevenue: utils.deepAccess(bid, 'ext.net', true), currency: response.cur, meta: { advertiserDomains: bid.adomain, @@ -209,7 +204,7 @@ export const spec = { } }; - const videoContext = deepAccess(JSON.parse(bidRequest.data).imp[0], 'video.ext.context') + const videoContext = utils.deepAccess(JSON.parse(bidRequest.data).imp[0], 'video.ext.context') if (videoContext === ADPOD) { resultingBid.vastXml = bid.adm; resultingBid.mediaType = VIDEO; @@ -239,14 +234,14 @@ export const spec = { bids.push(resultingBid); break; default: - logInfo('[SMAATO] Invalid ad type:', smtAdType); + utils.logInfo('[SMAATO] Invalid ad type:', smtAdType); } } resultingBid.meta.mediaType = resultingBid.mediaType; }); }); - logInfo('[SMAATO] Prebid bids:', bids); + utils.logInfo('[SMAATO] Prebid bids:', bids); return bids; }, @@ -297,14 +292,13 @@ const createRichmediaAd = (adm) => { }; function createBannerImp(bidRequest) { - const adUnitSizes = getAdUnitSizes(bidRequest); + const adUnitSizes = utils.getAdUnitSizes(bidRequest); const sizes = adUnitSizes.map((size) => ({w: size[0], h: size[1]})); return { imp: [{ id: bidRequest.bidId, - tagid: deepAccess(bidRequest, 'params.adspaceId'), + tagid: utils.deepAccess(bidRequest, 'params.adspaceId'), bidfloor: getBidFloor(bidRequest, BANNER, adUnitSizes), - instl: deepAccess(bidRequest.ortb2Imp, 'instl'), banner: { w: sizes[0].w, h: sizes[0].h, @@ -318,9 +312,8 @@ function createVideoImp(bidRequest, videoMediaType) { return { imp: [{ id: bidRequest.bidId, - tagid: deepAccess(bidRequest, 'params.adspaceId'), + tagid: utils.deepAccess(bidRequest, 'params.adspaceId'), bidfloor: getBidFloor(bidRequest, VIDEO, videoMediaType.playerSize), - instl: deepAccess(bidRequest.ortb2Imp, 'instl'), video: { mimes: videoMediaType.mimes, minduration: videoMediaType.minduration, @@ -342,13 +335,12 @@ function createVideoImp(bidRequest, videoMediaType) { } function createAdPodImp(bidRequest, videoMediaType) { - const tagid = deepAccess(bidRequest, 'params.adbreakId') + const tagid = utils.deepAccess(bidRequest, 'params.adbreakId') const bce = config.getConfig('adpod.brandCategoryExclusion') let imp = { id: bidRequest.bidId, tagid: tagid, bidfloor: getBidFloor(bidRequest, VIDEO, videoMediaType.playerSize), - instl: deepAccess(bidRequest.ortb2Imp, 'instl'), video: { w: videoMediaType.playerSize[0][0], h: videoMediaType.playerSize[0][1], @@ -367,13 +359,13 @@ function createAdPodImp(bidRequest, videoMediaType) { } const numberOfPlacements = getAdPodNumberOfPlacements(videoMediaType) - let imps = fill(imp, numberOfPlacements) + let imps = utils.fill(imp, numberOfPlacements) const durationRangeSec = videoMediaType.durationRangeSec if (videoMediaType.requireExactDuration) { // equal distribution of numberOfPlacement over all available durations const divider = Math.ceil(numberOfPlacements / durationRangeSec.length) - const chunked = chunk(imps, divider) + const chunked = utils.chunk(imps, divider) // each configured duration is set as min/maxduration for a subset of requests durationRangeSec.forEach((duration, index) => { @@ -386,7 +378,7 @@ function createAdPodImp(bidRequest, videoMediaType) { }); } else { // all maxdurations should be the same - const maxDuration = getMaxValueFromArray(durationRangeSec); + const maxDuration = utils.getMaxValueFromArray(durationRangeSec); imps.map((imp, index) => { const sequence = index + 1; imp.video.maxduration = maxDuration @@ -401,7 +393,7 @@ function createAdPodImp(bidRequest, videoMediaType) { function getAdPodNumberOfPlacements(videoMediaType) { const {adPodDurationSec, durationRangeSec, requireExactDuration} = videoMediaType - const minAllowedDuration = getMinValueFromArray(durationRangeSec) + const minAllowedDuration = utils.getMinValueFromArray(durationRangeSec) const numberOfPlacements = Math.floor(adPodDurationSec / minAllowedDuration) return requireExactDuration @@ -431,7 +423,7 @@ const addOptionalAdpodParameters = (request, videoMediaType) => { content.livestream = videoMediaType.contentMode === 'live' ? 1 : 0 } - if (!isEmpty(content)) { + if (!utils.isEmpty(content)) { request.site.content = content } } diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index d6e1c8de452..a7b609bca20 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, deepClone, logError, isFn, isPlainObject } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { createEidsArray } from './userId/eids.js'; @@ -170,8 +170,8 @@ export const spec = { payload.us_privacy = bidderRequest.uspConsent; } - const videoMediaType = deepAccess(bid, 'mediaTypes.video'); - const bannerMediaType = deepAccess(bid, 'mediaTypes.banner'); + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const bannerMediaType = utils.deepAccess(bid, 'mediaTypes.banner'); const isAdUnitContainingVideo = videoMediaType && (videoMediaType.context === 'instream' || videoMediaType.context === 'outstream'); if (!isAdUnitContainingVideo && bannerMediaType) { payload.sizes = spec.adaptBannerSizes(bannerMediaType.sizes); @@ -182,7 +182,7 @@ export const spec = { } else if (isAdUnitContainingVideo && bannerMediaType) { // If there are video and banner media types in the ad unit, we clone the payload // to create a specific one for video. - let videoPayload = deepClone(payload); + let videoPayload = utils.deepClone(payload); spec.fillPayloadForVideoBidRequest(videoPayload, videoMediaType, bid.params.video); bidRequests.push(spec.createServerRequest(videoPayload, bid.params.domain)); @@ -238,7 +238,7 @@ export const spec = { bidResponses.push(bidResponse); } } catch (error) { - logError('Error while parsing smart server response', error); + utils.logError('Error while parsing smart server response', error); } return bidResponses; }, @@ -251,7 +251,7 @@ export const spec = { * @return {number} Floor price */ getBidFloor: function (bid, currency) { - if (!isFn(bid.getFloor)) { + if (!utils.isFn(bid.getFloor)) { return DEFAULT_FLOOR; } @@ -261,7 +261,7 @@ export const spec = { size: '*' }); - if (isPlainObject(floor) && !isNaN(floor.floor)) { + if (utils.isPlainObject(floor) && !isNaN(floor.floor)) { return floor.floor; } diff --git a/modules/smarthubBidAdapter.js b/modules/smarthubBidAdapter.js deleted file mode 100644 index a94ed972b2e..00000000000 --- a/modules/smarthubBidAdapter.js +++ /dev/null @@ -1,187 +0,0 @@ -import {deepAccess, isFn, logError, logMessage} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; - -const BIDDER_CODE = 'smarthub'; - -function isBidResponseValid(bid) { - if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency || !bid.hasOwnProperty('netRevenue')) { - return false; - } - switch (bid.mediaType) { - case BANNER: - return Boolean(bid.width && bid.height && bid.ad); - case VIDEO: - return Boolean(bid.width && bid.height && (bid.vastUrl || bid.vastXml)); - case NATIVE: - return Boolean(bid.native && bid.native.impressionTrackers && bid.native.impressionTrackers.length); - default: - return false; - } -} - -function getPlacementReqData(bid) { - const { params, bidId, mediaTypes } = bid; - const schain = bid.schain || {}; - const { partnerName, seat, token, iabCat, minBidfloor, pos } = params; - const bidfloor = getBidFloor(bid); - - const placement = { - partnerName: partnerName.toLowerCase(), - seat, - token, - iabCat, - minBidfloor, - pos, - bidId, - schain, - bidfloor - }; - - if (mediaTypes && mediaTypes[BANNER]) { - placement.adFormat = BANNER; - placement.sizes = mediaTypes[BANNER].sizes; - } else if (mediaTypes && mediaTypes[VIDEO]) { - placement.adFormat = VIDEO; - placement.playerSize = mediaTypes[VIDEO].playerSize; - placement.minduration = mediaTypes[VIDEO].minduration; - placement.maxduration = mediaTypes[VIDEO].maxduration; - placement.mimes = mediaTypes[VIDEO].mimes; - placement.protocols = mediaTypes[VIDEO].protocols; - placement.startdelay = mediaTypes[VIDEO].startdelay; - placement.placement = mediaTypes[VIDEO].placement; - placement.skip = mediaTypes[VIDEO].skip; - placement.skipafter = mediaTypes[VIDEO].skipafter; - placement.minbitrate = mediaTypes[VIDEO].minbitrate; - placement.maxbitrate = mediaTypes[VIDEO].maxbitrate; - placement.delivery = mediaTypes[VIDEO].delivery; - placement.playbackmethod = mediaTypes[VIDEO].playbackmethod; - placement.api = mediaTypes[VIDEO].api; - placement.linearity = mediaTypes[VIDEO].linearity; - } else if (mediaTypes && mediaTypes[NATIVE]) { - placement.native = mediaTypes[NATIVE]; - placement.adFormat = NATIVE; - } - - return placement; -} - -function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidfloor', 0); - } - - try { - const bidFloor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*', - }); - return bidFloor.floor; - } catch (e) { - logError(e); - return 0; - } -} - -function buildRequestParams(bidderRequest = {}, placements = []) { - let deviceWidth = 0; - let deviceHeight = 0; - - let winLocation; - try { - const winTop = window.top; - deviceWidth = winTop.screen.width; - deviceHeight = winTop.screen.height; - winLocation = winTop.location; - } catch (e) { - logMessage(e); - winLocation = window.location; - } - - const refferUrl = bidderRequest.refererInfo && bidderRequest.refererInfo.referer; - let refferLocation; - try { - refferLocation = refferUrl && new URL(refferUrl); - } catch (e) { - logMessage(e); - } - - let location = refferLocation || winLocation; - const language = (navigator && navigator.language) ? navigator.language.split('-')[0] : ''; - const host = location.host; - const page = location.pathname; - const secure = location.protocol === 'https:' ? 1 : 0; - return { - deviceWidth, - deviceHeight, - language, - secure, - host, - page, - placements, - coppa: config.getConfig('coppa') === true ? 1 : 0, - ccpa: bidderRequest.uspConsent || undefined, - gdpr: bidderRequest.gdprConsent || undefined, - tmax: config.getConfig('bidderTimeout') - }; -} - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO, NATIVE], - - isBidRequestValid: (bid = {}) => { - const { params, bidId, mediaTypes } = bid; - let valid = Boolean(bidId && params && params.partnerName && params.seat && params.token); - - if (mediaTypes && mediaTypes[BANNER]) { - valid = valid && Boolean(mediaTypes[BANNER] && mediaTypes[BANNER].sizes); - } else if (mediaTypes && mediaTypes[VIDEO]) { - valid = valid && Boolean(mediaTypes[VIDEO] && mediaTypes[VIDEO].playerSize); - } else if (mediaTypes && mediaTypes[NATIVE]) { - valid = valid && Boolean(mediaTypes[NATIVE]); - } else { - valid = false; - } - return valid; - }, - - buildRequests: (validBidRequests = [], bidderRequest = {}) => { - const tempObj = {}; - - const len = validBidRequests.length; - for (let i = 0; i < len; i++) { - const bid = validBidRequests[i]; - const data = getPlacementReqData(bid); - tempObj[data.partnerName] = tempObj[data.partnerName] || []; - tempObj[data.partnerName].push(data); - } - - return Object.keys(tempObj).map(key => { - const request = buildRequestParams(bidderRequest, tempObj[key]); - return { - method: 'POST', - url: `https://${key}-prebid.smart-hub.io/pbjs`, - data: request, - } - }); - }, - - interpretResponse: (serverResponse) => { - let response = []; - for (let i = 0; i < serverResponse.body.length; i++) { - let resItem = serverResponse.body[i]; - if (isBidResponseValid(resItem)) { - const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : []; - resItem.meta = { ...resItem.meta, advertiserDomains }; - - response.push(resItem); - } - } - return response; - } -}; - -registerBidder(spec); diff --git a/modules/smarthubBidAdapter.md b/modules/smarthubBidAdapter.md deleted file mode 100644 index c09855303e2..00000000000 --- a/modules/smarthubBidAdapter.md +++ /dev/null @@ -1,94 +0,0 @@ -# Overview - -``` -Module Name: SmartHub Bidder Adapter -Module Type: SmartHub Bidder Adapter -Maintainer: support@smart-hub.io -``` - -# Description - -Connects to SmartHub exchange for bids. - -SmartHub bid adapter supports Banner, Video (instream and outstream) and Native. - -# Test Parameters -``` - var adUnits = [ - // Will return static test banner - { - code: 'adunit1', - mediaTypes: { - banner: { - sizes: [ [300, 250], [320, 50] ], - } - }, - bids: [ - { - bidder: 'smarthub', - params: { - partnerName: 'pbjstest', - seat: 'testSeat', - token: 'testBanner', - iabCat: ['IAB1-1', 'IAB3-1', 'IAB4-3'], - minBidfloor: 10, - pos: 1, - } - } - ] - }, - { - code: 'addunit2', - mediaTypes: { - video: { - playerSize: [ [640, 480] ], - minduration: 5, - maxduration: 60, - } - }, - bids: [ - { - bidder: 'smarthub', - params: { - partnerName: 'pbjstest', - seat: 'testSeat', - token: 'testVideo', - iabCat: ['IAB1-1', 'IAB3-1', 'IAB4-3'], - minBidfloor: 10, - pos: 1, - } - } - ] - }, - { - code: 'addunit3', - mediaTypes: { - native: { - title: { - required: true - }, - body: { - required: true - }, - icon: { - required: true, - size: [64, 64] - } - } - }, - bids: [ - { - bidder: 'smarthub', - params: { - partnerName: 'pbjstest', - seat: 'testSeat', - token: 'testNative', - iabCat: ['IAB1-1', 'IAB3-1', 'IAB4-3'], - minBidfloor: 10, - pos: 1, - } - } - ] - } - ]; -``` diff --git a/modules/smarticoBidAdapter.js b/modules/smarticoBidAdapter.js index edb774f812f..2399a12f932 100644 --- a/modules/smarticoBidAdapter.js +++ b/modules/smarticoBidAdapter.js @@ -1,6 +1,6 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER} from '../src/mediaTypes.js'; -import {find} from '../src/polyfill.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER } from '../src/mediaTypes.js'; +import find from 'core-js-pure/features/array/find.js'; const SMARTICO_CONFIG = { bidRequestUrl: 'https://trmads.eu/preBidRequest', diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 00c962445d9..c29708c8420 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -1,4 +1,4 @@ -import { logError, deepAccess, isArray, getBidIdParameter, getDNT, generateUUID, isEmpty, _each, logMessage, logWarn, isFn, isPlainObject } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { Renderer } from '../src/Renderer.js'; @@ -22,37 +22,37 @@ export const spec = { */ isBidRequestValid: function (bid) { if (bid && typeof bid.params !== 'object') { - logError(BIDDER_CODE + ': params is not defined or is incorrect in the bidder settings.'); + utils.logError(BIDDER_CODE + ': params is not defined or is incorrect in the bidder settings.'); return false; } - if (!deepAccess(bid, 'mediaTypes.video')) { - logError(BIDDER_CODE + ': mediaTypes.video is not present in the bidder settings.'); + if (!utils.deepAccess(bid, 'mediaTypes.video')) { + utils.logError(BIDDER_CODE + ': mediaTypes.video is not present in the bidder settings.'); return false; } - const playerSize = deepAccess(bid, 'mediaTypes.video.playerSize'); - if (!playerSize || !isArray(playerSize)) { - logError(BIDDER_CODE + ': mediaTypes.video.playerSize is not defined in the bidder settings.'); + const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); + if (!playerSize || !utils.isArray(playerSize)) { + utils.logError(BIDDER_CODE + ': mediaTypes.video.playerSize is not defined in the bidder settings.'); return false; } - if (!getBidIdParameter('tagId', bid.params)) { - logError(BIDDER_CODE + ': tagId is not present in bidder params'); + if (!utils.getBidIdParameter('tagId', bid.params)) { + utils.logError(BIDDER_CODE + ': tagId is not present in bidder params'); return false; } - if (!getBidIdParameter('publisherId', bid.params)) { - logError(BIDDER_CODE + ': publisherId is not present in bidder params'); + if (!utils.getBidIdParameter('publisherId', bid.params)) { + utils.logError(BIDDER_CODE + ': publisherId is not present in bidder params'); return false; } - if (!getBidIdParameter('siteId', bid.params)) { - logError(BIDDER_CODE + ': siteId is not present in bidder params'); + if (!utils.getBidIdParameter('siteId', bid.params)) { + utils.logError(BIDDER_CODE + ': siteId is not present in bidder params'); return false; } - if (deepAccess(bid, 'mediaTypes.video.context') === 'outstream') { - if (!getBidIdParameter('outstream_options', bid.params)) { - logError(BIDDER_CODE + ': outstream_options parameter is not defined'); + if (utils.deepAccess(bid, 'mediaTypes.video.context') === 'outstream') { + if (!utils.getBidIdParameter('outstream_options', bid.params)) { + utils.logError(BIDDER_CODE + ': outstream_options parameter is not defined'); return false; } - if (!getBidIdParameter('slot', bid.params.outstream_options)) { - logError(BIDDER_CODE + ': slot parameter is not defined in outstream_options object in the configuration'); + if (!utils.getBidIdParameter('slot', bid.params.outstream_options)) { + utils.logError(BIDDER_CODE + ': slot parameter is not defined in outstream_options object in the configuration'); return false; } } @@ -71,33 +71,33 @@ export const spec = { const isPageSecure = !!page.match(/^https:/) const smartxRequests = bidRequests.map(function (bid) { - const tagId = getBidIdParameter('tagId', bid.params); - const publisherId = getBidIdParameter('publisherId', bid.params); + const tagId = utils.getBidIdParameter('tagId', bid.params); + const publisherId = utils.getBidIdParameter('publisherId', bid.params); const bidfloor = getBidFloor(bid) || 0; - const bidfloorcur = getBidIdParameter('bidfloorcur', bid.params) || 'EUR'; - const siteId = getBidIdParameter('siteId', bid.params); - const domain = getBidIdParameter('domain', bid.params); - const cat = getBidIdParameter('cat', bid.params) || ['']; + const bidfloorcur = utils.getBidIdParameter('bidfloorcur', bid.params) || 'EUR'; + const siteId = utils.getBidIdParameter('siteId', bid.params); + const domain = utils.getBidIdParameter('domain', bid.params); + const cat = utils.getBidIdParameter('cat', bid.params) || ['']; let pubcid = null; - const playerSize = deepAccess(bid, 'mediaTypes.video.playerSize'); + const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); const contentWidth = playerSize[0][0]; const contentHeight = playerSize[0][1]; - const secure = +(isPageSecure || (getBidIdParameter('secure', bid.params) ? 1 : 0)); + const secure = +(isPageSecure || (utils.getBidIdParameter('secure', bid.params) ? 1 : 0)); const ext = { sdk_name: 'Prebid 1+' }; - const mimes = getBidIdParameter('mimes', bid.params) || ['application/javascript', 'video/mp4', 'video/webm']; - const linearity = getBidIdParameter('linearity', bid.params) || 1; - const minduration = getBidIdParameter('minduration', bid.params) || 0; - const maxduration = getBidIdParameter('maxduration', bid.params) || 500; - const startdelay = getBidIdParameter('startdelay', bid.params) || 0; - const minbitrate = getBidIdParameter('minbitrate', bid.params) || 0; - const maxbitrate = getBidIdParameter('maxbitrate', bid.params) || 3500; - const delivery = getBidIdParameter('delivery', bid.params) || [2]; - const pos = getBidIdParameter('pos', bid.params) || 1; - const api = getBidIdParameter('api', bid.params) || [2]; - const protocols = getBidIdParameter('protocols', bid.params) || [2, 3, 5, 6]; - var contextcustom = deepAccess(bid, 'mediaTypes.video.context'); + const mimes = utils.getBidIdParameter('mimes', bid.params) || ['application/javascript', 'video/mp4', 'video/webm']; + const linearity = utils.getBidIdParameter('linearity', bid.params) || 1; + const minduration = utils.getBidIdParameter('minduration', bid.params) || 0; + const maxduration = utils.getBidIdParameter('maxduration', bid.params) || 500; + const startdelay = utils.getBidIdParameter('startdelay', bid.params) || 0; + const minbitrate = utils.getBidIdParameter('minbitrate', bid.params) || 0; + const maxbitrate = utils.getBidIdParameter('maxbitrate', bid.params) || 3500; + const delivery = utils.getBidIdParameter('delivery', bid.params) || [2]; + const pos = utils.getBidIdParameter('pos', bid.params) || 1; + const api = utils.getBidIdParameter('api', bid.params) || [2]; + const protocols = utils.getBidIdParameter('protocols', bid.params) || [2, 3, 5, 6]; + var contextcustom = utils.deepAccess(bid, 'mediaTypes.video.context'); var placement = 1; if (contextcustom === 'outstream') { @@ -141,18 +141,18 @@ export const spec = { const device = { h: screen.height, w: screen.width, - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, language: navigator[language].split('-')[0], make: navigator.vendor ? navigator.vendor : '', ua: navigator.userAgent }; - const at = getBidIdParameter('at', bid.params) || 2; + const at = utils.getBidIdParameter('at', bid.params) || 2; - const cur = getBidIdParameter('cur', bid.params) || ['EUR']; + const cur = utils.getBidIdParameter('cur', bid.params) || ['EUR']; const requestPayload = { - id: generateUUID(), + id: utils.generateUUID(), imp: smartxReq, site: { id: siteId, @@ -161,20 +161,11 @@ export const spec = { domain: domain, publisher: { id: publisherId - }, - content: { - ext: { - prebid: { - name: 'pbjs', - version: '$prebid.version$' - } - } } }, device: device, at: at, - cur: cur, - ext: {} + cur: cur }; const userExt = {}; @@ -197,16 +188,14 @@ export const spec = { } // Only add the user object if it's not empty - if (!isEmpty(userExt)) { + if (!utils.isEmpty(userExt)) { requestPayload.user = { ext: userExt }; } - // requestPayload.user.ext.ver = pbjs.version; - // Targeting - if (getBidIdParameter('data', bid.params.user)) { + if (utils.getBidIdParameter('data', bid.params.user)) { var targetingarr = []; for (var i = 0; i < bid.params.user.data.length; i++) { var isemq = (bid.params.user.data[i].name) || 'empty'; @@ -257,9 +246,9 @@ export const spec = { interpretResponse: function (serverResponse, bidderRequest) { const bidResponses = []; const serverResponseBody = serverResponse.body; - if (serverResponseBody && isArray(serverResponseBody.seatbid)) { - _each(serverResponseBody.seatbid, function (bids) { - _each(bids.bid, function (smartxBid) { + if (serverResponseBody && utils.isArray(serverResponseBody.seatbid)) { + utils._each(serverResponseBody.seatbid, function (bids) { + utils._each(bids.bid, function (smartxBid) { let currentBidRequest = {}; for (let i in bidderRequest.bidRequest.bids) { if (smartxBid.impid == bidderRequest.bidRequest.bids[i].bidId) { @@ -270,7 +259,7 @@ export const spec = { * Make sure currency and price are the right ones * TODO: what about the pre_market_bid partners sizes? */ - _each(currentBidRequest.params.pre_market_bids, function (pmb) { + utils._each(currentBidRequest.params.pre_market_bids, function (pmb) { if (pmb.deal_id == smartxBid.id) { smartxBid.price = pmb.price; serverResponseBody.cur = pmb.currency; @@ -296,10 +285,10 @@ export const spec = { bid.meta.advertiserDomains = smartxBid.adomain; } - const context = deepAccess(currentBidRequest, 'mediaTypes.video.context'); + const context = utils.deepAccess(currentBidRequest, 'mediaTypes.video.context'); if (context === 'outstream') { - const playersize = deepAccess(currentBidRequest, 'mediaTypes.video.playerSize'); + const playersize = utils.deepAccess(currentBidRequest, 'mediaTypes.video.playerSize'); const renderer = Renderer.install({ id: 0, url: 'https://dco.smartclip.net/?plc=7777778', @@ -307,27 +296,27 @@ export const spec = { adText: 'SmartX Outstream Video Ad via Prebid.js', player_width: playersize[0][0], player_height: playersize[0][1], - content_page_url: deepAccess(bidderRequest, 'data.site.page'), - ad_mute: +!!deepAccess(currentBidRequest, 'params.ad_mute'), - hide_skin: +!!deepAccess(currentBidRequest, 'params.hide_skin'), - outstream_options: deepAccess(currentBidRequest, 'params.outstream_options') + content_page_url: utils.deepAccess(bidderRequest, 'data.site.page'), + ad_mute: +!!utils.deepAccess(currentBidRequest, 'params.ad_mute'), + hide_skin: +!!utils.deepAccess(currentBidRequest, 'params.hide_skin'), + outstream_options: utils.deepAccess(currentBidRequest, 'params.outstream_options') } }); try { renderer.setRender(createOutstreamConfig); renderer.setEventHandlers({ impression: function impression() { - return logMessage('SmartX outstream video impression event'); + return utils.logMessage('SmartX outstream video impression event'); }, loaded: function loaded() { - return logMessage('SmartX outstream video loaded event'); + return utils.logMessage('SmartX outstream video loaded event'); }, ended: function ended() { - return logMessage('SmartX outstream renderer video event'); + return utils.logMessage('SmartX outstream renderer video event'); } }); } catch (err) { - logWarn('Prebid Error calling setRender or setEventHandlers on renderer', err); + utils.logWarn('Prebid Error calling setRender or setEventHandlers on renderer', err); } bid.renderer = renderer; } @@ -340,21 +329,25 @@ export const spec = { } function createOutstreamConfig(bid) { - let confMinAdWidth = getBidIdParameter('minAdWidth', bid.renderer.config.outstream_options) || 290; - let confMaxAdWidth = getBidIdParameter('maxAdWidth', bid.renderer.config.outstream_options) || 900; - let confStartOpen = getBidIdParameter('startOpen', bid.renderer.config.outstream_options) - let confEndingScreen = getBidIdParameter('endingScreen', bid.renderer.config.outstream_options) - let confTitle = getBidIdParameter('title', bid.renderer.config.outstream_options); - let confSkipOffset = getBidIdParameter('skipOffset', bid.renderer.config.outstream_options); - let confDesiredBitrate = getBidIdParameter('desiredBitrate', bid.renderer.config.outstream_options); - let confVisibilityThreshold = getBidIdParameter('visibilityThreshold', bid.renderer.config.outstream_options); - let elementId = getBidIdParameter('slot', bid.renderer.config.outstream_options) || bid.adUnitCode; - - logMessage('[SMARTX][renderer] Handle SmartX outstream renderer'); + const confMinAdWidth = utils.getBidIdParameter('minAdWidth', bid.renderer.config.outstream_options) || 290; + const confMaxAdWidth = utils.getBidIdParameter('maxAdWidth', bid.renderer.config.outstream_options) || 900; + const confStartOpen = utils.getBidIdParameter('startOpen', bid.renderer.config.outstream_options); + const confEndingScreen = utils.getBidIdParameter('endingScreen', bid.renderer.config.outstream_options); + const confTitle = utils.getBidIdParameter('title', bid.renderer.config.outstream_options); + const confSkipOffset = utils.getBidIdParameter('skipOffset', bid.renderer.config.outstream_options); + const confDesiredBitrate = utils.getBidIdParameter('desiredBitrate', bid.renderer.config.outstream_options); + const elementId = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options) || bid.adUnitCode; + + utils.logMessage('[SMARTX][renderer] Handle SmartX outstream renderer'); var smartPlayObj = { minAdWidth: confMinAdWidth, maxAdWidth: confMaxAdWidth, + title: confTitle, + skipOffset: confSkipOffset, + startOpen: confStartOpen, + endingScreen: confEndingScreen, + desiredBitrate: confDesiredBitrate, onStartCallback: function (m, n) { try { window.sc_smartIntxtStart(n); @@ -372,43 +365,15 @@ function createOutstreamConfig(bid) { }, }; - if (confStartOpen == 'true') { - smartPlayObj.startOpen = true; - } else if (confStartOpen == 'false') { - smartPlayObj.startOpen = false; - } - - if (confEndingScreen == 'true') { - smartPlayObj.endingScreen = true; - } else if (confEndingScreen == 'false') { - smartPlayObj.endingScreen = false; - } - - if (confTitle || (typeof bid.renderer.config.outstream_options.title == 'string' && bid.renderer.config.outstream_options.title == '')) { - smartPlayObj.title = confTitle; - } - - if (confSkipOffset) { - smartPlayObj.skipOffset = confSkipOffset; - } - - if (confDesiredBitrate) { - smartPlayObj.desiredBitrate = confDesiredBitrate; - } - - if (confVisibilityThreshold) { - smartPlayObj.visibilityThreshold = confVisibilityThreshold; - } - smartPlayObj.adResponse = bid.vastContent; const divID = '[id="' + elementId + '"]'; try { // eslint-disable-next-line - let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj); + let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj); } catch (e) { - logError('[SMARTX][renderer] Error caught: ' + e); + utils.logError('[SMARTX][renderer] Error caught: ' + e); } return smartPlayObj; } @@ -420,17 +385,17 @@ function createOutstreamConfig(bid) { * @returns {*|number} floor price */ function getBidFloor(bid) { - let floor = getBidIdParameter('bidfloor', bid.params); - let floorcur = getBidIdParameter('bidfloorcur', bid.params) || 'EUR'; + let floor = utils.getBidIdParameter('bidfloor', bid.params); + let floorcur = utils.getBidIdParameter('bidfloorcur', bid.params) || 'EUR'; - if (!floor && isFn(bid.getFloor)) { + if (!floor && utils.isFn(bid.getFloor)) { const floorObj = bid.getFloor({ currency: floorcur, mediaType: '*', size: '*' }); - if (isPlainObject(floorObj) && !isNaN(floorObj.floor) && floorObj.currency === floorcur) { + if (utils.isPlainObject(floorObj) && !isNaN(floorObj.floor) && floorObj.currency === floorcur) { floor = floorObj.floor; } } diff --git a/modules/smartxBidAdapter.md b/modules/smartxBidAdapter.md index 853f06d6baf..223e51763b9 100644 --- a/modules/smartxBidAdapter.md +++ b/modules/smartxBidAdapter.md @@ -38,8 +38,8 @@ This adapter requires setup and approval from the smartclip team. maxAdWidth: 900, title: '', skipOffset: 0, - startOpen: 'true', - endingScreen: 'true', + startOpen: true, + endingScreen: true, desiredBitrate: 800, }, } @@ -73,8 +73,8 @@ This adapter requires setup and approval from the smartclip team. maxAdWidth: 900, title: '', skipOffset: 0, - startOpen: 'true', - endingScreen: 'true', + startOpen: true, + endingScreen: true, desiredBitrate: 800, }, user: { diff --git a/modules/smartyadsBidAdapter.js b/modules/smartyadsBidAdapter.js index b999d02b059..610617155ed 100644 --- a/modules/smartyadsBidAdapter.js +++ b/modules/smartyadsBidAdapter.js @@ -1,11 +1,11 @@ -import { logMessage } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'smartyads'; -const AD_URL = 'https://n1.smartyads.com/?c=o&m=prebid&secret_key=prebid_js'; -const URL_SYNC = 'https://as.ck-ie.com/prebidjs?p=7c47322e527cf8bdeb7facc1bb03387a'; +const AD_URL = 'https://ssp-nj.webtradehub.com/?c=o&m=multi'; +const URL_SYNC = 'https://ssp-nj.webtradehub.com/?c=o&m=cookie'; function isBidResponseValid(bid) { if (!bid.requestId || !bid.cpm || !bid.creativeId || @@ -29,7 +29,7 @@ export const spec = { supportedMediaTypes: [BANNER, VIDEO, NATIVE], isBidRequestValid: (bid) => { - return Boolean(bid.bidId && bid.params && !isNaN(bid.params.sourceid) && !isNaN(bid.params.accountid) && bid.params.host == 'prebid'); + return Boolean(bid.bidId && bid.params && !isNaN(bid.params.placementId)); }, buildRequests: (validBidRequests = [], bidderRequest) => { @@ -40,7 +40,7 @@ export const spec = { winTop = window.top; } catch (e) { location = winTop.location; - logMessage(e); + utils.logMessage(e); }; let placements = []; let request = { @@ -68,11 +68,10 @@ export const spec = { let bid = validBidRequests[i]; let traff = bid.params.traffic || BANNER placements.push({ - placementId: bid.params.sourceid, + placementId: bid.params.placementId, bidId: bid.bidId, sizes: bid.mediaTypes && bid.mediaTypes[traff] && bid.mediaTypes[traff].sizes ? bid.mediaTypes[traff].sizes : [], - traffic: traff, - publisherId: bid.params.accountid + traffic: traff }); if (bid.schain) { placements.schain = bid.schain; @@ -97,23 +96,11 @@ export const spec = { return response; }, - getUserSyncs: (syncOptions, serverResponses = [], gdprConsent = {}, uspConsent = '') => { - let syncs = []; - let { gdprApplies, consentString = '' } = gdprConsent; - - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: `${URL_SYNC}&gdpr=${gdprApplies ? 1 : 0}&gdpr_consent=${consentString}&type=iframe&us_privacy=${uspConsent}` - }); - } else { - syncs.push({ - type: 'image', - url: `${URL_SYNC}&gdpr=${gdprApplies ? 1 : 0}&gdpr_consent=${consentString}&type=image&us_privacy=${uspConsent}` - }); - } - - return syncs + getUserSyncs: (syncOptions, serverResponses) => { + return [{ + type: 'image', + url: URL_SYNC + }]; } }; diff --git a/modules/smartyadsBidAdapter.md b/modules/smartyadsBidAdapter.md index f078d905e62..4fe4d51a2e6 100644 --- a/modules/smartyadsBidAdapter.md +++ b/modules/smartyadsBidAdapter.md @@ -23,9 +23,7 @@ Module that connects to SmartyAds' demand sources { bidder: 'smartyads', params: { - host: 'prebid', - sourceid: '0', - accountid: '0', + placementId: 0, traffic: 'native' } } @@ -43,9 +41,7 @@ Module that connects to SmartyAds' demand sources { bidder: 'smartyads', params: { - host: 'prebid', - sourceid: '0', - accountid: '0', + placementId: 0, traffic: 'banner' } } @@ -64,9 +60,7 @@ Module that connects to SmartyAds' demand sources { bidder: 'smartyads', params: { - host: 'prebid', - sourceid: '0', - accountid: '0', + placementId: 0, traffic: 'video' } } diff --git a/modules/smilewantedBidAdapter.js b/modules/smilewantedBidAdapter.js index 73bd6101670..65f166566fe 100644 --- a/modules/smilewantedBidAdapter.js +++ b/modules/smilewantedBidAdapter.js @@ -1,4 +1,4 @@ -import { isArray, logError, logWarn, isFn, isPlainObject } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { Renderer } from '../src/Renderer.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; @@ -108,13 +108,13 @@ export const spec = { } bidResponse.meta = {}; - if (response.meta && response.meta.advertiserDomains && isArray(response.meta.advertiserDomains)) { + if (response.meta && response.meta.advertiserDomains && utils.isArray(response.meta.advertiserDomains)) { bidResponse.meta.advertiserDomains = response.meta.advertiserDomains; } bidResponses.push(bidResponse); } } catch (error) { - logError('Error while parsing smilewanted response', error); + utils.logError('Error while parsing smilewanted response', error); } return bidResponses; }, @@ -170,7 +170,7 @@ function newRenderer(bidRequest, bidResponse) { try { renderer.setRender(outstreamRender); } catch (err) { - logWarn('Prebid Error calling setRender on newRenderer', err); + utils.logWarn('Prebid Error calling setRender on newRenderer', err); } return renderer; } @@ -197,13 +197,13 @@ function outstreamRender(bid) { * @returns {*|number} floor price */ function getBidFloor(bid) { - if (isFn(bid.getFloor)) { + if (utils.isFn(bid.getFloor)) { const floorInfo = bid.getFloor({ currency: 'USD', mediaType: 'banner', size: bid.sizes.map(size => ({ w: size[0], h: size[1] })) }); - if (isPlainObject(floorInfo) && !isNaN(floorInfo.floor) && floorInfo.currency === 'USD') { + if (utils.isPlainObject(floorInfo) && !isNaN(floorInfo.floor) && floorInfo.currency === 'USD') { return parseFloat(floorInfo.floor); } } diff --git a/modules/sonobiAnalyticsAdapter.js b/modules/sonobiAnalyticsAdapter.js index 0de6647149a..d69276e915c 100644 --- a/modules/sonobiAnalyticsAdapter.js +++ b/modules/sonobiAnalyticsAdapter.js @@ -1,9 +1,9 @@ -import { deepClone, logInfo, logError } from '../src/utils.js'; import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; import {ajaxBuilder} from '../src/ajax.js'; +const utils = require('../src/utils.js'); let ajax = ajaxBuilder(0); const DEFAULT_EVENT_URL = 'apex.go.sonobi.com/keymaker'; @@ -91,7 +91,7 @@ function addToAuctionQueue(auctionId, id) { if (item.bidid !== id) { return true; } return auction.stats[id].data.p !== item.p; }); - auction.queue.push(deepClone(auction.stats[id].data)); + auction.queue.push(utils.deepClone(auction.stats[id].data)); if (!auction.qTimeout) { auction.qTimeout = setTimeout(() => { sendQueue(auctionId); @@ -102,18 +102,18 @@ function updateBidStats(auctionId, id, data) { let auction = auctionCache[auctionId]; auction.stats[id].data = {...auction.stats[id].data, ...data}; addToAuctionQueue(auctionId, id); - _logInfo('Updated Bid Stats: ', auction.stats[id]); + logInfo('Updated Bid Stats: ', auction.stats[id]); return auction.stats[id]; } function handleOtherEvents(eventType, args) { - _logInfo('Other Event: ' + eventType, args); + logInfo('Other Event: ' + eventType, args); } function handlerAuctionInit(args) { auctionCache[args.auctionId] = buildAuctionEntity(args); deleteOldAuctions(); - _logInfo('Auction Init', args); + logInfo('Auction Init', args); } function handlerBidRequested(args) { let auction = auctionCache[args.auctionId]; @@ -127,14 +127,14 @@ function handlerBidRequested(args) { addToAuctionQueue(args.auctionId, built.bidid); }) - _logInfo('Bids Requested ', data); + logInfo('Bids Requested ', data); } function handlerBidAdjustment(args) { - _logInfo('Bid Adjustment', args); + logInfo('Bid Adjustment', args); } function handlerBidderDone(args) { - _logInfo('Bidder Done', args); + logInfo('Bidder Done', args); } function handlerAuctionEnd(args) { @@ -152,24 +152,24 @@ function handlerAuctionEnd(args) { updateBidStats(args.auctionId, bidId, {response: 4}); } }) - _logInfo('Auction End', args); - _logInfo('Auction Cache', auctionCache[args.auctionId].stats); + logInfo('Auction End', args); + logInfo('Auction Cache', auctionCache[args.auctionId].stats); } function handlerBidWon(args) { let {auctionId, requestId} = args; let res = updateBidStats(auctionId, requestId, {p: 3, response: 6}); - _logInfo('Bid Won ', args); - _logInfo('Bid Update Result: ', res); + logInfo('Bid Won ', args); + logInfo('Bid Update Result: ', res); } function handlerBidResponse(args) { let {auctionId, requestId, cpm, size, timeToRespond} = args; updateBidStats(auctionId, requestId, {bid: cpm, s: size, jsLatency: timeToRespond, latency: timeToRespond, p: 2, response: 9}); - _logInfo('Bid Response ', args); + logInfo('Bid Response ', args); } function handlerBidTimeout(args) { let {auctionId, bidId} = args; - _logInfo('Bid Timeout ', args); + logInfo('Bid Timeout ', args); updateBidStats(auctionId, bidId, {p: 2, response: 0, latency: args.timeout, jsLatency: args.timeout}); } let sonobiAdapter = Object.assign(adapter({url: DEFAULT_EVENT_URL, analyticsType}), { @@ -211,7 +211,7 @@ sonobiAdapter.originEnableAnalytics = sonobiAdapter.enableAnalytics; sonobiAdapter.enableAnalytics = function (config) { if (this.initConfig(config)) { - _logInfo('Analytics adapter enabled', initOptions); + logInfo('Analytics adapter enabled', initOptions); sonobiAdapter.originEnableAnalytics(config); } }; @@ -219,17 +219,17 @@ sonobiAdapter.enableAnalytics = function (config) { sonobiAdapter.initConfig = function (config) { let isCorrectConfig = true; initOptions = {}; - initOptions.options = deepClone(config.options); + initOptions.options = utils.deepClone(config.options); initOptions.pubId = initOptions.options.pubId || null; initOptions.siteId = initOptions.options.siteId || null; initOptions.delay = initOptions.options.delay || QUEUE_TIMEOUT_DEFAULT; if (!initOptions.pubId) { - _logError('"options.pubId" is empty'); + logError('"options.pubId" is empty'); isCorrectConfig = false; } if (!initOptions.siteId) { - _logError('"options.siteId" is empty'); + logError('"options.siteId" is empty'); isCorrectConfig = false; } @@ -247,7 +247,7 @@ sonobiAdapter.sendData = function (auction, data) { let url = 'https://' + initOptions.server + '?pageviewid=' + auction.id + '&corscred=1&pubId=' + initOptions.pubId + '&siteId=' + initOptions.siteId; ajax( url, - function () { _logInfo('Auction [' + auction.id + '] sent ', data); }, + function () { logInfo('Auction [' + auction.id + '] sent ', data); }, JSON.stringify(data), { method: 'POST', @@ -257,12 +257,12 @@ sonobiAdapter.sendData = function (auction, data) { ); } -function _logInfo(message, meta) { - logInfo(buildLogMessage(message), meta); +function logInfo(message, meta) { + utils.logInfo(buildLogMessage(message), meta); } -function _logError(message) { - logError(buildLogMessage(message)); +function logError(message) { + utils.logError(buildLogMessage(message)); } function buildLogMessage(message) { diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index c5fc07320d8..2edcdca1a51 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -83,15 +83,8 @@ export const spec = { 'lib_name': 'prebid', 'lib_v': '$prebid.version$', 'us': 0, - }; - const fpd = config.getConfig('ortb2'); - - if (fpd) { - payload.fpd = JSON.stringify(fpd); - } - if (config.getConfig('userSync') && config.getConfig('userSync').syncsPerBidder) { payload.us = config.getConfig('userSync').syncsPerBidder; } @@ -237,7 +230,6 @@ export const spec = { delete bids.width; delete bids.height; } else if (mediaType === 'outstream' && bidRequest) { - delete bids.ad; // Some pubs expect bids.ad to be a vast xml structure, we have a vatUrl so lets delete this. bids.mediaType = 'video'; bids.vastUrl = createCreative(bidResponse.sbi_dc, bid.sbi_aid); bids.renderer = newRenderer(bidRequest.adUnitCode, bids, deepAccess( diff --git a/modules/sortableAnalyticsAdapter.js b/modules/sortableAnalyticsAdapter.js index 4580ce6dbb8..73ce1393c23 100644 --- a/modules/sortableAnalyticsAdapter.js +++ b/modules/sortableAnalyticsAdapter.js @@ -1,11 +1,10 @@ -import { logInfo, getParameterByName, getOldestHighestCpmBid } from '../src/utils.js'; import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; +import * as utils from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import {getGlobal} from '../src/prebidGlobal.js'; import { config } from '../src/config.js'; -import {bidderSettings} from '../src/bidderSettings.js'; const DEFAULT_PROTOCOL = 'https'; const DEFAULT_HOST = 'pa.deployads.com'; @@ -161,7 +160,7 @@ function getSessionParams() { sessionParams = paramsFromStorage && stillValid(paramsFromStorage) ? paramsFromStorage : null; } sessionParams = sessionParams || {'created': +new Date(), 'sessionId': generateRandomId()}; - const urlParams = UTM_PARAMS.map(getParameterByName); + const urlParams = UTM_PARAMS.map(utils.getParameterByName); if (UTM_PARAMS.every(key => !sessionParams[key])) { UTM_PARAMS.forEach((v, i) => sessionParams[v] = urlParams[i] || sessionParams[v]); sessionParams.created = +new Date(); @@ -183,11 +182,11 @@ function getFactor(bidder) { } function getBiddersFactors() { + const pb = getGlobal(); const result = {}; - const settings = bidderSettings.getSettings(); - if (settings) { - Object.keys(settings).forEach(bidderKey => { - const bidder = settings[bidderKey]; + if (pb && pb.bidderSettings) { + Object.keys(pb.bidderSettings).forEach(bidderKey => { + const bidder = pb.bidderSettings[bidderKey]; const factor = getFactor(bidder); if (factor !== null) { result[bidderKey] = factor; @@ -319,7 +318,7 @@ function sendEvents(events) { 'method': 'POST', 'withCredentials': true }; - const onSend = () => logInfo('Sortable Analytics data sent'); + const onSend = () => utils.logInfo('Sortable Analytics data sent'); ajax(url, onSend, JSON.stringify(mergedEvents), options); } @@ -445,7 +444,7 @@ function handleAuctionEnd(event) { const events = Object.keys(adUnits).map(adUnitCode => { const bidderKeys = Object.keys(auction.adUnits[adUnitCode].bids); const bids = bidderKeys.map(bidderCode => auction.adUnits[adUnitCode].bids[bidderCode]); - const highestBid = bids.length ? bids.reduce(getOldestHighestCpmBid) : null; + const highestBid = bids.length ? bids.reduce(utils.getOldestHighestCpmBid) : null; return bidderKeys.map(bidderCode => { const bid = auction.adUnits[adUnitCode].bids[bidderCode]; if (highestBid && highestBid.cpm) { @@ -508,7 +507,7 @@ sortableAnalyticsAdapter.originEnableAnalytics = sortableAnalyticsAdapter.enable sortableAnalyticsAdapter.enableAnalytics = function (setupConfig) { if (this.initConfig(setupConfig)) { - logInfo('Sortable Analytics adapter enabled'); + utils.logInfo('Sortable Analytics adapter enabled'); sortableAnalyticsAdapter.originEnableAnalytics(setupConfig); } }; diff --git a/modules/sortableBidAdapter.js b/modules/sortableBidAdapter.js index 15246a10eab..906369eccc3 100644 --- a/modules/sortableBidAdapter.js +++ b/modules/sortableBidAdapter.js @@ -1,4 +1,4 @@ -import { _each, logError, isFn, isPlainObject, isNumber, isStr, deepAccess, parseUrl, _map, getUniqueIdentifierStr, createTrackPixelHtml } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; @@ -55,7 +55,7 @@ function buildNativeRequest(nativeMediaType) { assets.push(setAssetRequired(sponsoredBy, {data: {type: 1}})); } - _each(assets, (asset, id) => asset.id = id); + utils._each(assets, (asset, id) => asset.id = id); return { ver: '1', request: JSON.stringify({ @@ -70,7 +70,7 @@ function tryParseNativeResponse(adm) { try { native = JSON.parse(adm); } catch (e) { - logError('Sortable bid adapter unable to parse native bid response:\n\n' + e); + utils.logError('Sortable bid adapter unable to parse native bid response:\n\n' + e); } return native && native.native; } @@ -92,7 +92,7 @@ function interpretNativeResponse(response) { if (response.link) { native.clickUrl = response.link.url; } - _each(response.assets, asset => { + utils._each(response.assets, asset => { switch (asset.id) { case 1: native.title = asset.title.text; @@ -118,9 +118,9 @@ function interpretNativeResponse(response) { } function transformSyncs(responses, type, syncs) { - _each(responses, res => { + utils._each(responses, res => { if (res.body && res.body.ext && res.body.ext.sync_dsps && res.body.ext.sync_dsps.length) { - _each(res.body.ext.sync_dsps, sync => { + utils._each(res.body.ext.sync_dsps, sync => { if (sync[0] === type && sync[1]) { syncs.push({type, url: sync[1]}); } @@ -130,7 +130,7 @@ function transformSyncs(responses, type, syncs) { } function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { + if (!utils.isFn(bid.getFloor)) { return bid.params.floor ? bid.params.floor : null; } @@ -141,7 +141,7 @@ function getBidFloor(bid) { mediaType: '*', size: '*' }); - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { + if (utils.isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { return floor.floor; } return null; @@ -155,36 +155,36 @@ export const spec = { const sortableConfig = config.getConfig('sortable'); const haveSiteId = (sortableConfig && !!sortableConfig.siteId) || bid.params.siteId; const floor = getBidFloor(bid); - const validFloor = !floor || isNumber(floor); + const validFloor = !floor || utils.isNumber(floor); const validKeywords = !bid.params.keywords || - (isPlainObject(bid.params.keywords) && + (utils.isPlainObject(bid.params.keywords) && Object.keys(bid.params.keywords).every(key => - isStr(key) && isStr(bid.params.keywords[key]) + utils.isStr(key) && utils.isStr(bid.params.keywords[key]) )) const isBanner = !bid.mediaTypes || bid.mediaTypes[BANNER] || !(bid.mediaTypes[NATIVE] || bid.mediaTypes[VIDEO]); - const bannerSizes = isBanner ? deepAccess(bid, `mediaType.${BANNER}.sizes`) || bid.sizes : null; + const bannerSizes = isBanner ? utils.deepAccess(bid, `mediaType.${BANNER}.sizes`) || bid.sizes : null; return !!(bid.params.tagId && haveSiteId && validFloor && validKeywords && (!isBanner || - (bannerSizes && bannerSizes.length > 0 && bannerSizes.every(sizeArr => sizeArr.length == 2 && sizeArr.every(num => isNumber(num)))))); + (bannerSizes && bannerSizes.length > 0 && bannerSizes.every(sizeArr => sizeArr.length == 2 && sizeArr.every(num => utils.isNumber(num)))))); }, buildRequests: function(validBidReqs, bidderRequest) { const sortableConfig = config.getConfig('sortable') || {}; const globalSiteId = sortableConfig.siteId; - let loc = parseUrl(bidderRequest.refererInfo.referer); + let loc = utils.parseUrl(bidderRequest.refererInfo.referer); - const sortableImps = _map(validBidReqs, bid => { + const sortableImps = utils._map(validBidReqs, bid => { const rv = { id: bid.bidId, tagid: bid.params.tagId, ext: {} }; - const bannerMediaType = deepAccess(bid, `mediaTypes.${BANNER}`); - const nativeMediaType = deepAccess(bid, `mediaTypes.${NATIVE}`); - const videoMediaType = deepAccess(bid, `mediaTypes.${VIDEO}`); + const bannerMediaType = utils.deepAccess(bid, `mediaTypes.${BANNER}`); + const nativeMediaType = utils.deepAccess(bid, `mediaTypes.${NATIVE}`); + const videoMediaType = utils.deepAccess(bid, `mediaTypes.${VIDEO}`); if (bannerMediaType || !(nativeMediaType || videoMediaType)) { const bannerSizes = (bannerMediaType && bannerMediaType.sizes) || bid.sizes; rv.banner = { - format: _map(bannerSizes, ([width, height]) => ({w: width, h: height})) + format: utils._map(bannerSizes, ([width, height]) => ({w: width, h: height})) }; } if (nativeMediaType) { @@ -193,9 +193,9 @@ export const spec = { if (videoMediaType && videoMediaType.context === 'instream') { const video = {placement: 1}; video.mimes = videoMediaType.mimes || []; - video.minduration = deepAccess(bid, 'params.video.minduration') || 10; - video.maxduration = deepAccess(bid, 'params.video.maxduration') || 60; - const startDelay = deepAccess(bid, 'params.video.startdelay'); + video.minduration = utils.deepAccess(bid, 'params.video.minduration') || 10; + video.maxduration = utils.deepAccess(bid, 'params.video.maxduration') || 60; + const startDelay = utils.deepAccess(bid, 'params.video.startdelay'); if (startDelay != null) { video.startdelay = startDelay; } @@ -223,18 +223,17 @@ export const spec = { rv.ext.keywords = bid.params.keywords; } if (bid.params.bidderParams) { - _each(bid.params.bidderParams, (params, partner) => { + utils._each(bid.params.bidderParams, (params, partner) => { rv.ext[partner] = params; }); } - rv.ext.gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); return rv; }); const gdprConsent = bidderRequest && bidderRequest.gdprConsent; const bidUserId = validBidReqs[0].userId; const eids = createEidsArray(bidUserId); const sortableBidReq = { - id: getUniqueIdentifierStr(), + id: utils.getUniqueIdentifierStr(), imp: sortableImps, source: { ext: { @@ -291,8 +290,8 @@ export const spec = { const { body: {id, seatbid} } = serverResponse; const sortableBids = []; if (id && seatbid) { - _each(seatbid, seatbid => { - _each(seatbid.bid, bid => { + utils._each(seatbid, seatbid => { + utils._each(seatbid.bid, bid => { const bidObj = { requestId: bid.impid, cpm: parseFloat(bid.price), @@ -309,7 +308,7 @@ export const spec = { } }; if (bid.adm) { - const adFormat = deepAccess(bid, 'ext.ad_format') + const adFormat = utils.deepAccess(bid, 'ext.ad_format') if (adFormat === 'native') { let native = tryParseNativeResponse(bid.adm); if (!native) { @@ -324,7 +323,7 @@ export const spec = { bidObj.mediaType = BANNER; bidObj.ad = bid.adm; if (bid.nurl) { - bidObj.ad += createTrackPixelHtml(decodeURIComponent(bid.nurl)); + bidObj.ad += utils.createTrackPixelHtml(decodeURIComponent(bid.nurl)); } } } else if (bid.nurl) { diff --git a/modules/sovrnAnalyticsAdapter.js b/modules/sovrnAnalyticsAdapter.js index 065cfaa58bc..0d2576edb05 100644 --- a/modules/sovrnAnalyticsAdapter.js +++ b/modules/sovrnAnalyticsAdapter.js @@ -1,10 +1,11 @@ -import {logError, timestamp} from '../src/utils.js'; -import adapter from '../src/AnalyticsAdapter.js'; -import adaptermanager from '../src/adapterManager.js'; -import CONSTANTS from '../src/constants.json'; -import {ajaxBuilder} from '../src/ajax.js'; -import {config} from '../src/config.js'; -import {find, includes} from '../src/polyfill.js'; +import adapter from '../src/AnalyticsAdapter.js' +import adaptermanager from '../src/adapterManager.js' +import CONSTANTS from '../src/constants.json' +import {ajaxBuilder} from '../src/ajax.js' +import * as utils from '../src/utils.js' +import {config} from '../src/config.js' +import find from 'core-js-pure/features/array/find.js' +import includes from 'core-js-pure/features/array/includes.js' const ajax = ajaxBuilder(0) @@ -111,7 +112,7 @@ sovrnAnalyticsAdapter.enableAnalytics = function (config) { if (config && config.options && (config.options.sovrnId || config.options.affiliateId)) { sovrnId = config.options.sovrnId || config.options.affiliateId; } else { - logError('Need Sovrn Id to log auction results. Please contact a Sovrn representative if you do not know your Sovrn Id.') + utils.logError('Need Sovrn Id to log auction results. Please contact a Sovrn representative if you do not know your Sovrn Id.') return } sovrnAnalyticsAdapter.sovrnId = sovrnId; @@ -148,7 +149,7 @@ class BidWinner { * Sends the auction to the the ingest server */ send() { - this.body.ts = timestamp() + this.body.ts = utils.timestamp() ajax( pbaUrl, null, @@ -268,7 +269,7 @@ class AuctionData { Object.keys(maxBids).forEach(unit => { maxBids[unit].isAuctionWinner = true }) - this.auction.ts = timestamp() + this.auction.ts = utils.timestamp() ajax( pbaUrl, () => { @@ -310,7 +311,7 @@ class LogError { if (ErrorEvent.data && this.error.data.ad) { delete this.error.data.ad } - this.error.ts = timestamp() + this.error.ts = utils.timestamp() ajax( pbaUrl, null, diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index eed9ccb7461..cba90e7d434 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -1,46 +1,12 @@ -import { _each, getBidIdParameter, isArray, deepClone, parseUrl, getUniqueIdentifierStr, deepSetValue, logError, deepAccess, isInteger, logWarn } from '../src/utils.js'; +import * as utils from '../src/utils.js' import { registerBidder } from '../src/adapters/bidderFactory.js' -import { ADPOD, BANNER, VIDEO } from '../src/mediaTypes.js' -import { createEidsArray } from './userId/eids.js' -import {config} from '../src/config.js' - -const ORTB_VIDEO_PARAMS = { - 'mimes': (value) => Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string'), - 'minduration': (value) => isInteger(value), - 'maxduration': (value) => isInteger(value), - 'protocols': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 10), - 'w': (value) => isInteger(value), - 'h': (value) => isInteger(value), - 'startdelay': (value) => isInteger(value), - 'placement': (value) => isInteger(value) && value >= 1 && value <= 5, - 'linearity': (value) => [1, 2].indexOf(value) !== -1, - 'skip': (value) => [0, 1].indexOf(value) !== -1, - 'skipmin': (value) => isInteger(value), - 'skipafter': (value) => isInteger(value), - 'sequence': (value) => isInteger(value), - 'battr': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 17), - 'maxextended': (value) => isInteger(value), - 'minbitrate': (value) => isInteger(value), - 'maxbitrate': (value) => isInteger(value), - 'boxingallowed': (value) => [0, 1].indexOf(value) !== -1, - 'playbackmethod': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6), - 'playbackend': (value) => [1, 2, 3].indexOf(value) !== -1, - 'delivery': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 3), - 'pos': (value) => isInteger(value) && value >= 1 && value <= 7, - 'api': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6) -} - -const REQUIRED_VIDEO_PARAMS = { - context: (value) => value !== ADPOD, - mimes: ORTB_VIDEO_PARAMS.mimes, - minduration: ORTB_VIDEO_PARAMS.minduration, - maxduration: ORTB_VIDEO_PARAMS.maxduration, - protocols: ORTB_VIDEO_PARAMS.protocols -} +import { BANNER } from '../src/mediaTypes.js' +import { createEidsArray } from './userId/eids.js'; +import {config} from '../src/config.js'; export const spec = { code: 'sovrn', - supportedMediaTypes: [BANNER, VIDEO], + supportedMediaTypes: [BANNER], gvlid: 13, /** @@ -48,25 +14,14 @@ export const spec = { * @param {object} bid the Sovrn bid to validate * @return boolean for whether or not a bid is valid */ - isBidRequestValid: function (bid) { - const video = bid?.mediaTypes?.video - return !!( - bid.params.tagid && - !isNaN(parseFloat(bid.params.tagid)) && - isFinite(bid.params.tagid) && ( - !video || ( - Object.keys(REQUIRED_VIDEO_PARAMS) - .every(key => REQUIRED_VIDEO_PARAMS[key](video[key])) - ) - ) - ) + isBidRequestValid: function(bid) { + return !!(bid.params.tagid && !isNaN(parseFloat(bid.params.tagid)) && isFinite(bid.params.tagid)) }, /** * Format the bid request object for our endpoint + * @param {BidRequest[]} bidRequests Array of Sovrn bidders * @return object of parameters for Prebid AJAX request - * @param bidReqs - * @param bidderRequest */ buildRequests: function(bidReqs, bidderRequest) { try { @@ -77,7 +32,7 @@ export const spec = { let tpid = [] let criteoId; - _each(bidReqs, function (bid) { + utils._each(bidReqs, function (bid) { if (!eids && bid.userId) { eids = createEidsArray(bid.userId) eids.forEach(function (id) { @@ -93,41 +48,34 @@ export const spec = { if (bid.schain) { schain = schain || bid.schain } - iv = iv || getBidIdParameter('iv', bid.params) + iv = iv || utils.getBidIdParameter('iv', bid.params) + let bidSizes = (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) || bid.sizes + bidSizes = ((utils.isArray(bidSizes) && utils.isArray(bidSizes[0])) ? bidSizes : [bidSizes]) + bidSizes = bidSizes.filter(size => utils.isArray(size)) + const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) const floorInfo = (bid.getFloor && typeof bid.getFloor === 'function') ? bid.getFloor({ currency: 'USD', - mediaType: bid.mediaTypes && bid.mediaTypes.banner ? 'banner' : 'video', + mediaType: 'banner', size: '*' }) : {} - floorInfo.floor = floorInfo.floor || getBidIdParameter('bidfloor', bid.params) + floorInfo.floor = floorInfo.floor || utils.getBidIdParameter('bidfloor', bid.params) const imp = { adunitcode: bid.adUnitCode, id: bid.bidId, - tagid: String(getBidIdParameter('tagid', bid.params)), - bidfloor: floorInfo.floor - } - - if (deepAccess(bid, 'mediaTypes.banner')) { - let bidSizes = deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes - bidSizes = (isArray(bidSizes) && isArray(bidSizes[0])) ? bidSizes : [bidSizes] - bidSizes = bidSizes.filter(size => isArray(size)) - const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) - - imp.banner = { + banner: { format: processedSizes, w: 1, h: 1, - }; - } - if (deepAccess(bid, 'mediaTypes.video')) { - imp.video = _buildVideoRequestObj(bid); + }, + tagid: String(utils.getBidIdParameter('tagid', bid.params)), + bidfloor: floorInfo.floor } - imp.ext = getBidIdParameter('ext', bid.ortb2Imp) || undefined + imp.ext = utils.getBidIdParameter('ext', bid.ortb2Imp) || undefined - const segmentsString = getBidIdParameter('segments', bid.params) + const segmentsString = utils.getBidIdParameter('segments', bid.params) if (segmentsString) { imp.ext = imp.ext || {} imp.ext.deals = segmentsString.split(',').map(deal => deal.trim()) @@ -135,15 +83,15 @@ export const spec = { sovrnImps.push(imp) }) - const fpd = deepClone(config.getConfig('ortb2')) + const fpd = config.getConfig('ortb2') || {} const site = fpd.site || {} site.page = bidderRequest.refererInfo.referer // clever trick to get the domain - site.domain = parseUrl(site.page).hostname + site.domain = utils.parseUrl(site.page).hostname const sovrnBidReq = { - id: getUniqueIdentifierStr(), + id: utils.getUniqueIdentifierStr(), imp: sovrnImps, site: site, user: fpd.user || {} @@ -158,18 +106,18 @@ export const spec = { } if (bidderRequest.gdprConsent) { - deepSetValue(sovrnBidReq, 'regs.ext.gdpr', +bidderRequest.gdprConsent.gdprApplies); - deepSetValue(sovrnBidReq, 'user.ext.consent', bidderRequest.gdprConsent.consentString) + utils.deepSetValue(sovrnBidReq, 'regs.ext.gdpr', +bidderRequest.gdprConsent.gdprApplies); + utils.deepSetValue(sovrnBidReq, 'user.ext.consent', bidderRequest.gdprConsent.consentString) } if (bidderRequest.uspConsent) { - deepSetValue(sovrnBidReq, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(sovrnBidReq, 'regs.ext.us_privacy', bidderRequest.uspConsent); } if (eids) { - deepSetValue(sovrnBidReq, 'user.ext.eids', eids) - deepSetValue(sovrnBidReq, 'user.ext.tpid', tpid) + utils.deepSetValue(sovrnBidReq, 'user.ext.eids', eids) + utils.deepSetValue(sovrnBidReq, 'user.ext.tpid', tpid) if (criteoId) { - deepSetValue(sovrnBidReq, 'user.ext.prebid_criteoid', criteoId) + utils.deepSetValue(sovrnBidReq, 'user.ext.prebid_criteoid', criteoId) } } @@ -183,7 +131,7 @@ export const spec = { options: {contentType: 'text/plain'} } } catch (e) { - logError('Could not build bidrequest, error deatils:', e); + utils.logError('Could not build bidrequest, error deatils:', e); } }, @@ -193,13 +141,15 @@ export const spec = { * @return {Bid[]} An array of formatted bids. */ interpretResponse: function({ body: {id, seatbid} }) { - if (!id || !seatbid || !Array.isArray(seatbid)) return [] - try { - return seatbid - .filter(seat => seat) - .map(seat => seat.bid.map(sovrnBid => { - const bid = { + let sovrnBidResponses = []; + if (id && + seatbid && + seatbid.length > 0 && + seatbid[0].bid && + seatbid[0].bid.length > 0) { + seatbid[0].bid.map(sovrnBid => { + sovrnBidResponses.push({ requestId: sovrnBid.impid, cpm: parseFloat(sovrnBid.price), width: parseInt(sovrnBid.w), @@ -208,23 +158,16 @@ export const spec = { dealId: sovrnBid.dealid || null, currency: 'USD', netRevenue: true, - mediaType: sovrnBid.nurl ? BANNER : VIDEO, - ttl: sovrnBid.ext?.ttl || 90, + mediaType: BANNER, + ad: decodeURIComponent(`${sovrnBid.adm}`), + ttl: sovrnBid.ext ? (sovrnBid.ext.ttl || 90) : 90, meta: { advertiserDomains: sovrnBid && sovrnBid.adomain ? sovrnBid.adomain : [] } - } - - if (sovrnBid.nurl) { - bid.ad = decodeURIComponent(`${sovrnBid.adm}`) - } else { - bid.vastXml = decodeURIComponent(sovrnBid.adm) - } - - return bid - })) - .flat() + }); + }); + } + return sovrnBidResponses } catch (e) { - logError('Could not interpret bidresponse, error details:', e) - return e + utils.logError('Could not intrepret bidresponse, error deatils:', e); } }, @@ -233,7 +176,7 @@ export const spec = { const tracks = [] if (serverResponses && serverResponses.length !== 0) { if (syncOptions.iframeEnabled) { - const iidArr = serverResponses.filter(resp => deepAccess(resp, 'body.ext.iid')) + const iidArr = serverResponses.filter(resp => utils.deepAccess(resp, 'body.ext.iid')) .map(resp => resp.body.ext.iid); const params = []; if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { @@ -253,7 +196,7 @@ export const spec = { } if (syncOptions.pixelEnabled) { - serverResponses.filter(resp => deepAccess(resp, 'body.ext.sync.pixels')) + serverResponses.filter(resp => utils.deepAccess(resp, 'body.ext.sync.pixels')) .reduce((acc, resp) => acc.concat(resp.body.ext.sync.pixels), []) .map(pixel => pixel.url) .forEach(url => tracks.push({ type: 'image', url })) @@ -266,34 +209,4 @@ export const spec = { }, } -function _buildVideoRequestObj(bid) { - const videoObj = {} - const videoAdUnitParams = deepAccess(bid, 'mediaTypes.video', {}) - const videoBidderParams = deepAccess(bid, 'params.video', {}) - const computedParams = {} - - if (Array.isArray(videoAdUnitParams.playerSize)) { - const sizes = (Array.isArray(videoAdUnitParams.playerSize[0])) ? videoAdUnitParams.playerSize[0] : videoAdUnitParams.playerSize - computedParams.w = sizes[0] - computedParams.h = sizes[1] - } - - const videoParams = { - ...computedParams, - ...videoAdUnitParams, - ...videoBidderParams - }; - - Object.keys(ORTB_VIDEO_PARAMS).forEach(paramName => { - if (videoParams.hasOwnProperty(paramName)) { - if (ORTB_VIDEO_PARAMS[paramName](videoParams[paramName])) { - videoObj[paramName] = videoParams[paramName] - } else { - logWarn(`The OpenRTB video param ${paramName} has been skipped due to misformating. Please refer to OpenRTB 2.5 spec.`); - } - } - }) - return videoObj -} - -registerBidder(spec) +registerBidder(spec); diff --git a/modules/sovrnBidAdapter.md b/modules/sovrnBidAdapter.md index 53e3158024d..2b5d21d5515 100644 --- a/modules/sovrnBidAdapter.md +++ b/modules/sovrnBidAdapter.md @@ -10,9 +10,9 @@ Maintainer: jrosendahl@sovrn.com Sovrn's adapter integration to the Prebid library. Posts plain-text JSON to the /rtb/bid endpoint. -# Banner Test Parameters +# Test Parameters -```js +``` var adUnits = [ { code: 'test-leaderboard', @@ -45,81 +45,3 @@ var adUnits = [ } ] ``` - -# Video Test Parameters -### Instream -```js -var videoAdUnit = { - code: 'video1', - sizes: [640, 480], - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1, - }, - }, - bids: [ - { - bidder: 'sovrn', - // Prebid Server Bidder Params https://docs.prebid.org/dev-docs/pbs-bidders.html#sovrn - params: { - tagid: '315045', - bidfloor: '0.04', - }, - }, - ], -} -``` -### Outstream -```js -var adUnits = [ - { - code: videoId, - mediaTypes: { - video: { - context: 'outstream', - playerSize: [640, 360], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1, - }, - }, - bids: [ - { - bidder: 'sovrn', - // Prebid Server Bidder Params https://docs.prebid.org/dev-docs/pbs-bidders.html#sovrn - params: { - tagid: '315045', - bidfloor: '0.04', - }, - }, - ], - renderer: { - url: 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js', - render: function (bid) { - adResponse = { - ad: { - video: { - content: bid.vastXml, - player_height: bid.height, - player_width: bid.width, - }, - }, - } - // push to render queue because ANOutstreamVideo may not be loaded yet. - bid.renderer.push(() => { - ANOutstreamVideo.renderAd({ - targetId: bid.adUnitCode, - adResponse: adResponse, - }) - }) - }, - }, - }, -] -``` diff --git a/modules/spotxBidAdapter.js b/modules/spotxBidAdapter.js index 2fd403058d1..e18c0d3ba3e 100644 --- a/modules/spotxBidAdapter.js +++ b/modules/spotxBidAdapter.js @@ -1,4 +1,4 @@ -import { logError, deepAccess, isArray, getBidIdParameter, getDNT, deepSetValue, isEmpty, _each, logMessage, logWarn, isBoolean, isNumber, isPlainObject, isFn } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { Renderer } from '../src/Renderer.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; @@ -11,7 +11,8 @@ export const GOOGLE_CONSENT = { consented_providers: ['3', '7', '11', '12', '15' export const spec = { code: BIDDER_CODE, - gvlid: 52, + gvlid: 165, + aliases: ['spotx'], supportedMediaTypes: [VIDEO], /** @@ -23,34 +24,34 @@ export const spec = { */ isBidRequestValid: function(bid) { if (bid && typeof bid.params !== 'object') { - logError(BIDDER_CODE + ': params is not defined or is incorrect in the bidder settings.'); + utils.logError(BIDDER_CODE + ': params is not defined or is incorrect in the bidder settings.'); return false; } - if (!deepAccess(bid, 'mediaTypes.video')) { - logError(BIDDER_CODE + ': mediaTypes.video is not present in the bidder settings.'); + if (!utils.deepAccess(bid, 'mediaTypes.video')) { + utils.logError(BIDDER_CODE + ': mediaTypes.video is not present in the bidder settings.'); return false; } - const playerSize = deepAccess(bid, 'mediaTypes.video.playerSize'); - if (!playerSize || !isArray(playerSize)) { - logError(BIDDER_CODE + ': mediaTypes.video.playerSize is not defined in the bidder settings.'); + const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); + if (!playerSize || !utils.isArray(playerSize)) { + utils.logError(BIDDER_CODE + ': mediaTypes.video.playerSize is not defined in the bidder settings.'); return false; } - if (!getBidIdParameter('channel_id', bid.params)) { - logError(BIDDER_CODE + ': channel_id is not present in bidder params'); + if (!utils.getBidIdParameter('channel_id', bid.params)) { + utils.logError(BIDDER_CODE + ': channel_id is not present in bidder params'); return false; } - if (deepAccess(bid, 'mediaTypes.video.context') == 'outstream' || deepAccess(bid, 'params.ad_unit') == 'outstream') { - if (!getBidIdParameter('outstream_function', bid.params)) { - if (!getBidIdParameter('outstream_options', bid.params)) { - logError(BIDDER_CODE + ': please define outstream_options parameter or override the default SpotX outstream rendering by defining your own Outstream function using field outstream_function.'); + if (utils.deepAccess(bid, 'mediaTypes.video.context') == 'outstream' || utils.deepAccess(bid, 'params.ad_unit') == 'outstream') { + if (!utils.getBidIdParameter('outstream_function', bid.params)) { + if (!utils.getBidIdParameter('outstream_options', bid.params)) { + utils.logError(BIDDER_CODE + ': please define outstream_options parameter or override the default SpotX outstream rendering by defining your own Outstream function using field outstream_function.'); return false; } - if (!getBidIdParameter('slot', bid.params.outstream_options)) { - logError(BIDDER_CODE + ': please define parameter slot in outstream_options object in the configuration.'); + if (!utils.getBidIdParameter('slot', bid.params.outstream_options)) { + utils.logError(BIDDER_CODE + ': please define parameter slot in outstream_options object in the configuration.'); return false; } } @@ -74,54 +75,54 @@ export const spec = { const siteId = ''; const spotxRequests = bidRequests.map(function(bid) { let page; - if (getBidIdParameter('page', bid.params)) { - page = getBidIdParameter('page', bid.params); + if (utils.getBidIdParameter('page', bid.params)) { + page = utils.getBidIdParameter('page', bid.params); } else if (config.getConfig('pageUrl')) { page = config.getConfig('pageUrl'); } else { page = referer; } - const channelId = getBidIdParameter('channel_id', bid.params); + const channelId = utils.getBidIdParameter('channel_id', bid.params); let pubcid = null; - const playerSize = deepAccess(bid, 'mediaTypes.video.playerSize'); + const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); const contentWidth = playerSize[0][0]; const contentHeight = playerSize[0][1]; - const secure = isPageSecure || (getBidIdParameter('secure', bid.params) ? 1 : 0); + const secure = isPageSecure || (utils.getBidIdParameter('secure', bid.params) ? 1 : 0); const ext = { sdk_name: 'Prebid 1+', versionOrtb: ORTB_VERSION }; - if (getBidIdParameter('hide_skin', bid.params) != '') { - ext.hide_skin = +!!getBidIdParameter('hide_skin', bid.params); + if (utils.getBidIdParameter('hide_skin', bid.params) != '') { + ext.hide_skin = +!!utils.getBidIdParameter('hide_skin', bid.params); } - if (getBidIdParameter('ad_volume', bid.params) != '') { - ext.ad_volume = getBidIdParameter('ad_volume', bid.params); + if (utils.getBidIdParameter('ad_volume', bid.params) != '') { + ext.ad_volume = utils.getBidIdParameter('ad_volume', bid.params); } - if (getBidIdParameter('ad_unit', bid.params) != '') { - ext.ad_unit = getBidIdParameter('ad_unit', bid.params); + if (utils.getBidIdParameter('ad_unit', bid.params) != '') { + ext.ad_unit = utils.getBidIdParameter('ad_unit', bid.params); } - if (getBidIdParameter('outstream_options', bid.params) != '') { - ext.outstream_options = getBidIdParameter('outstream_options', bid.params); + if (utils.getBidIdParameter('outstream_options', bid.params) != '') { + ext.outstream_options = utils.getBidIdParameter('outstream_options', bid.params); } - if (getBidIdParameter('outstream_function', bid.params) != '') { - ext.outstream_function = getBidIdParameter('outstream_function', bid.params); + if (utils.getBidIdParameter('outstream_function', bid.params) != '') { + ext.outstream_function = utils.getBidIdParameter('outstream_function', bid.params); } - if (getBidIdParameter('custom', bid.params) != '') { - ext.custom = getBidIdParameter('custom', bid.params); + if (utils.getBidIdParameter('custom', bid.params) != '') { + ext.custom = utils.getBidIdParameter('custom', bid.params); } - if (getBidIdParameter('pre_market_bids', bid.params) != '' && isArray(getBidIdParameter('pre_market_bids', bid.params))) { - const preMarketBids = getBidIdParameter('pre_market_bids', bid.params); + if (utils.getBidIdParameter('pre_market_bids', bid.params) != '' && utils.isArray(utils.getBidIdParameter('pre_market_bids', bid.params))) { + const preMarketBids = utils.getBidIdParameter('pre_market_bids', bid.params); ext.pre_market_bids = []; for (let i in preMarketBids) { const preMarketBid = preMarketBids[i]; @@ -149,7 +150,7 @@ export const spec = { } } - const mimes = getBidIdParameter('mimes', bid.params) || ['application/javascript', 'video/mp4', 'video/webm']; + const mimes = utils.getBidIdParameter('mimes', bid.params) || ['application/javascript', 'video/mp4', 'video/webm']; const spotxReq = { id: bid.bidId, @@ -162,38 +163,24 @@ export const spec = { } }; - if (isFn(bid.getFloor)) { - let floorInfo = bid.getFloor({ - currency: 'USD', - mediaType: 'video', - size: '*' - }); - - if (floorInfo.currency === 'USD') { - spotxReq.bidfloor = floorInfo.floor; - } - } else if (getBidIdParameter('price_floor', bid.params) != '') { - spotxReq.bidfloor = getBidIdParameter('price_floor', bid.params); - } - - if (getBidIdParameter('start_delay', bid.params) != '') { - spotxReq.video.startdelay = 0 + Boolean(getBidIdParameter('start_delay', bid.params)); + if (utils.getBidIdParameter('start_delay', bid.params) != '') { + spotxReq.video.startdelay = 0 + Boolean(utils.getBidIdParameter('start_delay', bid.params)); } - if (getBidIdParameter('min_duration', bid.params) != '') { - spotxReq.video.minduration = getBidIdParameter('min_duration', bid.params); + if (utils.getBidIdParameter('min_duration', bid.params) != '') { + spotxReq.video.minduration = utils.getBidIdParameter('min_duration', bid.params); } - if (getBidIdParameter('max_duration', bid.params) != '') { - spotxReq.video.maxduration = getBidIdParameter('max_duration', bid.params); + if (utils.getBidIdParameter('max_duration', bid.params) != '') { + spotxReq.video.maxduration = utils.getBidIdParameter('max_duration', bid.params); } - if (getBidIdParameter('placement_type', bid.params) != '') { - spotxReq.video.ext.placement = getBidIdParameter('placement_type', bid.params); + if (utils.getBidIdParameter('placement_type', bid.params) != '') { + spotxReq.video.ext.placement = utils.getBidIdParameter('placement_type', bid.params); } - if (getBidIdParameter('position', bid.params) != '') { - spotxReq.video.ext.pos = getBidIdParameter('position', bid.params); + if (utils.getBidIdParameter('position', bid.params) != '') { + spotxReq.video.ext.pos = utils.getBidIdParameter('position', bid.params); } if (bid.crumbs && bid.crumbs.pubcid) { @@ -204,7 +191,7 @@ export const spec = { const device = { h: screen.height, w: screen.width, - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, language: navigator[language].split('-')[0], make: navigator.vendor ? navigator.vendor : '', ua: navigator.userAgent @@ -230,13 +217,13 @@ export const spec = { requestPayload['ext']['wrap_response'] = 0; } - if (getBidIdParameter('number_of_ads', bid.params)) { - requestPayload['ext']['number_of_ads'] = getBidIdParameter('number_of_ads', bid.params); + if (utils.getBidIdParameter('number_of_ads', bid.params)) { + requestPayload['ext']['number_of_ads'] = utils.getBidIdParameter('number_of_ads', bid.params); } const userExt = {}; - if (getBidIdParameter('spotx_all_google_consent', bid.params) == 1) { + if (utils.getBidIdParameter('spotx_all_google_consent', bid.params) == 1) { userExt['consented_providers_settings'] = GOOGLE_CONSENT; } @@ -245,16 +232,16 @@ export const spec = { userExt.consent = bidderRequest.gdprConsent.consentString; if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { - deepSetValue(requestPayload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + utils.deepSetValue(requestPayload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); } } if (bidderRequest && bidderRequest.uspConsent) { - deepSetValue(requestPayload, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(requestPayload, 'regs.ext.us_privacy', bidderRequest.uspConsent); } // ID5 fied - if (deepAccess(bid, 'userId.id5id.uid')) { + if (utils.deepAccess(bid, 'userId.id5id.uid')) { userExt.eids = userExt.eids || []; userExt.eids.push( { @@ -297,7 +284,7 @@ export const spec = { } // Only add the user object if it's not empty - if (!isEmpty(userExt)) { + if (!utils.isEmpty(userExt)) { requestPayload.user = { ext: userExt }; } const urlQueryParams = 'src_sys=prebid' @@ -322,9 +309,9 @@ export const spec = { const bidResponses = []; const serverResponseBody = serverResponse.body; - if (serverResponseBody && isArray(serverResponseBody.seatbid)) { - _each(serverResponseBody.seatbid, function(bids) { - _each(bids.bid, function(spotxBid) { + if (serverResponseBody && utils.isArray(serverResponseBody.seatbid)) { + utils._each(serverResponseBody.seatbid, function(bids) { + utils._each(bids.bid, function(spotxBid) { let currentBidRequest = {}; for (let i in bidderRequest.bidRequest.bids) { if (spotxBid.impid == bidderRequest.bidRequest.bids[i].bidId) { @@ -336,7 +323,7 @@ export const spec = { * Make sure currency and price are the right ones * TODO: what about the pre_market_bid partners sizes? */ - _each(currentBidRequest.params.pre_market_bids, function(pmb) { + utils._each(currentBidRequest.params.pre_market_bids, function(pmb) { if (pmb.deal_id == spotxBid.id) { spotxBid.price = pmb.price; serverResponseBody.cur = pmb.currency; @@ -370,10 +357,10 @@ export const spec = { bid.meta.advertiserDomains = spotxBid.adomain; } - const context1 = deepAccess(currentBidRequest, 'mediaTypes.video.context'); - const context2 = deepAccess(currentBidRequest, 'params.ad_unit'); + const context1 = utils.deepAccess(currentBidRequest, 'mediaTypes.video.context'); + const context2 = utils.deepAccess(currentBidRequest, 'params.ad_unit'); if (context1 == 'outstream' || context2 == 'outstream') { - const playersize = deepAccess(currentBidRequest, 'mediaTypes.video.playerSize'); + const playersize = utils.deepAccess(currentBidRequest, 'mediaTypes.video.playerSize'); const renderer = Renderer.install({ id: 0, url: '/', @@ -381,11 +368,11 @@ export const spec = { adText: 'SpotX Outstream Video Ad via Prebid.js', player_width: playersize[0][0], player_height: playersize[0][1], - content_page_url: deepAccess(bidderRequest, 'data.site.page'), - ad_mute: +!!deepAccess(currentBidRequest, 'params.ad_mute'), - hide_skin: +!!deepAccess(currentBidRequest, 'params.hide_skin'), - outstream_options: deepAccess(currentBidRequest, 'params.outstream_options'), - outstream_function: deepAccess(currentBidRequest, 'params.outstream_function') + content_page_url: utils.deepAccess(bidderRequest, 'data.site.page'), + ad_mute: +!!utils.deepAccess(currentBidRequest, 'params.ad_mute'), + hide_skin: +!!utils.deepAccess(currentBidRequest, 'params.hide_skin'), + outstream_options: utils.deepAccess(currentBidRequest, 'params.outstream_options'), + outstream_function: utils.deepAccess(currentBidRequest, 'params.outstream_function') } }); @@ -393,17 +380,17 @@ export const spec = { renderer.setRender(outstreamRender); renderer.setEventHandlers({ impression: function impression() { - return logMessage('SpotX outstream video impression event'); + return utils.logMessage('SpotX outstream video impression event'); }, loaded: function loaded() { - return logMessage('SpotX outstream video loaded event'); + return utils.logMessage('SpotX outstream video loaded event'); }, ended: function ended() { - logMessage('SpotX outstream renderer video event'); + utils.logMessage('SpotX outstream renderer video event'); } }); } catch (err) { - logWarn('Prebid Error calling setRender or setEventHandlers on renderer', err); + utils.logWarn('Prebid Error calling setRender or setEventHandlers on renderer', err); } bid.renderer = renderer; } @@ -418,8 +405,8 @@ export const spec = { } function createOutstreamScript(bid) { - const slot = getBidIdParameter('slot', bid.renderer.config.outstream_options); - logMessage('[SPOTX][renderer] Handle SpotX outstream renderer'); + const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); + utils.logMessage('[SPOTX][renderer] Handle SpotX outstream renderer'); const script = window.document.createElement('script'); script.type = 'text/javascript'; script.src = 'https://js.spotx.tv/easi/v1/' + bid.channel_id + '.js'; @@ -429,8 +416,8 @@ function createOutstreamScript(bid) { dataSpotXParams['data-spotx_content_page_url'] = bid.renderer.config.content_page_url; dataSpotXParams['data-spotx_ad_unit'] = 'incontent'; - logMessage('[SPOTX][renderer] Default behavior'); - if (getBidIdParameter('ad_mute', bid.renderer.config.outstream_options)) { + utils.logMessage('[SPOTX][renderer] Default behavior'); + if (utils.getBidIdParameter('ad_mute', bid.renderer.config.outstream_options)) { dataSpotXParams['data-spotx_ad_mute'] = '1'; } dataSpotXParams['data-spotx_collapse'] = '0'; @@ -438,9 +425,9 @@ function createOutstreamScript(bid) { dataSpotXParams['data-spotx_blocked_autoplay_override_mode'] = '1'; dataSpotXParams['data-spotx_video_slot_can_autoplay'] = '1'; - const playersizeAutoAdapt = getBidIdParameter('playersize_auto_adapt', bid.renderer.config.outstream_options); - if (playersizeAutoAdapt && isBoolean(playersizeAutoAdapt) && playersizeAutoAdapt === true) { - const ratio = bid.width && isNumber(bid.width) && bid.height && isNumber(bid.height) ? bid.width / bid.height : 4 / 3; + const playersizeAutoAdapt = utils.getBidIdParameter('playersize_auto_adapt', bid.renderer.config.outstream_options); + if (playersizeAutoAdapt && utils.isBoolean(playersizeAutoAdapt) && playersizeAutoAdapt === true) { + const ratio = bid.width && utils.isNumber(bid.width) && bid.height && utils.isNumber(bid.height) ? bid.width / bid.height : 4 / 3; const slotClientWidth = window.document.getElementById(slot).clientWidth; let playerWidth = bid.renderer.config.player_width; let playerHeight = bid.renderer.config.player_height; @@ -462,13 +449,13 @@ function createOutstreamScript(bid) { dataSpotXParams['data-spotx_content_height'] = '' + contentHeight; } - const customOverride = getBidIdParameter('custom_override', bid.renderer.config.outstream_options); - if (customOverride && isPlainObject(customOverride)) { - logMessage('[SPOTX][renderer] Custom behavior.'); + const customOverride = utils.getBidIdParameter('custom_override', bid.renderer.config.outstream_options); + if (customOverride && utils.isPlainObject(customOverride)) { + utils.logMessage('[SPOTX][renderer] Custom behavior.'); for (let name in customOverride) { if (customOverride.hasOwnProperty(name)) { if (name === 'channel_id' || name === 'vast_url' || name === 'content_page_url' || name === 'ad_unit') { - logWarn('[SPOTX][renderer] Custom behavior: following option cannot be overridden: ' + name); + utils.logWarn('[SPOTX][renderer] Custom behavior: following option cannot be overridden: ' + name); } else { dataSpotXParams['data-spotx_' + name] = customOverride[name]; } @@ -491,7 +478,7 @@ function outstreamRender(bid) { bid.renderer.config.outstream_function(bid, script); } else { try { - const inIframe = getBidIdParameter('in_iframe', bid.renderer.config.outstream_options); + const inIframe = utils.getBidIdParameter('in_iframe', bid.renderer.config.outstream_options); if (inIframe && window.document.getElementById(inIframe).nodeName == 'IFRAME') { const rawframe = window.document.getElementById(inIframe); let framedoc = rawframe.contentDocument; @@ -500,7 +487,7 @@ function outstreamRender(bid) { } framedoc.body.appendChild(script); } else { - const slot = getBidIdParameter('slot', bid.renderer.config.outstream_options); + const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); if (slot && window.document.getElementById(slot)) { window.document.getElementById(slot).appendChild(script); } else { @@ -508,7 +495,7 @@ function outstreamRender(bid) { } } } catch (err) { - logError('[SPOTX][renderer] Error:' + err.message) + utils.logError('[SPOTX][renderer] Error:' + err.message) } } } diff --git a/modules/sspBCBidAdapter.js b/modules/sspBCBidAdapter.js index e46073a63ba..15e0baa811f 100644 --- a/modules/sspBCBidAdapter.js +++ b/modules/sspBCBidAdapter.js @@ -1,23 +1,19 @@ -import {deepAccess, isArray, logWarn, parseUrl} from '../src/utils.js'; -import {ajax} from '../src/ajax.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {includes as strIncludes} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { ajax } from '../src/ajax.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER } from '../src/mediaTypes.js'; +import strIncludes from 'core-js-pure/features/string/includes.js'; const BIDDER_CODE = 'sspBC'; const BIDDER_URL = 'https://ssp.wp.pl/bidder/'; const SYNC_URL = 'https://ssp.wp.pl/bidder/usersync'; const NOTIFY_URL = 'https://ssp.wp.pl/bidder/notify'; -const TRACKER_URL = 'https://bdr.wpcdn.pl/tag/jstracker.js'; -const GVLID = 676; const TMAX = 450; -const BIDDER_VERSION = '5.41'; +const BIDDER_VERSION = '5.0'; const W = window; const { navigator } = W; const oneCodeDetection = {}; -const adUnitsCalled = {}; const adSizesCalled = {}; -const pageView = {}; var consentApiVersion; /** @@ -26,16 +22,16 @@ var consentApiVersion; */ const getNotificationPayload = bidData => { if (bidData) { - const bids = isArray(bidData) ? bidData : [bidData]; + const bids = utils.isArray(bidData) ? bidData : [bidData]; if (bids.length > 0) { const result = { requestId: undefined, siteId: [], + adUnit: [], slotId: [], - tagid: [], } bids.forEach(bid => { - let params = isArray(bid.params) ? bid.params[0] : bid.params; + let params = utils.isArray(bid.params) ? bid.params[0] : bid.params; params = params || {}; // check for stored detection @@ -57,7 +53,7 @@ const getNotificationPayload = bidData => { result.adomain = meta.advertiserDomains && meta.advertiserDomains[0]; result.networkName = meta.networkName; } - result.tagid.push(bid.adUnitCode); + result.adUnit.push(bid.adUnitCode) result.requestId = bid.auctionId || result.requestId; result.timeout = bid.timeout || result.timeout; }) @@ -74,7 +70,6 @@ const cookieSupport = () => { }; const applyClientHints = ortbRequest => { - const { location } = document; const { connection = {}, deviceMemory, userAgentData = {} } = navigator; const viewport = W.visualViewport || false; const segments = []; @@ -90,16 +85,6 @@ const applyClientHints = ortbRequest => { 'CH-isMobile': userAgentData.mobile, }; - /** - Check / generate page view id - Should be generated dureing first call to applyClientHints(), - and re-generated if pathname has changed - */ - if (!pageView.id || location.pathname !== pageView.path) { - pageView.path = location.pathname; - pageView.id = Math.floor(1E20 * Math.random()); - } - Object.keys(hints).forEach(key => { const hint = hints[key]; @@ -115,26 +100,9 @@ const applyClientHints = ortbRequest => { id: '12', name: 'NetInfo', segment: segments, - }, { - id: '7', - name: 'pvid', - segment: [ - { - value: `${pageView.id}` - } - ] }]; - const ch = { data }; - ortbRequest.user = { ...ortbRequest.user, ...ch }; -}; - -const applyUserIds = (validBidRequest, ortbRequest) => { - const eids = validBidRequest.userIdAsEids - if (eids && eids.length) { - const ids = { eids }; - ortbRequest.user = { ...ortbRequest.user, ...ids }; - } + ortbRequest.user = Object.assign(ortbRequest.user, { data }); }; /** @@ -146,22 +114,21 @@ const applyGdpr = (bidderRequest, ortbRequest) => { if (gdprConsent) { const { apiVersion, gdprApplies, consentString } = gdprConsent; consentApiVersion = apiVersion; - ortbRequest.regs = Object.assign(ortbRequest.regs, { 'gdpr': gdprApplies ? 1 : 0 }); - ortbRequest.user = Object.assign(ortbRequest.user, { 'consent': consentString }); + ortbRequest.regs = Object.assign(ortbRequest.regs, { '[ortb_extensions.gdpr]': gdprApplies ? 1 : 0 }); + ortbRequest.user = Object.assign(ortbRequest.user, { '[ortb_extensions.consent]': consentString }); } } /** * Get value for first occurence of key within the collection */ -const setOnAny = (collection, key) => collection.reduce((prev, next) => prev || deepAccess(next, key), false); +const setOnAny = (collection, key) => collection.reduce((prev, next) => prev || utils.deepAccess(next, key), false); /** * Send payload to notification endpoint */ const sendNotification = payload => { ajax(NOTIFY_URL, null, JSON.stringify(payload), { - contentType: 'application/json', withCredentials: false, method: 'POST', crossOrigin: true @@ -174,7 +141,7 @@ const sendNotification = payload => { */ const mapBanner = slot => { if (slot.mediaType === 'banner' || - deepAccess(slot, 'mediaTypes.banner') || + utils.deepAccess(slot, 'mediaTypes.banner') || (!slot.mediaType && !slot.mediaTypes)) { const format = slot.sizes.map(size => ({ w: size[0], @@ -188,108 +155,6 @@ const mapBanner = slot => { } } -/** - * @param {string} paramName Native parameter name - * @param {object} paramValue Native parameter value - * @returns {object} native asset object that conforms to ortb native ads spec - */ -const mapAsset = (paramName, paramValue) => { - let asset; - switch (paramName) { - case 'title': - asset = { - id: 0, - required: paramValue.required, - title: { len: paramValue.len } - } - break; - case 'cta': - asset = { - id: 1, - required: paramValue.required, - data: { type: 12 } - } - break; - case 'icon': - asset = { - id: 2, - required: paramValue.required, - img: { type: 1, w: paramValue.sizes[0], h: paramValue.sizes[1] } - } - break; - case 'image': - asset = { - id: 3, - required: paramValue.required, - img: { type: 3, w: paramValue.sizes[0], h: paramValue.sizes[1] } - } - break; - case 'body': - asset = { - id: 4, - required: paramValue.required, - data: { type: 2 } - } - break; - case 'sponsoredBy': - asset = { - id: 5, - required: paramValue.required, - data: { type: 1 } - } - break; - } - return asset; -} - -/** - * @param {object} slot Ad Unit Params by Prebid - * @returns {object} native object that conforms to ortb native ads spec - */ -const mapNative = slot => { - const native = deepAccess(slot, 'mediaTypes.native'); - let assets; - if (native) { - const nativeParams = Object.keys(native); - assets = []; - nativeParams.forEach(par => { - const newAsset = mapAsset(par, native[par]); - if (newAsset) { assets.push(newAsset) }; - }); - } - return assets ? { request: JSON.stringify({ native: { assets } }) } : undefined; -} - -var mapVideo = slot => { - var video = deepAccess(slot, 'mediaTypes.video'); - var videoParamsUsed = ['api', 'context', 'linearity', 'maxduration', 'mimes', 'protocols']; - var videoAssets; - - if (video) { - var videoParams = Object.keys(video); - var playerSize = video.playerSize; - videoAssets = {}; // player width / height - - if (playerSize) { - var maxSize = playerSize.reduce(function (prev, next) { - return next[0] >= prev[0] && next[1] >= prev[1] ? next : prev; - }, [1, 1]); - videoAssets.w = maxSize[0]; - videoAssets.h = maxSize[1]; - } // remaining supported params - - videoParams.forEach(function (par) { - if (videoParamsUsed.indexOf(par) >= 0) { - videoAssets[par] = video[par]; - } - - ; - }); - } - - return videoAssets; -}; - const mapImpression = slot => { const { adUnitCode, bidId, params = {}, ortb2Imp = {} } = slot; const { id, siteId } = params; @@ -300,109 +165,32 @@ const mapImpression = slot => { send this info as ext.pbsize */ const slotSize = slot.sizes.length ? slot.sizes.reduce((prev, next) => prev[0] * prev[1] <= next[0] * next[1] ? next : prev).join('x') : '1x1'; - - if (!adUnitsCalled[adUnitCode]) { - // this is a new adunit - assign & save pbsize - adSizesCalled[slotSize] = adSizesCalled[slotSize] ? adSizesCalled[slotSize] += 1 : 1; - adUnitsCalled[adUnitCode] = `${slotSize}_${adSizesCalled[slotSize]}` - } - - ext.data = Object.assign({ pbsize: adUnitsCalled[adUnitCode] }, ext.data); + adSizesCalled[slotSize] = adSizesCalled[slotSize] ? adSizesCalled[slotSize] + 1 : 1; + ext.data = Object.assign({ pbsize: `${slotSize}_${adSizesCalled[slotSize]}` }, ext.data); const imp = { - id: id && siteId ? id.padStart(3, '0') : 'bidid-' + bidId, + id: id && siteId ? id : 'bidid-' + bidId, banner: mapBanner(slot), - native: mapNative(slot), - video: mapVideo(slot), + // native: mapNative(slot), tagid: adUnitCode, ext, }; // Check floorprices for this imp if (typeof slot.getFloor === 'function') { - var bannerFloor = 0; - var nativeFloor = 0; - var videoFloor = 0; // sspBC adapter accepts only floor per imp - check for maximum value for requested ad types and sizes - + let bannerFloor = 0; + // sspBC adapter accepts only floor per imp - check for maximum value for requested ad types and sizes if (slot.sizes.length) { - bannerFloor = slot.sizes.reduce(function (prev, next) { - var currentFloor = slot.getFloor({ - mediaType: 'banner', - size: next - }).floor; + bannerFloor = slot.sizes.reduce((prev, next) => { + const currentFloor = slot.getFloor({ mediaType: 'banner', size: next }).floor; return prev > currentFloor ? prev : currentFloor; }, 0); } - - nativeFloor = slot.getFloor({ - mediaType: 'native' - }); - videoFloor = slot.getFloor({ - mediaType: 'video' - }); - imp.bidfloor = Math.max(bannerFloor, nativeFloor, videoFloor); + imp.bidfloor = bannerFloor; } return imp; } -const isVideoAd = bid => { - const xmlTester = new RegExp(/^<\?xml/); - return bid.adm && bid.adm.match(xmlTester); -} - -const isNativeAd = bid => { - const xmlTester = new RegExp(/^{['"]native['"]/); - - return bid.admNative || (bid.adm && bid.adm.match(xmlTester)); -} - -const parseNative = nativeData => { - const result = {}; - nativeData.assets.forEach(asset => { - const id = parseInt(asset.id); - switch (id) { - case 0: - result.title = asset.title.text; - break; - case 1: - result.cta = asset.data.value; - break; - case 2: - result.icon = { - url: asset.img.url, - width: asset.img.w, - height: asset.img.h, - }; - break; - case 3: - result.image = { - url: asset.img.url, - width: asset.img.w, - height: asset.img.h, - }; - break; - case 4: - result.body = asset.data.value; - break; - case 5: - result.sponsoredBy = asset.data.value; - break; - - default: - logWarn('Unrecognized native asset', asset); - } - }); - result.clickUrl = nativeData.link.url; - result.impressionTrackers = nativeData.imptrackers; - - if (isArray(nativeData.jstracker)) { - result.javascriptTrackers = nativeData.jstracker; - } else if (nativeData.jstracker) { - result.javascriptTrackers = [nativeData.jstracker]; - } - return result; -} - const renderCreative = (site, auctionId, bid, seat, request) => { let gam; @@ -437,7 +225,7 @@ const renderCreative = (site, auctionId, bid, seat, request) => { gam.targeting = {}; } } catch (err) { - logWarn('Could not parse adm data', bid.adm); + utils.logWarn('Could not parse adm data', bid.adm); } } @@ -455,16 +243,17 @@ const renderCreative = (site, auctionId, bid, seat, request) => { @@ -478,9 +267,8 @@ const renderCreative = (site, auctionId, bid, seat, request) => { const spec = { code: BIDDER_CODE, - gvlid: GVLID, aliases: [], - supportedMediaTypes: [BANNER, NATIVE, VIDEO], + supportedMediaTypes: [BANNER], isBidRequestValid(bid) { // as per OneCode integration, bids without params are valid return true; @@ -493,7 +281,7 @@ const spec = { const siteId = setOnAny(validBidRequests, 'params.siteId'); const publisherId = setOnAny(validBidRequests, 'params.publisherId'); const page = setOnAny(validBidRequests, 'params.page') || bidderRequest.refererInfo.referer; - const domain = setOnAny(validBidRequests, 'params.domain') || parseUrl(page).hostname; + const domain = setOnAny(validBidRequests, 'params.domain') || utils.parseUrl(page).hostname; const tmax = setOnAny(validBidRequests, 'params.tmax') ? parseInt(setOnAny(validBidRequests, 'params.tmax'), 10) : TMAX; const pbver = '$prebid.version$'; const testMode = setOnAny(validBidRequests, 'params.test') ? 1 : undefined; @@ -523,7 +311,6 @@ const spec = { applyGdpr(bidderRequest, payload); applyClientHints(payload); - applyUserIds(validBidRequests[0], payload); return { method: 'POST', @@ -569,14 +356,10 @@ const spec = { /* bid response might include ext object containing siteId / slotId, as detected by OneCode update site / slot data in this case - - ext also might contain publisherId and custom ad label */ - const { siteid, slotid, pubid, adlabel } = ext; + const { siteid, slotid } = ext; site.id = siteid || site.id; site.slot = slotid || site.slot; - site.publisherId = pubid; - site.adLabel = adlabel; } if (bidRequest && site.id && !strIncludes(site.id, 'bidid')) { @@ -594,62 +377,20 @@ const spec = { width: w, height: h, bidderCode: BIDDER_CODE, + mediaType: 'banner', meta: { advertiserDomains: adomain, networkName: seat, }, netRevenue: true, + ad: renderCreative(site, response.id, serverBid, seat, bidderRequest), }; - // mediaType and ad data for instream / native / banner - if (isVideoAd(serverBid)) { - // video - bid.adType = 'instream'; - bid.mediaType = 'video'; - bid.vastXml = serverBid.adm; - bid.vastContent = serverBid.adm; - } else if (isNativeAd(serverBid)) { - // native - bid.mediaType = 'native'; - // check native object - try { - const nativeData = serverBid.admNative || JSON.parse(serverBid.adm).native; - bid.native = parseNative(nativeData); - bid.width = 1; - bid.height = 1; - - // append viewability tracker - const jsData = { - rid: bidRequest.auctionId, - crid: bid.creativeId, - adunit: bidRequest.adUnitCode, - url: bid.native.clickUrl, - vendor: seat, - site: site.id, - slot: site.slot, - cpm: bid.cpm.toPrecision(4), - } - const jsTracker = ' - - - `; -} - -registerBidder(spec); diff --git a/modules/targetVideoBidAdapter.md b/modules/targetVideoBidAdapter.md deleted file mode 100644 index 557c9f94410..00000000000 --- a/modules/targetVideoBidAdapter.md +++ /dev/null @@ -1,34 +0,0 @@ -# Overview - -``` -Module Name: Target Video Bid Adapter -Module Type: Bidder Adapter -Maintainer: grajzer@gmail.com -``` - -# Description - -Connects to Appnexus exchange for bids. - -TargetVideo bid adapter supports Banner. - -# Test Parameters -``` -var adUnits = [ - // Banner adUnit - { - code: 'banner-div', - mediaTypes: { - banner: { - sizes: [[640, 480], [300, 250]], - } - }, - bids: [{ - bidder: 'targetVideo', - params: { - placementId: 13232361 - } - }] - } -]; -``` diff --git a/modules/teadsBidAdapter.js b/modules/teadsBidAdapter.js index a8902c896f6..5e6062e5483 100644 --- a/modules/teadsBidAdapter.js +++ b/modules/teadsBidAdapter.js @@ -1,6 +1,6 @@ -import { getValue, logError, deepAccess, getBidIdParameter, parseSizesInput, isArray } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {getStorageManager} from '../src/storageManager.js'; +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'teads'; const GVL_ID = 132; @@ -12,7 +12,7 @@ const gdprStatus = { CMP_NOT_FOUND_OR_ERROR: 22 }; const FP_TEADS_ID_COOKIE_NAME = '_tfpvi'; -export const storage = getStorageManager({gvlid: GVL_ID, bidderCode: BIDDER_CODE}); +export const storage = getStorageManager(GVL_ID, BIDDER_CODE); export const spec = { code: BIDDER_CODE, @@ -27,13 +27,13 @@ export const spec = { isBidRequestValid: function(bid) { let isValid = false; if (typeof bid.params !== 'undefined') { - let isValidPlacementId = _validateId(getValue(bid.params, 'placementId')); - let isValidPageId = _validateId(getValue(bid.params, 'pageId')); + let isValidPlacementId = _validateId(utils.getValue(bid.params, 'placementId')); + let isValidPageId = _validateId(utils.getValue(bid.params, 'pageId')); isValid = isValidPlacementId && isValidPageId; } if (!isValid) { - logError('Teads placementId and pageId parameters are required. Bid aborted.'); + utils.logError('Teads placementId and pageId parameters are required. Bid aborted.'); } return isValid; }, @@ -54,8 +54,8 @@ export const spec = { data: bids, deviceWidth: screen.width, hb_version: '$prebid.version$', - ...getFLoCParameters(deepAccess(validBidRequests, '0.userId.flocId')), - ...getUnifiedId2Parameter(deepAccess(validBidRequests, '0.userId.uid2')), + ...getFLoCParameters(utils.deepAccess(validBidRequests, '0.userId.flocId')), + ...getUnifiedId2Parameter(utils.deepAccess(validBidRequests, '0.userId.uid2')), ...getFirstPartyTeadsIdParameter() }; @@ -188,37 +188,35 @@ function isGlobalConsent(gdprData, apiVersion) { function buildRequestObject(bid) { const reqObj = {}; - let placementId = getValue(bid.params, 'placementId'); - let pageId = getValue(bid.params, 'pageId'); - const gpid = deepAccess(bid, 'ortb2Imp.ext.gpid'); + let placementId = utils.getValue(bid.params, 'placementId'); + let pageId = utils.getValue(bid.params, 'pageId'); reqObj.sizes = getSizes(bid); - reqObj.bidId = getBidIdParameter('bidId', bid); - reqObj.bidderRequestId = getBidIdParameter('bidderRequestId', bid); + reqObj.bidId = utils.getBidIdParameter('bidId', bid); + reqObj.bidderRequestId = utils.getBidIdParameter('bidderRequestId', bid); reqObj.placementId = parseInt(placementId, 10); reqObj.pageId = parseInt(pageId, 10); - reqObj.adUnitCode = getBidIdParameter('adUnitCode', bid); - reqObj.auctionId = getBidIdParameter('auctionId', bid); - reqObj.transactionId = getBidIdParameter('transactionId', bid); - if (gpid) { reqObj.gpid = gpid; } + reqObj.adUnitCode = utils.getBidIdParameter('adUnitCode', bid); + reqObj.auctionId = utils.getBidIdParameter('auctionId', bid); + reqObj.transactionId = utils.getBidIdParameter('transactionId', bid); return reqObj; } function getSizes(bid) { - return parseSizesInput(concatSizes(bid)); + return utils.parseSizesInput(concatSizes(bid)); } function concatSizes(bid) { - let playerSize = deepAccess(bid, 'mediaTypes.video.playerSize'); - let videoSizes = deepAccess(bid, 'mediaTypes.video.sizes'); - let bannerSizes = deepAccess(bid, 'mediaTypes.banner.sizes'); + let playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); + let videoSizes = utils.deepAccess(bid, 'mediaTypes.video.sizes'); + let bannerSizes = utils.deepAccess(bid, 'mediaTypes.banner.sizes'); - if (isArray(bannerSizes) || isArray(playerSize) || isArray(videoSizes)) { + if (utils.isArray(bannerSizes) || utils.isArray(playerSize) || utils.isArray(videoSizes)) { let mediaTypesSizes = [bannerSizes, videoSizes, playerSize]; return mediaTypesSizes .reduce(function(acc, currSize) { - if (isArray(currSize)) { - if (isArray(currSize[0])) { + if (utils.isArray(currSize)) { + if (utils.isArray(currSize[0])) { currSize.forEach(function (childSize) { acc.push(childSize); }) diff --git a/modules/telariaBidAdapter.js b/modules/telariaBidAdapter.js index 42913414cbc..b2904045144 100644 --- a/modules/telariaBidAdapter.js +++ b/modules/telariaBidAdapter.js @@ -1,6 +1,8 @@ -import { logError, isEmpty, deepAccess, triggerPixel, logWarn, isArray } from '../src/utils.js'; +import * as utils from '../src/utils.js'; +import {createBid as createBidFactory} from '../src/bidfactory.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {VIDEO} from '../src/mediaTypes.js'; +import {STATUS} from '../src/constants.json'; const BIDDER_CODE = 'telaria'; const DOMAIN = 'tremorhub.com'; @@ -9,11 +11,7 @@ const EVENTS_ENDPOINT = `events.${DOMAIN}/diag`; export const spec = { code: BIDDER_CODE, - gvlid: 52, - aliases: [ - { code: 'tremor', gvlid: 52 }, - { code: 'tremorvideo', gvlid: 52 } - ], + aliases: ['tremor', 'tremorvideo'], supportedMediaTypes: [VIDEO], /** * Determines if the request is valid @@ -75,7 +73,7 @@ export const spec = { } }); } catch (error) { - logError(error); + utils.logError(error); width = 0; height = 0; } @@ -85,12 +83,10 @@ export const spec = { if (bidResult && bidResult.error) { errorMessage += `: ${bidResult.error}`; } - logError(errorMessage); - } else if (!isEmpty(bidResult.seatbid)) { + utils.logError(errorMessage); + } else if (!utils.isEmpty(bidResult.seatbid)) { bidResult.seatbid[0].bid.forEach(tag => { - if (tag) { - bids.push(createBid(bidderRequest, tag, width, height)); - } + bids.push(createBid(STATUS.GOOD, bidderRequest, tag, width, height, BIDDER_CODE)); }); } @@ -106,7 +102,7 @@ export const spec = { getUserSyncs: function (syncOptions, serverResponses) { const syncs = []; if (syncOptions.pixelEnabled && serverResponses.length) { - (deepAccess(serverResponses, '0.body.ext.telaria.userSync') || []).forEach(url => syncs.push({type: 'image', url: url})); + (utils.deepAccess(serverResponses, '0.body.ext.telaria.userSync') || []).forEach(url => syncs.push({type: 'image', url: url})); } return syncs; }, @@ -118,7 +114,7 @@ export const spec = { onTimeout: function (timeoutData) { let url = getTimeoutUrl(timeoutData); if (url) { - triggerPixel(url); + utils.triggerPixel(url); } } }; @@ -139,7 +135,7 @@ function getEncodedValIfNotEmpty(val) { * @returns {string} */ function getSupplyChainAsUrlParam(schainObject) { - if (isEmpty(schainObject)) { + if (utils.isEmpty(schainObject)) { return ''; } @@ -161,22 +157,22 @@ function getSupplyChainAsUrlParam(schainObject) { function getUrlParams(params, schainFromBidRequest) { let urlSuffix = ''; - if (!isEmpty(params)) { + if (!utils.isEmpty(params)) { for (let key in params) { - if (key !== 'schain' && params.hasOwnProperty(key) && !isEmpty(params[key])) { + if (key !== 'schain' && params.hasOwnProperty(key) && !utils.isEmpty(params[key])) { urlSuffix += `&${key}=${params[key]}`; } } - urlSuffix += getSupplyChainAsUrlParam(!isEmpty(schainFromBidRequest) ? schainFromBidRequest : params['schain']); + urlSuffix += getSupplyChainAsUrlParam(!utils.isEmpty(schainFromBidRequest) ? schainFromBidRequest : params['schain']); } return urlSuffix; } export const getTimeoutUrl = function(timeoutData) { - let params = deepAccess(timeoutData, '0.params.0'); + let params = utils.deepAccess(timeoutData, '0.params.0'); - if (!isEmpty(params)) { + if (!utils.isEmpty(params)) { let url = `https://${EVENTS_ENDPOINT}`; params = Object.assign({ @@ -199,14 +195,14 @@ export const getTimeoutUrl = function(timeoutData) { * @returns {string} */ function generateUrl(bid, bidderRequest) { - let playerSize = deepAccess(bid, 'mediaTypes.video.playerSize'); + let playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); if (!playerSize) { - logWarn(`Although player size isn't required it is highly recommended`); + utils.logWarn(`Although player size isn't required it is highly recommended`); } let width, height; if (playerSize) { - if (isArray(playerSize) && (playerSize.length === 2) && (!isNaN(playerSize[0]) && !isNaN(playerSize[1]))) { + if (utils.isArray(playerSize) && (playerSize.length === 2) && (!isNaN(playerSize[0]) && !isNaN(playerSize[1]))) { width = playerSize[0]; height = playerSize[1]; } else if (typeof playerSize === 'object') { @@ -215,8 +211,8 @@ function generateUrl(bid, bidderRequest) { } } - let supplyCode = deepAccess(bid, 'params.supplyCode'); - let adCode = deepAccess(bid, 'params.adCode'); + let supplyCode = utils.deepAccess(bid, 'params.supplyCode'); + let adCode = utils.deepAccess(bid, 'params.adCode'); if (supplyCode && adCode) { let url = `https://${supplyCode}.${TAG_ENDPOINT}?adCode=${adCode}`; @@ -257,31 +253,38 @@ function generateUrl(bid, bidderRequest) { } /** - * Create and return a bid response + * Create and return a bid object based on status and tag + * @param status * @param reqBid * @param response * @param width * @param height + * @param bidderCode */ -function createBid(reqBid, response, width, height) { +function createBid(status, reqBid, response, width, height, bidderCode) { + let bid = createBidFactory(status, reqBid); + // TTL 5 mins by default, future support for extended imp wait time - const bid = { - requestId: reqBid.bidId, - cpm: response.price, - creativeId: response.crid || '-1', - vastXml: response.adm, - vastUrl: reqBid.vastUrl, - mediaType: 'video', - width: width, - height: height, - currency: 'USD', - netRevenue: true, - ttl: 300, - ad: response.adm, - meta: {} - }; - - if (response.adomain && response.adomain.length > 0) { + if (response) { + Object.assign(bid, { + requestId: reqBid.bidId, + cpm: response.price, + creativeId: response.crid || '-1', + vastXml: response.adm, + vastUrl: reqBid.vastUrl, + mediaType: 'video', + width: width, + height: height, + bidderCode: bidderCode, + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: response.adm + }); + } + + bid.meta = bid.meta || {}; + if (response && response.adomain && response.adomain.length > 0) { bid.meta.advertiserDomains = response.adomain; } diff --git a/modules/temedyaBidAdapter.js b/modules/temedyaBidAdapter.js index 76a6234c095..4577fb295cd 100644 --- a/modules/temedyaBidAdapter.js +++ b/modules/temedyaBidAdapter.js @@ -1,4 +1,4 @@ -import { parseSizesInput, parseQueryStringParameters, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE } from '../src/mediaTypes.js'; @@ -36,7 +36,7 @@ export const spec = { requestid: req.bidId }; if (mediaType === 'display') { - data.sizes = parseSizesInput( + data.sizes = utils.parseSizesInput( req.mediaTypes && req.mediaTypes.banner && req.mediaTypes.banner.sizes ).join('|') } @@ -44,7 +44,7 @@ export const spec = { return { method: ENDPOINT_METHOD, url: ENDPOINT_URL, - data: parseQueryStringParameters(data), + data: utils.parseQueryStringParameters(data), options: { withCredentials: false, requestId: req.bidId, mediaType: mediaType } }; }); @@ -128,7 +128,7 @@ export const spec = { } return bidResponses; } catch (err) { - logError(err); + utils.logError(err); return []; } }, diff --git a/modules/terceptAnalyticsAdapter.js b/modules/terceptAnalyticsAdapter.js index 748e512bd42..54da2bd06d2 100644 --- a/modules/terceptAnalyticsAdapter.js +++ b/modules/terceptAnalyticsAdapter.js @@ -1,8 +1,8 @@ -import { parseSizesInput, getWindowLocation, buildUrl } from '../src/utils.js'; import { ajax } from '../src/ajax.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; +import * as utils from '../src/utils.js'; const emptyUrl = ''; const analyticsType = 'endpoint'; @@ -56,7 +56,7 @@ function mapBidRequests(params) { requestId: bid.bidderRequestId, auctionId: bid.auctionId, transactionId: bid.transactionId, - sizes: parseSizesInput(bid.mediaTypes.banner.sizes).toString(), + sizes: utils.parseSizesInput(bid.mediaTypes.banner.sizes).toString(), renderStatus: 1, requestTimestamp: params.auctionStart }); @@ -110,13 +110,13 @@ function mapBidResponse(bidResponse, status) { } function send(data, status) { - let location = getWindowLocation(); + let location = utils.getWindowLocation(); if (typeof data !== 'undefined' && typeof data.auctionInit !== 'undefined') { Object.assign(data.auctionInit, { host: location.host, path: location.pathname, search: location.search }); } data.initOptions = initOptions; - let terceptAnalyticsRequestUrl = buildUrl({ + let terceptAnalyticsRequestUrl = utils.buildUrl({ protocol: 'https', hostname: (initOptions && initOptions.hostName) || defaultHostName, pathname: (initOptions && initOptions.pathName) || defaultPathName, diff --git a/modules/theAdxBidAdapter.js b/modules/theAdxBidAdapter.js index d7a79fe74d0..91e36077e88 100644 --- a/modules/theAdxBidAdapter.js +++ b/modules/theAdxBidAdapter.js @@ -1,4 +1,4 @@ -import { logInfo, isEmpty, deepAccess, parseUrl, getDNT, parseSizesInput, _map } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { BANNER, NATIVE, @@ -125,7 +125,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - logInfo('theadx.isBidRequestValid', bid); + utils.logInfo('theadx.isBidRequestValid', bid); let res = false; if (bid && bid.params) { res = !!(bid.params.pid && bid.params.tagId); @@ -141,10 +141,10 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function (validBidRequests, bidderRequest) { - logInfo('theadx.buildRequests', 'validBidRequests', validBidRequests, 'bidderRequest', bidderRequest); + utils.logInfo('theadx.buildRequests', 'validBidRequests', validBidRequests, 'bidderRequest', bidderRequest); let results = []; const requestType = 'POST'; - if (!isEmpty(validBidRequests)) { + if (!utils.isEmpty(validBidRequests)) { results = validBidRequests.map( bidRequest => { return { @@ -176,7 +176,7 @@ export const spec = { * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: (serverResponse, request) => { - logInfo('theadx.interpretResponse', 'serverResponse', serverResponse, ' request', request); + utils.logInfo('theadx.interpretResponse', 'serverResponse', serverResponse, ' request', request); let responses = []; @@ -185,8 +185,8 @@ export const spec = { let seatBids = responseBody.seatbid; - if (!(isEmpty(seatBids) || - isEmpty(seatBids[0].bid))) { + if (!(utils.isEmpty(seatBids) || + utils.isEmpty(seatBids[0].bid))) { let seatBid = seatBids[0]; let bid = seatBid.bid[0]; @@ -280,7 +280,7 @@ export const spec = { * @return {UserSync[]} The user syncs which should be dropped. */ getUserSyncs: function (syncOptions, serverResponses) { - logInfo('theadx.getUserSyncs', 'syncOptions', syncOptions, 'serverResponses', serverResponses) + utils.logInfo('theadx.getUserSyncs', 'syncOptions', syncOptions, 'serverResponses', serverResponses) const syncs = []; if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) { @@ -288,8 +288,8 @@ export const spec = { } serverResponses.forEach(resp => { - const syncIframeUrls = deepAccess(resp, 'body.ext.sync.iframe'); - const syncImageUrls = deepAccess(resp, 'body.ext.sync.image'); + const syncIframeUrls = utils.deepAccess(resp, 'body.ext.sync.iframe'); + const syncImageUrls = utils.deepAccess(resp, 'body.ext.sync.image'); if (syncOptions.iframeEnabled && syncIframeUrls) { syncIframeUrls.forEach(syncIframeUrl => { syncs.push({ @@ -314,7 +314,7 @@ export const spec = { } let buildSiteComponent = (bidRequest, bidderRequest) => { - let loc = parseUrl(bidderRequest.refererInfo.referer, { + let loc = utils.parseUrl(bidderRequest.refererInfo.referer, { decodeSearchAsString: true }); @@ -353,7 +353,7 @@ let buildDeviceComponent = (bidRequest, bidderRequest) => { language: ('language' in navigator) ? navigator.language : null, ua: ('userAgent' in navigator) ? navigator.userAgent : null, devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2, - dnt: getDNT() ? 1 : 0, + dnt: utils.getDNT() ? 1 : 0, }; // Include connection info if available const CONNECTION = navigator.connection || navigator.webkitConnection; @@ -383,14 +383,14 @@ let extractValidSize = (bidRequest, bidderRequest) => { } else { requestedSizes = mediaTypes.video.sizes; } - } else if (!isEmpty(bidRequest.sizes)) { + } else if (!utils.isEmpty(bidRequest.sizes)) { requestedSizes = bidRequest.sizes } // Ensure the size array is normalized - let conformingSize = parseSizesInput(requestedSizes); + let conformingSize = utils.parseSizesInput(requestedSizes); - if (!isEmpty(conformingSize) && conformingSize[0] != null) { + if (!utils.isEmpty(conformingSize) && conformingSize[0] != null) { // Currently only the first size is utilized let splitSizes = conformingSize[0].split('x'); @@ -423,7 +423,7 @@ let generateBannerComponent = (bidRequest, bidderRequest) => { } let generateNativeComponent = (bidRequest, bidderRequest) => { - const assets = _map(bidRequest.mediaTypes.native, (bidParams, key) => { + const assets = utils._map(bidRequest.mediaTypes.native, (bidParams, key) => { const props = NATIVEPROBS[key]; const asset = { required: bidParams.required & 1, diff --git a/modules/timeoutRtdProvider.js b/modules/timeoutRtdProvider.js deleted file mode 100644 index 323a5291e2d..00000000000 --- a/modules/timeoutRtdProvider.js +++ /dev/null @@ -1,181 +0,0 @@ - -import { submodule } from '../src/hook.js'; -import * as ajax from '../src/ajax.js'; -import { logInfo, deepAccess, logError } from '../src/utils.js'; -import { getGlobal } from '../src/prebidGlobal.js'; - -const SUBMODULE_NAME = 'timeout'; - -// this allows the stubbing of functions during testing -export const timeoutRtdFunctions = { - getDeviceType, - getConnectionSpeed, - checkVideo, - calculateTimeoutModifier, - handleTimeoutIncrement -}; - -const entries = Object.entries || function(obj) { - const ownProps = Object.keys(obj); - let i = ownProps.length; - let resArray = new Array(i); - while (i--) { resArray[i] = [ownProps[i], obj[ownProps[i]]]; } - return resArray; -}; - -function getDeviceType() { - const userAgent = window.navigator.userAgent.toLowerCase(); - if ((/ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i.test(userAgent))) { - return 5; // tablet - } - if ((/iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(userAgent))) { - return 4; // mobile - } - return 2; // personal computer -} - -function checkVideo(adUnits) { - return adUnits.some((adUnit) => { - return adUnit.mediaTypes && adUnit.mediaTypes.video; - }); -} - -function getConnectionSpeed() { - const connection = window.navigator.connection || window.navigator.mozConnection || window.navigator.webkitConnection || {} - const connectionType = connection.type || connection.effectiveType; - - switch (connectionType) { - case 'slow-2g': - case '2g': - return 'slow'; - - case '3g': - return 'medium'; - - case 'bluetooth': - case 'cellular': - case 'ethernet': - case 'wifi': - case 'wimax': - case '4g': - return 'fast'; - } - - return 'unknown'; -} -/** - * Calculate the time to be added to the timeout - * @param {Array} adUnits - * @param {Object} rules - * @return {int} - */ -function calculateTimeoutModifier(adUnits, rules) { - logInfo('Timeout rules', rules); - let timeoutModifier = 0; - let toAdd = 0; - - if (rules.includesVideo) { - const hasVideo = timeoutRtdFunctions.checkVideo(adUnits); - toAdd = rules.includesVideo[hasVideo] || 0; - logInfo(`Adding ${toAdd} to timeout for includesVideo ${hasVideo}`) - timeoutModifier += toAdd; - } - - if (rules.numAdUnits) { - const numAdUnits = adUnits.length; - if (rules.numAdUnits[numAdUnits]) { - timeoutModifier += rules.numAdUnits[numAdUnits]; - } else { - for (const [rangeStr, timeoutVal] of entries(rules.numAdUnits)) { - const [lowerBound, upperBound] = rangeStr.split('-'); - if (parseInt(lowerBound) <= numAdUnits && numAdUnits <= parseInt(upperBound)) { - logInfo(`Adding ${timeoutVal} to timeout for numAdUnits ${numAdUnits}`) - timeoutModifier += timeoutVal; - break; - } - } - } - } - - if (rules.deviceType) { - const deviceType = timeoutRtdFunctions.getDeviceType(); - toAdd = rules.deviceType[deviceType] || 0; - logInfo(`Adding ${toAdd} to timeout for deviceType ${deviceType}`) - timeoutModifier += toAdd; - } - - if (rules.connectionSpeed) { - const connectionSpeed = timeoutRtdFunctions.getConnectionSpeed(); - toAdd = rules.connectionSpeed[connectionSpeed] || 0; - logInfo(`Adding ${toAdd} to timeout for connectionSpeed ${connectionSpeed}`) - timeoutModifier += toAdd; - } - - logInfo('timeout Modifier calculated', timeoutModifier); - return timeoutModifier; -} - -/** - * - * @param {Object} reqBidsConfigObj - * @param {function} callback - * @param {Object} config - * @param {Object} userConsent - */ -function getBidRequestData(reqBidsConfigObj, callback, config, userConsent) { - logInfo('Timeout rtd config', config); - const timeoutUrl = deepAccess(config, 'params.endpoint.url'); - if (timeoutUrl) { - logInfo('Timeout url', timeoutUrl); - ajax.ajaxBuilder()(timeoutUrl, { - success: function(response) { - try { - const rules = JSON.parse(response); - timeoutRtdFunctions.handleTimeoutIncrement(reqBidsConfigObj, rules); - } catch (e) { - logError('Error parsing json response from timeout provider.') - } - callback(); - }, - error: function(errorStatus) { - logError('Timeout request error!', errorStatus); - callback(); - } - }); - } else if (deepAccess(config, 'params.rules')) { - timeoutRtdFunctions.handleTimeoutIncrement(reqBidsConfigObj, deepAccess(config, 'params.rules')); - callback(); - } else { - logInfo('No timeout endpoint or timeout rules found. Exiting timeout rtd module'); - callback(); - } -} - -/** - * Gets the timeout modifier, adds it to the bidder timeout, and sets it to reqBidsConfigObj - * @param {Object} reqBidsConfigObj - * @param {Object} rules - */ -function handleTimeoutIncrement(reqBidsConfigObj, rules) { - const adUnits = reqBidsConfigObj.adUnits || getGlobal().adUnits; - const timeoutModifier = timeoutRtdFunctions.calculateTimeoutModifier(adUnits, rules); - const bidderTimeout = getGlobal().getConfig('bidderTimeout'); - reqBidsConfigObj.timeout = bidderTimeout + timeoutModifier; -} - -/** @type {RtdSubmodule} */ -export const timeoutSubmodule = { - /** - * used to link submodule with realTimeData - * @type {string} - */ - name: SUBMODULE_NAME, - init: () => true, - getBidRequestData, -}; - -function registerSubModule() { - submodule('realTimeData', timeoutSubmodule); -} - -registerSubModule(); diff --git a/modules/timeoutRtdProvider.md b/modules/timeoutRtdProvider.md deleted file mode 100644 index 49d1e1fc70a..00000000000 --- a/modules/timeoutRtdProvider.md +++ /dev/null @@ -1,151 +0,0 @@ - --- - layout: page_v2 - title: Timeout Rtd Module - description: Module for managing timeouts in real time - page_type: module - module_type: rtd - module_code : example - enable_download : true - sidebarType : 1 - --- - -## Overview -The timeout RTD module enables publishers to set rules that determine the timeout based on -certain features. It supports rule sets dynamically retrieved from a timeout provider as well as rules -set directly via configuration. -Build the timeout RTD module into the Prebid.js package with: -``` -gulp build --modules=timeoutRtdProvider,rtdModule... -``` - -## Configuration -The module is configured in the realTimeData.dataProviders object. The module will override -`bidderTimeout` in the pbjs config. - -### Timeout Data Provider interface -The timeout RTD module provides an interface of dynamically fetching timeout rules from -a data provider just before the auction begins. The endpoint url is set in the config just as in -the example below, and the timeout data will be used when making bid requests. - -``` -pbjs.setConfig({ - ... - "realTimeData": { - "dataProviders": [{ - "name": 'timeout', - "params": { - "endpoint": { - "url": "http://{cdn-link}.json" - } - } - } - ]}, - - // This value below will be modified by the timeout RTD module if it successfully - // fetches the timeout data. - "bidderTimeout": 1500, - ... -}); -``` - -Sample Endpoint Response: -``` -{ - "rules": { - "includesVideo": { - "true": 200, - "false": 50 - }, - "numAdUnits" : { - "1-5": 100, - "6-10": 200, - "11-15": 300 - }, - "deviceType": { - "2": 50, - "4": 100, - "5": 200 - }, - "connectionSpeed": { - "slow": 200, - "medium": 100, - "fast": 50, - "unknown": 10 - }, -} -``` - -### Rule Handling: -The rules retrieved from the endpoint will be used to add time to the `bidderTimeout` based on certain features such as -the user's deviceType, connection speed, etc. These rules can also be configured statically on page via a `rules` object. -Note that the timeout Module will ignore the static rules if an endpoint url is provided. The timeout rules follow the -format: -``` -{ - '': { - '': - } -} -``` -See bottom of page for examples. - -Currently supported features: - -|Name |Description | Keys | Example -| :------------ | :------------ | :------------ |:------------ | -| includesVideo | Adds time to the timeout based on whether there is a video ad unit in the auction or not | 'true'/'false'| { "true": 200, "false": 50 } | -| numAdUnits | Adds time based on the number of ad units. Ranges in the format `'lowerbound-upperbound` are accepted. This range is inclusive | numbers or number ranges | {"1": 50, "2-5": 100, "6-10": 200} | -| deviceType | Adds time based on device type| 2, 4, or 5| {"2": 50, "4": 100} | -| connectionSpeed | Adds time based on connection speed. `connectionSpeed` defaults to 'unknown' if connection speed cannot be determined | slow, medium, fast, or unknown | { "slow": 200} | - -If there are multiple rules set, all of them would be used and any that apply will be added to the base timeout. For example, if the rules object contains: -``` -{ - "includesVideo": { - "true": 200, - "false": 50 - }, - "numAdUnits" : { - "1-3": 100, - "4-5": 200 - } -} -``` -and there are 3 ad units in the auction, all of which are banner, then the timeout to be added will be 150 milliseconds (50 for `includesVideo[false]` + 100 for `numAdUnits['1-3']`). - -Full example: -``` -pbjs.setConfig({ - ... - "realTimeData": { - "dataProviders": [{ - "name": 'timeout', - "params": { - "rules": { - "includesVideo": { - "true": 200, - "false": 50 - }, - "numAdUnits" : { - "1-5": 100, - "6-10": 200, - "11-15": 300 - }, - "deviceType": { - "2": 50, - "4": 100, - "5": 200 - }, - "connectionSpeed": { - "slow": 200, - "medium": 100, - "fast": 50, - "unknown": 10 - }, - } - } - ]} - ... - // The timeout RTD module will add time to `bidderTimeout` based on the rules set above. - "bidderTimeout": 1500, -``` diff --git a/modules/tpmnBidAdapter.js b/modules/tpmnBidAdapter.js index 88e89bcd64b..ec9d30c0e29 100644 --- a/modules/tpmnBidAdapter.js +++ b/modules/tpmnBidAdapter.js @@ -1,16 +1,13 @@ /* eslint-disable no-tabs */ import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { parseUrl, deepAccess } from '../src/utils.js'; -import { getStorageManager } from '../src/storageManager.js'; +import * as utils from '../src/utils.js'; import { BANNER } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; export const ADAPTER_VERSION = '1'; const SUPPORTED_AD_TYPES = [BANNER]; + const BIDDER_CODE = 'tpmn'; const URL = 'https://ad.tpmn.co.kr/prebidhb.tpmn'; -const IFRAMESYNC = 'https://ad.tpmn.co.kr/sync.tpmn?type=iframe'; -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); export const spec = { code: BIDDER_CODE, @@ -21,20 +18,20 @@ export const spec = { * @param {object} bid The bid to validate. * @return boolean True if this is a valid bid, and false otherwise. */ - isBidRequestValid: function (bid) { + isBidRequestValid: function(bid) { return 'params' in bid && - 'inventoryId' in bid.params && - 'publisherId' in bid.params && - !isNaN(Number(bid.params.inventoryId)) && - bid.params.inventoryId > 0 && - (typeof bid.mediaTypes.banner.sizes != 'undefined'); // only accepting appropriate sizes + 'inventoryId' in bid.params && + 'publisherId' in bid.params && + !isNaN(Number(bid.params.inventoryId)) && + bid.params.inventoryId > 0 && + (typeof bid.mediaTypes.banner.sizes != 'undefined'); // only accepting appropriate sizes }, /** - * @param {BidRequest[]} bidRequests - * @param {*} bidderRequest - * @return {ServerRequest} - */ + * @param {BidRequest[]} bidRequests + * @param {*} bidderRequest + * @return {ServerRequest} + */ buildRequests: (bidRequests, bidderRequest) => { if (bidRequests.length === 0) { return []; @@ -52,11 +49,11 @@ export const spec = { }]; }, /** - * Unpack the response from the server into a list of bids. - * - * @param {serverResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ + * Unpack the response from the server into a list of bids. + * + * @param {serverResponse} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ interpretResponse: function (serverResponse, serverRequest) { if (!Array.isArray(serverResponse.body)) { return []; @@ -66,48 +63,7 @@ export const spec = { // our server directly returns the format needed by prebid.js so no more // transformation is needed here. return bidResults; - }, - - getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) { - const syncArr = []; - if (syncOptions.iframeEnabled) { - let policyParam = ''; - if (gdprConsent && gdprConsent.consentString) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - policyParam += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - policyParam += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; - } - } - if (uspConsent && uspConsent.consentString) { - policyParam += `&ccpa_consent=${uspConsent.consentString}`; - } - const coppa = config.getConfig('coppa') ? 1 : 0; - policyParam += `&coppa=${coppa}`; - syncArr.push({ - type: 'iframe', - url: IFRAMESYNC + policyParam - }) - } else { - syncArr.push({ - type: 'image', - url: 'https://x.bidswitch.net/sync?ssp=tpmn' - }); - syncArr.push({ - type: 'image', - url: 'https://gocm.c.appier.net/tpmn' - }); - syncArr.push({ - type: 'image', - url: 'https://info.mmnneo.com/getGuidRedirect.info?url=https%3A%2F%2Fad.tpmn.co.kr%2Fcookiesync.tpmn%3Ftpmn_nid%3Dbf91e8b3b9d3f1af3fc1d657f090b4fb%26tpmn_buid%3D' - }); - syncArr.push({ - type: 'image', - url: 'https://sync.aralego.com/idSync?redirect=https%3A%2F%2Fad.tpmn.co.kr%2FpixelCt.tpmn%3Ftpmn_nid%3Dde91e8b3b9d3f1af3fc1d657f090b815%26tpmn_buid%3DSspCookieUserId' - }); - } - return syncArr; - }, + } }; registerBidder(spec); @@ -116,7 +72,7 @@ registerBidder(spec); * Creates site description object */ function createSite(refInfo) { - let url = parseUrl(refInfo.referer); + let url = utils.parseUrl(refInfo.referer); let site = { 'domain': url.hostname, 'page': url.protocol + '://' + url.hostname + url.pathname @@ -146,7 +102,7 @@ function parseSizes(sizes) { } function getBannerSizes(bidRequest) { - return parseSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes); + return parseSizes(utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes); } function bidToRequest(bid) { diff --git a/modules/trionBidAdapter.js b/modules/trionBidAdapter.js index 5750406116b..e9e030ce33f 100644 --- a/modules/trionBidAdapter.js +++ b/modules/trionBidAdapter.js @@ -1,12 +1,13 @@ -import { getBidIdParameter, parseSizesInput, tryAppendQueryString } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { getStorageManager } from '../src/storageManager.js'; +const storage = getStorageManager(); + const BID_REQUEST_BASE_URL = 'https://in-appadvertising.com/api/bidRequest'; const USER_SYNC_URL = 'https://in-appadvertising.com/api/userSync.html'; const BIDDER_CODE = 'trion'; const BASE_KEY = '_trion_'; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); export const spec = { code: BIDDER_CODE, @@ -111,11 +112,11 @@ function getPublisherUrl() { } function buildTrionUrlParams(bid, bidderRequest) { - var pubId = getBidIdParameter('pubId', bid.params); - var sectionId = getBidIdParameter('sectionId', bid.params); + var pubId = utils.getBidIdParameter('pubId', bid.params); + var sectionId = utils.getBidIdParameter('sectionId', bid.params); var url = getPublisherUrl(); var bidSizes = getBidSizesFromBidRequest(bid); - var sizes = parseSizesInput(bidSizes).join(','); + var sizes = utils.parseSizesInput(bidSizes).join(','); var isAutomated = (navigator && navigator.webdriver) ? '1' : '0'; var isHidden = (document.hidden) ? '1' : '0'; var visibilityState = encodeURIComponent(document.visibilityState); @@ -130,10 +131,10 @@ function buildTrionUrlParams(bid, bidderRequest) { setStorageData(BASE_KEY + 'lps', pubId + ':' + sectionId); var trionUrl = ''; - trionUrl = tryAppendQueryString(trionUrl, 'bidId', bid.bidId); - trionUrl = tryAppendQueryString(trionUrl, 'pubId', pubId); - trionUrl = tryAppendQueryString(trionUrl, 'sectionId', sectionId); - trionUrl = tryAppendQueryString(trionUrl, 'vers', '$prebid.version$'); + trionUrl = utils.tryAppendQueryString(trionUrl, 'bidId', bid.bidId); + trionUrl = utils.tryAppendQueryString(trionUrl, 'pubId', pubId); + trionUrl = utils.tryAppendQueryString(trionUrl, 'sectionId', sectionId); + trionUrl = utils.tryAppendQueryString(trionUrl, 'vers', '$prebid.version$'); if (url) { trionUrl += 'url=' + url + '&'; } @@ -141,22 +142,22 @@ function buildTrionUrlParams(bid, bidderRequest) { trionUrl += 'sizes=' + sizes + '&'; } if (intT) { - trionUrl = tryAppendQueryString(trionUrl, 'int_t', encodeURIComponent(intT)); + trionUrl = utils.tryAppendQueryString(trionUrl, 'int_t', encodeURIComponent(intT)); } - trionUrl = tryAppendQueryString(trionUrl, 'tr_wd', isAutomated); - trionUrl = tryAppendQueryString(trionUrl, 'tr_hd', isHidden); - trionUrl = tryAppendQueryString(trionUrl, 'tr_vs', visibilityState); + trionUrl = utils.tryAppendQueryString(trionUrl, 'tr_wd', isAutomated); + trionUrl = utils.tryAppendQueryString(trionUrl, 'tr_hd', isHidden); + trionUrl = utils.tryAppendQueryString(trionUrl, 'tr_vs', visibilityState); if (bidderRequest && bidderRequest.gdprConsent) { var gdpr = bidderRequest.gdprConsent; if (gdpr) { if (gdpr.consentString) { - trionUrl = tryAppendQueryString(trionUrl, 'gdprc', encodeURIComponent(gdpr.consentString)); + trionUrl = utils.tryAppendQueryString(trionUrl, 'gdprc', encodeURIComponent(gdpr.consentString)); } - trionUrl = tryAppendQueryString(trionUrl, 'gdpr', (gdpr.gdprApplies ? 1 : 0)); + trionUrl = utils.tryAppendQueryString(trionUrl, 'gdpr', (gdpr.gdprApplies ? 1 : 0)); } } if (bidderRequest && bidderRequest.uspConsent) { - trionUrl = tryAppendQueryString(trionUrl, 'usp', encodeURIComponent(bidderRequest.uspConsent)); + trionUrl = utils.tryAppendQueryString(trionUrl, 'usp', encodeURIComponent(bidderRequest.uspConsent)); } // remove the trailing "&" if (trionUrl.lastIndexOf('&') === trionUrl.length - 1) { diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 7e964661db6..e8d248eea03 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -1,13 +1,11 @@ -import { tryAppendQueryString, logMessage, logError, isEmpty, isStr, isPlainObject, isArray, logWarn } from '../src/utils.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; const GVLID = 28; const BIDDER_CODE = 'triplelift'; const STR_ENDPOINT = 'https://tlx.3lift.com/header/auction?'; -const BANNER_TIME_TO_LIVE = 300; -const INSTREAM_TIME_TO_LIVE = 3600; let gdprApplies = true; let consentString = null; @@ -23,41 +21,41 @@ export const tripleliftAdapterSpec = { let tlCall = STR_ENDPOINT; let data = _buildPostBody(bidRequests); - tlCall = tryAppendQueryString(tlCall, 'lib', 'prebid'); - tlCall = tryAppendQueryString(tlCall, 'v', '$prebid.version$'); + tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid'); + tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$'); if (bidderRequest && bidderRequest.refererInfo) { let referrer = bidderRequest.refererInfo.referer; - tlCall = tryAppendQueryString(tlCall, 'referrer', referrer); + tlCall = utils.tryAppendQueryString(tlCall, 'referrer', referrer); } if (bidderRequest && bidderRequest.timeout) { - tlCall = tryAppendQueryString(tlCall, 'tmax', bidderRequest.timeout); + tlCall = utils.tryAppendQueryString(tlCall, 'tmax', bidderRequest.timeout); } if (bidderRequest && bidderRequest.gdprConsent) { if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { gdprApplies = bidderRequest.gdprConsent.gdprApplies; - tlCall = tryAppendQueryString(tlCall, 'gdpr', gdprApplies.toString()); + tlCall = utils.tryAppendQueryString(tlCall, 'gdpr', gdprApplies.toString()); } if (typeof bidderRequest.gdprConsent.consentString !== 'undefined') { consentString = bidderRequest.gdprConsent.consentString; - tlCall = tryAppendQueryString(tlCall, 'cmp_cs', consentString); + tlCall = utils.tryAppendQueryString(tlCall, 'cmp_cs', consentString); } } if (bidderRequest && bidderRequest.uspConsent) { - tlCall = tryAppendQueryString(tlCall, 'us_privacy', bidderRequest.uspConsent); + tlCall = utils.tryAppendQueryString(tlCall, 'us_privacy', bidderRequest.uspConsent); } if (config.getConfig('coppa') === true) { - tlCall = tryAppendQueryString(tlCall, 'coppa', true); + tlCall = utils.tryAppendQueryString(tlCall, 'coppa', true); } if (tlCall.lastIndexOf('&') === tlCall.length - 1) { tlCall = tlCall.substring(0, tlCall.length - 1); } - logMessage('tlCall request built: ' + tlCall); + utils.logMessage('tlCall request built: ' + tlCall); return { method: 'POST', @@ -81,17 +79,17 @@ export const tripleliftAdapterSpec = { let syncEndpoint = 'https://eb2.3lift.com/sync?'; if (syncType === 'image') { - syncEndpoint = tryAppendQueryString(syncEndpoint, 'px', 1); - syncEndpoint = tryAppendQueryString(syncEndpoint, 'src', 'prebid'); + syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'px', 1); + syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'src', 'prebid'); } if (consentString !== null) { - syncEndpoint = tryAppendQueryString(syncEndpoint, 'gdpr', gdprApplies); - syncEndpoint = tryAppendQueryString(syncEndpoint, 'cmp_cs', consentString); + syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'gdpr', gdprApplies); + syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'cmp_cs', consentString); } if (usPrivacy) { - syncEndpoint = tryAppendQueryString(syncEndpoint, 'us_privacy', usPrivacy); + syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'us_privacy', usPrivacy); } return [{ @@ -124,7 +122,7 @@ function _buildPostBody(bidRequests) { } else if (bidRequest.mediaTypes.banner) { imp.banner = { format: _sizes(bidRequest.sizes) }; }; - if (!isEmpty(bidRequest.ortb2Imp)) { + if (!utils.isEmpty(bidRequest.ortb2Imp)) { imp.fpd = _getAdUnitFpd(bidRequest.ortb2Imp); } return imp; @@ -145,7 +143,7 @@ function _buildPostBody(bidRequests) { let ext = _getExt(schain, globalFpd); - if (!isEmpty(ext)) { + if (!utils.isEmpty(ext)) { data.ext = ext; } return data; @@ -175,18 +173,14 @@ function _getORTBVideo(bidRequest) { function _getFloor (bid) { let floor = null; if (typeof bid.getFloor === 'function') { - try { - const floorInfo = bid.getFloor({ - currency: 'USD', - mediaType: _isInstreamBidRequest(bid) ? 'video' : 'banner', - size: '*' - }); - if (typeof floorInfo === 'object' && - floorInfo.currency === 'USD' && !isNaN(parseFloat(floorInfo.floor))) { - floor = parseFloat(floorInfo.floor); - } - } catch (err) { - logError('Triplelift: getFloor threw an error: ', err); + const floorInfo = bid.getFloor({ + currency: 'USD', + mediaType: _isInstreamBidRequest(bid) ? 'video' : 'banner', + size: '*' + }); + if (typeof floorInfo === 'object' && + floorInfo.currency === 'USD' && !isNaN(parseFloat(floorInfo.floor))) { + floor = parseFloat(floorInfo.floor); } } return floor !== null ? floor : bid.params.floor; @@ -196,18 +190,18 @@ function _getGlobalFpd() { const fpd = {}; const context = {} const user = {}; - const ortbData = config.getConfig('ortb2') || {}; + const ortbData = config.getLegacyFpd(config.getConfig('ortb2')) || {}; - const fpdContext = Object.assign({}, ortbData.site); + const fpdContext = Object.assign({}, ortbData.context); const fpdUser = Object.assign({}, ortbData.user); _addEntries(context, fpdContext); _addEntries(user, fpdUser); - if (!isEmpty(context)) { + if (!utils.isEmpty(context)) { fpd.context = context; } - if (!isEmpty(user)) { + if (!utils.isEmpty(user)) { fpd.user = user; } return fpd; @@ -219,7 +213,7 @@ function _getAdUnitFpd(adUnitFpd) { _addEntries(context, adUnitFpd.ext); - if (!isEmpty(context)) { + if (!utils.isEmpty(context)) { fpd.context = context; } @@ -227,7 +221,7 @@ function _getAdUnitFpd(adUnitFpd) { } function _addEntries(target, source) { - if (!isEmpty(source)) { + if (!utils.isEmpty(source)) { Object.keys(source).forEach(key => { if (source[key] != null) { target[key] = source[key]; @@ -238,10 +232,10 @@ function _addEntries(target, source) { function _getExt(schain, fpd) { let ext = {}; - if (!isEmpty(schain)) { + if (!utils.isEmpty(schain)) { ext.schain = { ...schain }; } - if (!isEmpty(fpd)) { + if (!utils.isEmpty(fpd)) { ext.fpd = { ...fpd }; } return ext; @@ -266,36 +260,19 @@ function getPubCommonEids(bidRequest) { function getEids(bidRequest, type, source, rtiPartner) { return bidRequest .map(getUserId(type)) // bids -> userIds of a certain type - .filter(filterEids(type)) // filter out unqualified userIds + .filter((x) => !!x) // filter out null userIds .map(formatEid(source, rtiPartner)); // userIds -> eid objects } -const filterEids = type => (userId, i, arr) => { - let isValidUserId = - !!userId && // is not null nor empty - (isStr(userId) - ? !!userId - : isPlainObject(userId) && // or, is object - !isArray(userId) && // not an array - !isEmpty(userId) && // is not empty - userId.id && // contains nested id field - isStr(userId.id) && // nested id field is a string - !!userId.id); // that is not empty - if (!isValidUserId && arr[0] !== undefined) { - logWarn(`Triplelift: invalid ${type} userId format`); - } - return isValidUserId; -}; - function getUserId(type) { - return bid => bid && bid.userId && bid.userId[type]; + return (bid) => (bid && bid.userId && bid.userId[type]); } function formatEid(source, rtiPartner) { - return (userId) => ({ + return (id) => ({ source, uids: [{ - id: userId.id ? userId.id : userId, + id, ext: { rtiPartner } }] }); @@ -334,7 +311,7 @@ function _buildResponseObject(bidderRequest, bid) { creativeId: creativeId, dealId: dealId, currency: 'USD', - ttl: BANNER_TIME_TO_LIVE, + ttl: 300, tl_source: bid.tl_source, meta: {} }; @@ -342,7 +319,6 @@ function _buildResponseObject(bidderRequest, bid) { if (_isInstreamBidRequest(breq)) { bidResponse.vastXml = bid.ad; bidResponse.mediaType = 'video'; - bidResponse.ttl = INSTREAM_TIME_TO_LIVE; }; if (bid.advertiser_name) { diff --git a/modules/truereachBidAdapter.js b/modules/truereachBidAdapter.js index a0244e3a349..fadc952b5fb 100755 --- a/modules/truereachBidAdapter.js +++ b/modules/truereachBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, getUniqueIdentifierStr } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER } from '../src/mediaTypes.js'; @@ -13,7 +13,7 @@ export const spec = { isBidRequestValid: function (bidRequest) { return (bidRequest.params.site_id && bidRequest.params.bidfloor && - deepAccess(bidRequest, 'mediaTypes.banner') && (deepAccess(bidRequest, 'mediaTypes.banner.sizes.length') > 0)); + utils.deepAccess(bidRequest, 'mediaTypes.banner') && (utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes.length') > 0)); }, buildRequests: function (validBidRequests, bidderRequest) { @@ -23,7 +23,7 @@ export const spec = { let queryParams = buildCommonQueryParamsFromBids(validBidRequests, bidderRequest); - let siteId = deepAccess(validBidRequests[0], 'params.site_id'); + let siteId = utils.deepAccess(validBidRequests[0], 'params.site_id'); let url = BIDDER_URL + siteId + '?hb=1&transactionId=' + validBidRequests[0].transactionId; @@ -121,7 +121,7 @@ function buildCommonQueryParamsFromBids(validBidRequests, bidderRequest) { let page = window.location.host + window.location.pathname + location.search + location.hash; let defaultParams = { - id: getUniqueIdentifierStr(), + id: utils.getUniqueIdentifierStr(), imp: [ { id: validBidRequests[0].bidId, diff --git a/modules/trustpidSystem.js b/modules/trustpidSystem.js deleted file mode 100644 index 051775fa777..00000000000 --- a/modules/trustpidSystem.js +++ /dev/null @@ -1,197 +0,0 @@ -/** - * This module adds TrustPid provided by Vodafone Sales and Services Limited to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/trustpidSystem - * @requires module:modules/userId - */ -import { logInfo, logError } from '../src/utils.js'; -import { submodule } from '../src/hook.js'; -import { getStorageManager } from '../src/storageManager.js'; - -const MODULE_NAME = 'trustpid'; -const LOG_PREFIX = 'Trustpid module' -let mnoAcronym = ''; -let mnoDomain = ''; - -export const storage = getStorageManager({gvlid: null, moduleName: MODULE_NAME}); - -/** - * Handle an event for an iframe. - * Takes the body.url parameter from event and returns the string domain. - * i.e.: "fc.vodafone.de" - * @param event - */ -function messageHandler(event) { - let msg; - try { - if (event && event.data && typeof event.data === 'string' && event.data) { - msg = JSON.parse(event.data); - if (msg.msgType === 'MNOSELECTOR' && msg.body && msg.body.url) { - let URL = msg.body.url.split('//'); - let domainURL = URL[1].split('/'); - mnoDomain = domainURL[0]; - logInfo(`${LOG_PREFIX}: Message handler set domain to ${mnoDomain}`); - getDomainAcronym(mnoDomain); - } - } - } catch (e) { - logError(e); - } -} - -/** - * Properly sets the trustpid acronym depending on the domain value. - * @param domain - */ -function getDomainAcronym(domain) { - let acronym = ''; - const prefix = '-'; - switch (domain) { - case 'tmi.mno.link': - acronym = 'ndye'; - break; - case 'tmi.vodafone.de': - acronym = 'pqnx'; - break; - case 'tmi.telekom.de': - acronym = 'avgw'; - break; - case 'tmi.tmid.es': - acronym = 'kjws'; - break; - case 'uat.mno.link': - acronym = 'xxxx'; - break; - case 'es.tmiservice.orange.com': - acronym = 'aplw'; - break; - default: - return 'none'; - } - return mnoAcronym = prefix + acronym; -} - -// Set a listener to handle the iframe response message. -window.addEventListener('message', messageHandler, false); - -/** - * Get the "umid" from html5 local storage to make it available to the UserId module. - * @param config - * @returns {{trustpid: (*|string), acr: (string)}} - */ -function getTrustpidFromStorage() { - // Get the domain either from localStorage or global - let domain = JSON.parse(storage.getDataFromLocalStorage('fcIdConnectDomain')) || mnoDomain; - logInfo(`${LOG_PREFIX}: Local storage domain: ${domain}`); - - if (!domain) { - logInfo(`${LOG_PREFIX}: Local storage domain not found, returning null`); - return { - trustpid: null, - acr: null, - }; - } - - // Get the acronym from global - let acronym = mnoAcronym; - // if acronym is empty, but "domain" is available, get the acronym from domain - if (!acronym) { - getDomainAcronym(domain); - acronym = mnoAcronym; - } - - logInfo(`${LOG_PREFIX}: Domain acronym found: ${acronym}`); - - // Domain is correct in both local storage and idGraph, but no acronym is existing for the domain - if (domain && !acronym) { - return { - trustpid: null, - acr: null - } - } - - let fcIdConnectObject; - let fcIdConnectData = JSON.parse(storage.getDataFromLocalStorage('fcIdConnectData')); - logInfo(`${LOG_PREFIX}: Local storage fcIdConnectData: ${JSON.stringify(fcIdConnectData)}`); - - if (fcIdConnectData && - fcIdConnectData.connectId && - Array.isArray(fcIdConnectData.connectId.idGraph) && - fcIdConnectData.connectId.idGraph.length > 0) { - fcIdConnectObject = fcIdConnectData.connectId.idGraph.find(item => { - return item.domain === domain; - }); - } - logInfo(`${LOG_PREFIX}: Local storage fcIdConnectObject for domain: ${JSON.stringify(fcIdConnectObject)}`); - - return { - trustpid: (fcIdConnectObject && fcIdConnectObject.umid) - ? fcIdConnectObject.umid - : null, - acr: acronym, - }; -} - -/** @type {Submodule} */ -export const trustpidSubmodule = { - /** - * Used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - /** - * Decodes the stored id value for passing to bid requests. - * @function - * @returns {{trustpid: string} | null} - */ - decode(bidId) { - logInfo(`${LOG_PREFIX}: Decoded ID value ${JSON.stringify(bidId)}`); - return bidId.trustpid ? bidId : null; - }, - /** - * Get the id from helper function and initiate a new user sync. - * @param config - * @returns {{callback: result}|{id: {trustpid: string}}} - */ - getId: function(config) { - const data = getTrustpidFromStorage(); - if (data.trustpid) { - logInfo(`${LOG_PREFIX}: Local storage ID value ${JSON.stringify(data)}`); - return {id: {trustpid: data.trustpid + data.acr}}; - } else { - if (!config) { - config = {}; - } - if (!config.params) { - config.params = {}; - } - if (typeof config.params.maxDelayTime === 'undefined' || config.params.maxDelayTime === null) { - config.params.maxDelayTime = 1000; - } - // Current delay and delay step in milliseconds - let currentDelay = 0; - const delayStep = 50; - const result = (callback) => { - const data = getTrustpidFromStorage(); - if (!data.trustpid) { - if (currentDelay > config.params.maxDelayTime) { - logInfo(`${LOG_PREFIX}: No trustpid value set after ${config.params.maxDelayTime} max allowed delay time`); - callback(null); - } else { - currentDelay += delayStep; - setTimeout(() => { - result(callback); - }, delayStep); - } - } else { - const dataToReturn = { trustpid: data.trustpid + data.acr }; - logInfo(`${LOG_PREFIX}: Returning ID value data of ${JSON.stringify(dataToReturn)}`); - callback(dataToReturn); - } - }; - return { callback: result }; - } - }, -}; - -submodule('userId', trustpidSubmodule); diff --git a/modules/trustpidSystem.md b/modules/trustpidSystem.md deleted file mode 100644 index c4309c9d807..00000000000 --- a/modules/trustpidSystem.md +++ /dev/null @@ -1,45 +0,0 @@ -## trustpid User Id Submodule - -trustpid User Id Module. - -First, make sure to add the trustpid submodule to your Prebid.js package with: - -``` -gulp build --modules=userId,adfBidAdapter,trustpidSystem -``` - -The following configuration parameters are available: - -``` -pbjs.setConfig({ - userSync: { - userIds: [ - { - name: 'trustpid', - params: { - maxDelayTime: 1000, - }, - bidders: ["adf"], - storage: { - type: "html5", - name: "trustpid", - expires: 1, //days - }, - } - ], - } -}); -``` - -## Parameter Descriptions - -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of the module | `"trustpid"` -| params | Required | Object | Object with configuration parameters for trustpid User Id submodule | - | -| params.maxDelayTime | Required | Integer | Max amount of time (in seconds) before looking into storage for data | 2500 | -| bidders | Required | Array of Strings | An array of bidder codes to which this user ID may be sent. Currently required and supporting AdformOpenRTB | `["adf"]` | -| storage | Required | Object | Local storage configuration object | - | -| storage.type | Required | String | Type of the storage that would be used to store user ID. Must be `"html5"` to utilise HTML5 local storage. | `"html5"` | -| storage.name | Required | String | The name of the key in local storage where the user ID will be stored. | `"trustpid"` | -| storage.expires | Required | Integer | How long (in days) the user ID information will be stored. For safety reasons, this information is required.| `1` | \ No newline at end of file diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js index 7d40a0b0452..66574e4fe57 100644 --- a/modules/trustxBidAdapter.js +++ b/modules/trustxBidAdapter.js @@ -1,13 +1,15 @@ -import {isEmpty, deepAccess, logError, logWarn, parseGPTSingleSizeArrayToRtbSize, mergeDeep} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { Renderer } from '../src/Renderer.js'; import { VIDEO, BANNER } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; const BIDDER_CODE = 'trustx'; -const ENDPOINT_URL = 'https://grid.bidswitch.net/hbjson?sp=trustx'; +const ENDPOINT_URL = 'https://sofia.trustx.org/hb'; +const NEW_ENDPOINT_URL = 'https://grid.bidswitch.net/hbjson?sp=trustx'; +const ADDITIONAL_SYNC_URL = 'https://x.bidswitch.net/sync?ssp=themediagrid'; const TIME_TO_LIVE = 360; -const ADAPTER_SYNC_URL = 'https://x.bidswitch.net/sync?ssp=themediagrid'; +const ADAPTER_SYNC_URL = 'https://sofia.trustx.org/push_sync'; const RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; const LOG_ERROR_MESS = { @@ -21,7 +23,6 @@ const LOG_ERROR_MESS = { hasEmptySeatbidArray: 'Response has empty seatbid array', hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' }; - export const spec = { code: BIDDER_CODE, supportedMediaTypes: [ BANNER, VIDEO ], @@ -38,240 +39,40 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {BidRequest[]} validBidRequests - an array of bids - * @param {bidderRequest} bidderRequest bidder request object + * @param {bidderRequest} - bidder request object * @return ServerRequest Info describing the request to the server. */ buildRequests: function(validBidRequests, bidderRequest) { - if (!validBidRequests.length) { - return null; - } - let pageKeywords = null; - let jwpseg = null; - let permutiveseg = null; - let content = null; - let schain = null; - let userId = null; - let userIdAsEids = null; - let user = null; - let userExt = null; - let {bidderRequestId, auctionId, gdprConsent, uspConsent, timeout, refererInfo} = bidderRequest || {}; - - const referer = refererInfo ? encodeURIComponent(refererInfo.referer) : ''; - const imp = []; - const bidsMap = {}; - - validBidRequests.forEach((bid) => { - if (!bidderRequestId) { - bidderRequestId = bid.bidderRequestId; - } - if (!auctionId) { - auctionId = bid.auctionId; - } - if (!schain) { - schain = bid.schain; - } - if (!userId) { - userId = bid.userId; - } - if (!userIdAsEids) { - userIdAsEids = bid.userIdAsEids; - } - const {params: {uid, keywords}, mediaTypes, bidId, adUnitCode, rtd, ortb2Imp} = bid; - bidsMap[bidId] = bid; - const bidFloor = _getFloor(mediaTypes || {}, bid); - if (rtd) { - const jwTargeting = rtd.jwplayer && rtd.jwplayer.targeting; - if (jwTargeting) { - if (!jwpseg && jwTargeting.segments) { - jwpseg = jwTargeting.segments; - } - if (!content && jwTargeting.content) { - content = jwTargeting.content; - } - } - const permutiveTargeting = rtd.p_standard && rtd.p_standard.targeting; - if (!permutiveseg && permutiveTargeting && permutiveTargeting.segments) { - permutiveseg = permutiveTargeting.segments; - } - } - let impObj = { - id: bidId && bidId.toString(), - tagid: uid.toString(), - ext: { - divid: adUnitCode && adUnitCode.toString() - } - }; - - if (ortb2Imp) { - if (ortb2Imp.instl) { - impObj.instl = ortb2Imp.instl; - } - if (ortb2Imp.ext && ortb2Imp.ext.data) { - impObj.ext.data = ortb2Imp.ext.data; - if (impObj.ext.data.adserver && impObj.ext.data.adserver.adslot) { - impObj.ext.gpid = impObj.ext.data.adserver.adslot.toString(); - } else { - impObj.ext.gpid = ortb2Imp.ext.data.pbadslot && ortb2Imp.ext.data.pbadslot.toString(); - } - } - } - - if (!isEmpty(keywords)) { - if (!pageKeywords) { - pageKeywords = keywords; - } - impObj.ext.bidder = { keywords }; - } - - if (bidFloor) { - impObj.bidfloor = bidFloor; - } - - if (!mediaTypes || mediaTypes[BANNER]) { - const banner = createBannerRequest(bid, mediaTypes ? mediaTypes[BANNER] : {}); - if (banner) { - impObj.banner = banner; - } - } - if (mediaTypes && mediaTypes[VIDEO]) { - const video = createVideoRequest(bid, mediaTypes[VIDEO]); - if (video) { - impObj.video = video; - } - } - - if (impObj.banner || impObj.video) { - imp.push(impObj); + const bids = validBidRequests || []; + const newFormatBids = []; + const oldFormatBids = []; + const requests = []; + bids.forEach(bid => { + if (bid.params.useNewFormat) { + newFormatBids.push(bid); + } else { + oldFormatBids.push(bid); } }); - - const source = { - tid: auctionId && auctionId.toString(), - ext: { - wrapper: 'Prebid_js', - wrapper_version: '$prebid.version$' + if (newFormatBids.length) { + const newFormatRequests = newFormatRequest(newFormatBids, bidderRequest); + if (newFormatRequests) { + requests.push(newFormatRequests); } - }; - - if (schain) { - source.ext.schain = schain; - } - - const bidderTimeout = config.getConfig('bidderTimeout') || timeout; - const tmax = timeout ? Math.min(bidderTimeout, timeout) : bidderTimeout; - - let request = { - id: bidderRequestId && bidderRequestId.toString(), - site: { - page: referer - }, - tmax, - source, - imp - }; - - if (content) { - request.site.content = content; } - - if (jwpseg && jwpseg.length) { - user = { - data: [{ - name: 'iow_labs_pub_data', - segment: segmentProcessing(jwpseg, 'jwpseg'), - }] - }; - } - - const ortb2UserData = config.getConfig('ortb2.user.data'); - if (ortb2UserData && ortb2UserData.length) { - if (!user) { - user = { data: [] }; + if (oldFormatBids.length) { + const oldFormatRequests = oldFormatRequest(oldFormatBids, bidderRequest); + if (oldFormatRequests) { + requests.push(oldFormatRequests); } - user = mergeDeep(user, { - data: [...ortb2UserData] - }); - } - - if (gdprConsent && gdprConsent.consentString) { - userExt = {consent: gdprConsent.consentString}; - } - - if (userIdAsEids && userIdAsEids.length) { - userExt = userExt || {}; - userExt.eids = [...userIdAsEids]; - } - - if (userExt && Object.keys(userExt).length) { - user = user || {}; - user.ext = userExt; - } - - if (user) { - request.user = user; } - - const userKeywords = deepAccess(config.getConfig('ortb2.user'), 'keywords') || null; - const siteKeywords = deepAccess(config.getConfig('ortb2.site'), 'keywords') || null; - - if (userKeywords) { - pageKeywords = pageKeywords || {}; - pageKeywords.user = pageKeywords.user || {}; - pageKeywords.user.ortb2 = [ - { - name: 'keywords', - keywords: userKeywords.split(','), - } - ]; - } - if (siteKeywords) { - pageKeywords = pageKeywords || {}; - pageKeywords.site = pageKeywords.site || {}; - pageKeywords.site.ortb2 = [ - { - name: 'keywords', - keywords: siteKeywords.split(','), - } - ]; - } - - if (pageKeywords) { - pageKeywords = reformatKeywords(pageKeywords); - if (pageKeywords) { - request.ext = { - keywords: pageKeywords - }; - } - } - - if (gdprConsent && gdprConsent.gdprApplies) { - request.regs = { - ext: { - gdpr: gdprConsent.gdprApplies ? 1 : 0 - } - } - } - - if (uspConsent) { - if (!request.regs) { - request.regs = {ext: {}}; - } - request.regs.ext.us_privacy = uspConsent; - } - - return { - method: 'POST', - url: ENDPOINT_URL, - data: JSON.stringify(request), - bidsMap - }; + return requests; }, /** * Unpack the response from the server into a list of bids. * * @param {*} serverResponse A successful response from the server. * @param {*} bidRequest - * @param {*} RendererConst * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: function(serverResponse, bidRequest, RendererConst = Renderer) { @@ -290,17 +91,17 @@ export const spec = { _addBidResponse(_getBidFromResponse(respItem), bidRequest, bidResponses, RendererConst); }); } - if (errorMessage) logError(errorMessage); + if (errorMessage) utils.logError(errorMessage); return bidResponses; }, getUserSyncs: function(syncOptions, responses, gdprConsent, uspConsent) { if (syncOptions.pixelEnabled) { + const syncsPerBidder = config.getConfig('userSync.syncsPerBidder'); let params = []; - if (gdprConsent) { + if (gdprConsent && typeof gdprConsent.consentString === 'string') { if (typeof gdprConsent.gdprApplies === 'boolean') { - params.push(`gdpr=${Number(gdprConsent.gdprApplies)}`); - } - if (typeof gdprConsent.consentString === 'string') { + params.push(`gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`); + } else { params.push(`gdpr_consent=${gdprConsent.consentString}`); } } @@ -308,21 +109,38 @@ export const spec = { params.push(`us_privacy=${uspConsent}`); } const stringParams = params.join('&'); - return { + const syncs = [{ type: 'image', - url: ADAPTER_SYNC_URL + stringParams - }; + url: ADAPTER_SYNC_URL + (stringParams ? `?${stringParams}` : '') + }]; + if (syncsPerBidder > 1) { + syncs.push({ + type: 'image', + url: ADDITIONAL_SYNC_URL + (stringParams ? `&${stringParams}` : '') + }); + } + return syncs; } } } +function isPopulatedArray(arr) { + return !!(utils.isArray(arr) && arr.length > 0); +} + +function deleteValues(keyPairObj) { + if (isPopulatedArray(keyPairObj.value) && keyPairObj.value[0] === '') { + delete keyPairObj.value; + } +} + function _getBidFromResponse(respItem) { if (!respItem) { - logError(LOG_ERROR_MESS.emptySeatbid); + utils.logError(LOG_ERROR_MESS.emptySeatbid); } else if (!respItem.bid) { - logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); } else if (!respItem.bid[0]) { - logError(LOG_ERROR_MESS.noBid); + utils.logError(LOG_ERROR_MESS.noBid); } return respItem && respItem.bid && respItem.bid[0]; } @@ -331,10 +149,25 @@ function _addBidResponse(serverBid, bidRequest, bidResponses, RendererConst) { if (!serverBid) return; let errorMessage; if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); - if (!serverBid.adm && !serverBid.nurl) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); else { - const { bidsMap } = bidRequest; - const bid = bidsMap[serverBid.impid]; + const { bidsMap, priceType, newFormat } = bidRequest; + let bid; + let slot; + if (newFormat) { + bid = bidsMap[serverBid.impid]; + } else { + const awaitingBids = bidsMap[serverBid.auid]; + if (awaitingBids) { + const sizeId = `${serverBid.w}x${serverBid.h}`; + if (awaitingBids[sizeId]) { + slot = awaitingBids[sizeId][0]; + bid = slot.bids.shift(); + } + } else { + errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; + } + } if (!errorMessage && bid) { const bidResponse = { @@ -344,7 +177,7 @@ function _addBidResponse(serverBid, bidRequest, bidResponses, RendererConst) { height: serverBid.h, creativeId: serverBid.auid, // bid.bidId, currency: 'USD', - netRevenue: false, + netRevenue: newFormat ? false : priceType !== 'gross', ttl: TIME_TO_LIVE, dealId: serverBid.dealid, meta: { @@ -352,15 +185,11 @@ function _addBidResponse(serverBid, bidRequest, bidResponses, RendererConst) { }, }; if (serverBid.content_type === 'video') { - if (serverBid.adm) { - bidResponse.vastXml = serverBid.adm; - bidResponse.adResponse = { - content: bidResponse.vastXml - }; - } else if (serverBid.nurl) { - bidResponse.vastUrl = serverBid.nurl; - } + bidResponse.vastXml = serverBid.adm; bidResponse.mediaType = VIDEO; + bidResponse.adResponse = { + content: bidResponse.vastXml + }; if (!bid.renderer && (!bid.mediaTypes || !bid.mediaTypes.video || bid.mediaTypes.video.context === 'outstream')) { bidResponse.renderer = createRenderer(bidResponse, { id: bid.bidId, @@ -374,9 +203,24 @@ function _addBidResponse(serverBid, bidRequest, bidResponses, RendererConst) { bidResponses.push(bidResponse); } + + if (slot && !slot.bids.length) { + slot.parents.forEach(({parent, key, uid}) => { + const index = parent[key].indexOf(slot); + if (index > -1) { + parent[key].splice(index, 1); + } + if (!parent[key].length) { + delete parent[key]; + if (!utils.getKeys(parent).length) { + delete bidsMap[uid]; + } + } + }); + } } if (errorMessage) { - logError(errorMessage); + utils.logError(errorMessage); } } @@ -399,7 +243,7 @@ function createRenderer (bid, rendererParams, RendererConst) { try { rendererInst.setRender(outstreamRender); } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); + utils.logWarn('Prebid Error calling setRender on renderer', err); } return rendererInst; @@ -410,7 +254,7 @@ function createVideoRequest(bid, mediaType) { const size = (playerSize || bid.sizes || [])[0]; if (!size) return; - let result = parseGPTSingleSizeArrayToRtbSize(size); + let result = utils.parseGPTSingleSizeArrayToRtbSize(size); if (mimes) { result.mimes = mimes; @@ -432,8 +276,8 @@ function createBannerRequest(bid, mediaType) { const sizes = mediaType.sizes || bid.sizes; if (!sizes || !sizes.length) return; - let format = sizes.map((size) => parseGPTSingleSizeArrayToRtbSize(size)); - let result = parseGPTSingleSizeArrayToRtbSize(sizes[0]); + let format = sizes.map((size) => utils.parseGPTSingleSizeArrayToRtbSize(size)); + let result = utils.parseGPTSingleSizeArrayToRtbSize(sizes[0]); if (format.length) { result.format = format @@ -441,65 +285,32 @@ function createBannerRequest(bid, mediaType) { return result; } -function segmentProcessing(segment, forceSegName) { - return segment - .map((seg) => { - const value = seg && (seg.value || seg.id || seg); - if (typeof value === 'string' || typeof value === 'number') { - return { - value: value.toString(), - ...(forceSegName && { name: forceSegName }), - ...(seg.name && { name: seg.name }), - }; - } - return null; - }) - .filter((seg) => !!seg); -} - -function reformatKeywords(pageKeywords) { - const formatedPageKeywords = {}; - Object.keys(pageKeywords).forEach((name) => { - const keywords = pageKeywords[name]; - if (keywords) { - if (name === 'site' || name === 'user') { - const formatedKeywords = {}; - Object.keys(keywords).forEach((pubName) => { - if (Array.isArray(keywords[pubName])) { - const formatedPublisher = []; - keywords[pubName].forEach((pubItem) => { - if (typeof pubItem === 'object' && pubItem.name) { - const formatedPubItem = { name: pubItem.name, segments: [] }; - Object.keys(pubItem).forEach((key) => { - if (Array.isArray(pubItem[key])) { - pubItem[key].forEach((keyword) => { - if (keyword) { - if (typeof keyword === 'string') { - formatedPubItem.segments.push({ name: key, value: keyword }); - } else if (key === 'segments' && typeof keyword.name === 'string' && typeof keyword.value === 'string') { - formatedPubItem.segments.push(keyword); - } - } - }); - } - }); - if (formatedPubItem.segments.length) { - formatedPublisher.push(formatedPubItem); - } - } - }); - if (formatedPublisher.length) { - formatedKeywords[pubName] = formatedPublisher; - } - } - }); - formatedPageKeywords[name] = formatedKeywords; - } else { - formatedPageKeywords[name] = keywords; +function addSegments(name, segName, segments, data, bidConfigName) { + if (segments && segments.length) { + data.push({ + name: name, + segment: segments.map((seg) => { + return {name: segName, value: seg}; + }) + }); + } else if (bidConfigName) { + const configData = config.getConfig('ortb2.user.data'); + let segData = null; + configData && configData.some(({name, segment}) => { + if (name === bidConfigName) { + segData = segment; + return true; } + }); + if (segData && segData.length) { + data.push({ + name: name, + segment: segData.map((seg) => { + return {name: segName, value: seg}; + }) + }); } - }); - return Object.keys(formatedPageKeywords).length && formatedPageKeywords; + } } /** @@ -529,4 +340,319 @@ function _getFloor (mediaTypes, bid) { return floor; } +function newFormatRequest(validBidRequests, bidderRequest) { + if (!validBidRequests.length) { + return null; + } + let pageKeywords = null; + let jwpseg = null; + let permutiveseg = null; + let content = null; + let schain = null; + let userId = null; + let userIdAsEids = null; + let user = null; + let userExt = null; + let {bidderRequestId, auctionId, gdprConsent, uspConsent, timeout, refererInfo} = bidderRequest || {}; + + const referer = refererInfo ? encodeURIComponent(refererInfo.referer) : ''; + const imp = []; + const bidsMap = {}; + + validBidRequests.forEach((bid) => { + if (!bidderRequestId) { + bidderRequestId = bid.bidderRequestId; + } + if (!auctionId) { + auctionId = bid.auctionId; + } + if (!schain) { + schain = bid.schain; + } + if (!userId) { + userId = bid.userId; + } + if (!userIdAsEids) { + userIdAsEids = bid.userIdAsEids; + } + const {params: {uid, keywords}, mediaTypes, bidId, adUnitCode, rtd} = bid; + bidsMap[bidId] = bid; + if (!pageKeywords && !utils.isEmpty(keywords)) { + pageKeywords = utils.transformBidderParamKeywords(keywords); + } + const bidFloor = _getFloor(mediaTypes || {}, bid); + if (rtd) { + const jwTargeting = rtd.jwplayer && rtd.jwplayer.targeting; + if (jwTargeting) { + if (!jwpseg && jwTargeting.segments) { + jwpseg = jwTargeting.segments; + } + if (!content && jwTargeting.content) { + content = jwTargeting.content; + } + } + const permutiveTargeting = rtd.p_standard && rtd.p_standard.targeting; + if (!permutiveseg && permutiveTargeting && permutiveTargeting.segments) { + permutiveseg = permutiveTargeting.segments; + } + } + let impObj = { + id: bidId, + tagid: uid.toString(), + ext: { + divid: adUnitCode + } + }; + + if (bidFloor) { + impObj.bidfloor = bidFloor; + } + + if (!mediaTypes || mediaTypes[BANNER]) { + const banner = createBannerRequest(bid, mediaTypes ? mediaTypes[BANNER] : {}); + if (banner) { + impObj.banner = banner; + } + } + if (mediaTypes && mediaTypes[VIDEO]) { + const video = createVideoRequest(bid, mediaTypes[VIDEO]); + if (video) { + impObj.video = video; + } + } + + if (impObj.banner || impObj.video) { + imp.push(impObj); + } + }); + + const source = { + tid: auctionId, + ext: { + wrapper: 'Prebid_js', + wrapper_version: '$prebid.version$' + } + }; + + if (schain) { + source.ext.schain = schain; + } + + const bidderTimeout = config.getConfig('bidderTimeout') || timeout; + const tmax = timeout ? Math.min(bidderTimeout, timeout) : bidderTimeout; + + let request = { + id: bidderRequestId, + site: { + page: referer + }, + tmax, + source, + imp + }; + + if (content) { + request.site.content = content; + } + + const userData = []; + addSegments('iow_labs_pub_data', 'jwpseg', jwpseg, userData); + addSegments('permutive', 'p_standard', permutiveseg, userData, 'permutive.com'); + + if (userData.length) { + user = { + data: userData + }; + } + + if (gdprConsent && gdprConsent.consentString) { + userExt = {consent: gdprConsent.consentString}; + } + + if (userIdAsEids && userIdAsEids.length) { + userExt = userExt || {}; + userExt.eids = [...userIdAsEids]; + } + + if (userExt && Object.keys(userExt).length) { + user = user || {}; + user.ext = userExt; + } + + if (user) { + request.user = user; + } + + const configKeywords = utils.transformBidderParamKeywords({ + 'user': utils.deepAccess(config.getConfig('ortb2.user'), 'keywords') || null, + 'context': utils.deepAccess(config.getConfig('ortb2.site'), 'keywords') || null + }); + + if (configKeywords.length) { + pageKeywords = (pageKeywords || []).concat(configKeywords); + } + + if (pageKeywords && pageKeywords.length > 0) { + pageKeywords.forEach(deleteValues); + } + + if (pageKeywords) { + request.ext = { + keywords: pageKeywords + }; + } + + if (gdprConsent && gdprConsent.gdprApplies) { + request.regs = { + ext: { + gdpr: gdprConsent.gdprApplies ? 1 : 0 + } + } + } + + if (uspConsent) { + if (!request.regs) { + request.regs = {ext: {}}; + } + request.regs.ext.us_privacy = uspConsent; + } + + return { + method: 'POST', + url: NEW_ENDPOINT_URL, + data: JSON.stringify(request), + newFormat: true, + bidsMap + }; +} + +function oldFormatRequest(validBidRequests, bidderRequest) { + const auids = []; + const bidsMap = {}; + const slotsMapByUid = {}; + const sizeMap = {}; + const bids = validBidRequests || []; + let priceType = 'net'; + let jwpseg = null; + let permutiveseg = null; + let pageKeywords; + let reqId; + + bids.forEach(bid => { + if (bid.params.priceType === 'gross') { + priceType = 'gross'; + } + reqId = bid.bidderRequestId; + const {params: {uid}, adUnitCode, rtd} = bid; + auids.push(uid); + const sizesId = utils.parseSizesInput(bid.sizes); + + if (!pageKeywords && !utils.isEmpty(bid.params.keywords)) { + const keywords = utils.transformBidderParamKeywords(bid.params.keywords); + + if (keywords.length > 0) { + keywords.forEach(deleteValues); + } + pageKeywords = keywords; + } + + if (rtd) { + const jwTargeting = rtd.jwplayer && rtd.jwplayer.targeting; + if (jwTargeting) { + if (!jwpseg && jwTargeting.segments) { + jwpseg = jwTargeting.segments; + } + } + const permutiveTargeting = rtd.p_standard && rtd.p_standard.targeting; + if (!permutiveseg && permutiveTargeting && permutiveTargeting.segments) { + permutiveseg = permutiveTargeting.segments; + } + } + + if (!slotsMapByUid[uid]) { + slotsMapByUid[uid] = {}; + } + const slotsMap = slotsMapByUid[uid]; + if (!slotsMap[adUnitCode]) { + slotsMap[adUnitCode] = {adUnitCode, bids: [bid], parents: []}; + } else { + slotsMap[adUnitCode].bids.push(bid); + } + const slot = slotsMap[adUnitCode]; + + sizesId.forEach((sizeId) => { + sizeMap[sizeId] = true; + if (!bidsMap[uid]) { + bidsMap[uid] = {}; + } + + if (!bidsMap[uid][sizeId]) { + bidsMap[uid][sizeId] = [slot]; + } else { + bidsMap[uid][sizeId].push(slot); + } + slot.parents.push({parent: bidsMap[uid], key: sizeId, uid}); + }); + }); + + const segmentsData = []; + addSegments('iow_labs_pub_data', 'jwpseg', jwpseg, segmentsData); + addSegments('permutive', 'p_standard', permutiveseg, segmentsData, 'permutive.com'); + + if (segmentsData.length) { + if (!pageKeywords) { + pageKeywords = []; + } + segmentsData.forEach(({segment}) => { + if (segment.length) { + pageKeywords.push({ + key: segment[0].name, + value: segment.map(({value}) => value) + }); + } + }); + } + + const payload = { + pt: priceType, + auids: auids.join(','), + sizes: utils.getKeys(sizeMap).join(','), + r: reqId, + wrapperType: 'Prebid_js', + wrapperVersion: '$prebid.version$' + }; + + if (pageKeywords) { + payload.keywords = JSON.stringify(pageKeywords); + } + + if (bidderRequest) { + if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + payload.u = bidderRequest.refererInfo.referer; + } + if (bidderRequest.timeout) { + payload.wtimeout = bidderRequest.timeout; + } + if (bidderRequest.gdprConsent) { + if (bidderRequest.gdprConsent.consentString) { + payload.gdpr_consent = bidderRequest.gdprConsent.consentString; + } + payload.gdpr_applies = + (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') + ? Number(bidderRequest.gdprConsent.gdprApplies) : 1; + } + if (bidderRequest.uspConsent) { + payload.us_privacy = bidderRequest.uspConsent; + } + } + + return { + method: 'GET', + url: ENDPOINT_URL, + data: utils.parseQueryStringParameters(payload).replace(/\&$/, ''), + bidsMap, + priceType + }; +} + registerBidder(spec); diff --git a/modules/trustxBidAdapter.md b/modules/trustxBidAdapter.md index f29d47eaf36..e891df8f161 100644 --- a/modules/trustxBidAdapter.md +++ b/modules/trustxBidAdapter.md @@ -14,55 +14,36 @@ TrustX Bid Adapter supports Banner and Video (instream and outstream). var adUnits = [ { code: 'test-div', - mediaTypes: { - banner: { - sizes: [[300, 250]], - } - }, + sizes: [[300, 250]], bids: [ { bidder: "trustx", params: { - uid: '58851', + uid: '44', + priceType: 'gross' // by default is 'net' } } ] },{ code: 'test-div', - mediaTypes: { - banner: { - sizes: [[728, 90],[300, 250]], - } - }, + sizes: [[728, 90]], bids: [ { bidder: "trustx", params: { - uid: 58851, + uid: 45, + priceType: 'gross', keywords: { - site: { - publisher: { - name: 'someKeywordsName', - brandsafety: ['disaster'], - topic: ['stress', 'fear'] - } - } + brandsafety: ['disaster'], + topic: ['stress', 'fear'] } } } ] },{ code: 'test-div', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 360], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } - }, + sizes: [[640, 360]], + mediaTypes: { video: {} }, bids: [ { bidder: "trustx", @@ -71,6 +52,18 @@ TrustX Bid Adapter supports Banner and Video (instream and outstream). } } ] + },{ + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "trustx", + params: { + uid: '58851', + useNewFormat: true + } + } + ] } ]; ``` diff --git a/modules/ttdBidAdapter.js b/modules/ttdBidAdapter.js deleted file mode 100644 index 4919442336f..00000000000 --- a/modules/ttdBidAdapter.js +++ /dev/null @@ -1,519 +0,0 @@ -import * as utils from '../src/utils.js'; -import { config } from '../src/config.js'; -import { createEidsArray } from './userId/eids.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; - -const BIDADAPTERVERSION = 'TTD-PREBID-2022.02.18'; -const BIDDER_CODE = 'ttd'; -const BIDDER_CODE_LONG = 'thetradedesk'; -const BIDDER_ENDPOINT = 'https://direct.adsrvr.org/bid/bidder/'; -const USER_SYNC_ENDPOINT = 'https://match.adsrvr.org'; - -const MEDIA_TYPE = { - BANNER: 1, - VIDEO: 2 -}; - -function getExt(firstPartyData) { - const ext = { - ver: BIDADAPTERVERSION, - pbjs: '$prebid.version$', - keywords: firstPartyData.site?.keywords ? firstPartyData.site.keywords.split(',').map(k => k.trim()) : [] - } - return { - ttdprebid: ext - }; -} - -function getRegs(bidderRequest) { - let regs = {}; - - if (bidderRequest.gdprConsent && typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { - utils.deepSetValue(regs, 'ext.gdpr', bidderRequest.gdprConsent.gdprApplies ? 1 : 0); - } - if (bidderRequest.uspConsent) { - utils.deepSetValue(regs, 'ext.us_privacy', bidderRequest.uspConsent); - } - if (config.getConfig('coppa') === true) { - regs.coppa = 1; - } - return regs; -} - -function getBidFloor(bid) { - if (!utils.isFn(bid.getFloor)) { - return null; - } - - let floor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*' - }); - if (utils.isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') { - return floor.floor; - } - return null; -} - -function getSource(validBidRequests) { - let source = {}; - if (validBidRequests[0].schain) { - utils.deepSetValue(source, 'ext.schain', validBidRequests[0].schain); - } - return source; -} - -function getDevice() { - const language = navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage; - let device = { - ua: navigator.userAgent, - dnt: utils.getDNT() ? 1 : 0, - language: language, - connectiontype: getConnectionType() - }; - - return device; -}; - -function getConnectionType() { - const connection = navigator.connection || navigator.webkitConnection; - if (!connection) { - return 0; - } - switch (connection.type) { - case 'ethernet': - return 1; - case 'wifi': - return 2; - case 'cellular': - switch (connection.effectiveType) { - case 'slow-2g': - case '2g': - return 4; - case '3g': - return 5; - case '4g': - return 6; - default: - return 3; - } - default: - return 0; - } -} - -function getUser(bidderRequest) { - let user = {}; - if (bidderRequest.gdprConsent) { - utils.deepSetValue(user, 'ext.consent', bidderRequest.gdprConsent.consentString); - } - - if (utils.isStr(utils.deepAccess(bidderRequest, 'bids.0.userId.tdid'))) { - user.buyeruid = bidderRequest.bids[0].userId.tdid; - } - - var eids = createEidsArray(utils.deepAccess(bidderRequest, 'bids.0.userId')) - if (eids.length) { - utils.deepSetValue(user, 'ext.eids', eids); - } - - return user; -} - -function getSite(bidderRequest, firstPartyData) { - var site = { - id: utils.deepAccess(bidderRequest, 'bids.0.params.siteId'), - page: utils.deepAccess(bidderRequest, 'refererInfo.referer'), - publisher: { - id: utils.deepAccess(bidderRequest, 'bids.0.params.publisherId'), - }, - ...firstPartyData.site - }; - - var publisherDomain = config.getConfig('publisherDomain'); - if (publisherDomain) { - utils.deepSetValue(site, 'publisher.domain', publisherDomain); - } - return site; -} - -function getImpression(bidRequest) { - let impression = { - id: bidRequest.bidId, - tagid: bidRequest.params.placementId - }; - - let gpid = utils.deepAccess(bidRequest, 'ortb2Imp.ext.gpid'); - if (gpid) { - impression.ext = { - gpid: gpid - } - } - - const mediaTypesVideo = utils.deepAccess(bidRequest, 'mediaTypes.video'); - const mediaTypesBanner = utils.deepAccess(bidRequest, 'mediaTypes.banner'); - - let mediaTypes = {}; - if (mediaTypesBanner) { - mediaTypes[BANNER] = banner(bidRequest); - } - if (mediaTypesVideo) { - mediaTypes[VIDEO] = video(bidRequest); - } - - Object.assign(impression, mediaTypes); - - let bidfloor = getBidFloor(bidRequest); - if (bidfloor) { - impression.bidfloor = parseFloat(bidfloor); - impression.bidfloorcur = 'USD'; - } - - return impression; -} - -function getSizes(sizes) { - const sizeStructs = utils.parseSizesInput(sizes) - .filter(x => x) // sizes that don't conform are returned as null, which we want to ignore - .map(x => x.split('x')) - .map(size => { - return { - width: parseInt(size[0]), - height: parseInt(size[1]), - } - }); - - return sizeStructs; -} - -function banner(bid) { - const sizes = getSizes(bid.mediaTypes.banner.sizes).map(x => { - return { - w: x.width, - h: x.height, - } - }); - const pos = parseInt(utils.deepAccess(bid, 'mediaTypes.banner.pos')); - const expdir = utils.deepAccess(bid, 'params.banner.expdir'); - let optionalParams = {}; - if (pos) { - optionalParams.pos = pos; - } - if (expdir && Array.isArray(expdir)) { - optionalParams.expdir = expdir; - } - - const banner = Object.assign( - { - w: sizes[0].w, - h: sizes[0].h, - format: sizes, - }, - optionalParams); - return banner; -} - -function video(bid) { - let minduration = utils.deepAccess(bid, 'mediaTypes.video.minduration'); - const maxduration = utils.deepAccess(bid, 'mediaTypes.video.maxduration'); - const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); - const api = utils.deepAccess(bid, 'mediaTypes.video.api'); - const mimes = utils.deepAccess(bid, 'mediaTypes.video.mimes'); - const placement = utils.deepAccess(bid, 'mediaTypes.video.placement'); - const protocols = utils.deepAccess(bid, 'mediaTypes.video.protocols'); - const playbackmethod = utils.deepAccess(bid, 'mediaTypes.video.playbackmethod'); - const pos = utils.deepAccess(bid, 'mediaTypes.video.pos'); - const startdelay = utils.deepAccess(bid, 'mediaTypes.video.startdelay'); - const skip = utils.deepAccess(bid, 'mediaTypes.video.skip'); - const skipmin = utils.deepAccess(bid, 'mediaTypes.video.skipmin'); - const skipafter = utils.deepAccess(bid, 'mediaTypes.video.skipafter'); - const minbitrate = utils.deepAccess(bid, 'mediaTypes.video.minbitrate'); - const maxbitrate = utils.deepAccess(bid, 'mediaTypes.video.maxbitrate'); - - if (!minduration || !utils.isInteger(minduration)) { - minduration = 0 - } - let video = { - minduration: minduration, - maxduration: maxduration, - api: api, - mimes: mimes, - placement: placement, - protocols: protocols - }; - - if (typeof playerSize !== 'undefined') { - if (utils.isArray(playerSize[0])) { - video.w = parseInt(playerSize[0][0]); - video.h = parseInt(playerSize[0][1]); - } else if (utils.isNumber(playerSize[0])) { - video.w = parseInt(playerSize[0]); - video.h = parseInt(playerSize[1]); - } - } - - if (playbackmethod) { - video.playbackmethod = playbackmethod; - } - if (pos) { - video.pos = pos; - } - if (startdelay && utils.isInteger(startdelay)) { - video.startdelay = startdelay; - } - if (skip && (skip === 0 || skip === 1)) { - video.skip = skip; - } - if (skipmin && utils.isInteger(skipmin)) { - video.skipmin = skipmin; - } - if (skipafter && utils.isInteger(skipafter)) { - video.skipafter = skipafter; - } - if (minbitrate && utils.isInteger(minbitrate)) { - video.minbitrate = minbitrate; - } - if (maxbitrate && utils.isInteger(maxbitrate)) { - video.maxbitrate = maxbitrate; - } - - return video; -} - -export const spec = { - code: BIDDER_CODE, - gvlid: 21, - aliases: [BIDDER_CODE_LONG], - supportedMediaTypes: [BANNER, VIDEO], - - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function (bid) { - const alphaRegex = /^[\w+]+$/; - - // required parameters - if (!bid || !bid.params) { - utils.logWarn(BIDDER_CODE + ': Missing bid parameters'); - return false; - } - if (!bid.params.supplySourceId) { - utils.logWarn(BIDDER_CODE + ': Missing required parameter params.supplySourceId'); - return false; - } - if (!alphaRegex.test(bid.params.supplySourceId)) { - utils.logWarn(BIDDER_CODE + ': supplySourceId must only contain alphabetic characters'); - return false; - } - if (!bid.params.publisherId) { - utils.logWarn(BIDDER_CODE + ': Missing required parameter params.publisherId'); - return false; - } - if (bid.params.publisherId.length > 32) { - utils.logWarn(BIDDER_CODE + ': params.publisherId must be 32 characters or less'); - return false; - } - if (!bid.params.siteId) { - utils.logWarn(BIDDER_CODE + ': Missing required parameter params.siteId'); - return false; - } - if (bid.params.siteId.length > 50) { - utils.logWarn(BIDDER_CODE + ': params.siteId must be 50 characters or less'); - return false; - } - if (!bid.params.placementId) { - utils.logWarn(BIDDER_CODE + ': Missing required parameter params.placementId'); - return false; - } - if (bid.params.placementId.length > 128) { - utils.logWarn(BIDDER_CODE + ': params.placementId must be 128 characters or less'); - return false; - } - - const mediaTypesBanner = utils.deepAccess(bid, 'mediaTypes.banner'); - const mediaTypesVideo = utils.deepAccess(bid, 'mediaTypes.video'); - - if (!mediaTypesBanner && !mediaTypesVideo) { - utils.logWarn(BIDDER_CODE + ': one of mediaTypes.banner or mediaTypes.video must be passed'); - return false; - } - - if (mediaTypesVideo) { - if (!mediaTypesVideo.maxduration || !utils.isInteger(mediaTypesVideo.maxduration)) { - utils.logWarn(BIDDER_CODE + ': mediaTypes.video.maxduration must be set to the maximum video ad duration in seconds'); - return false; - } - if (!mediaTypesVideo.api || mediaTypesVideo.api.length === 0) { - utils.logWarn(BIDDER_CODE + ': mediaTypes.video.api should be an array of supported api frameworks. See the Open RTB v2.5 spec for valid values'); - return false; - } - if (!mediaTypesVideo.mimes || mediaTypesVideo.mimes.length === 0) { - utils.logWarn(BIDDER_CODE + ': mediaTypes.video.mimes should be an array of supported mime types'); - return false; - } - if (!mediaTypesVideo.protocols) { - utils.logWarn(BIDDER_CODE + ': mediaTypes.video.protocols should be an array of supported protocols. See the Open RTB v2.5 spec for valid values') - return false; - } - } - - return true; - }, - - /** - * Make a server request from the list of BidRequests. - * - * @param {BidRequest[]} an array of validBidRequests - * @param {*} bidderRequest - * @return {ServerRequest} Info describing the request to the server. - */ - buildRequests: function (validBidRequests, bidderRequest) { - const firstPartyData = config.getConfig('ortb2') || {}; - let topLevel = { - id: bidderRequest.auctionId, - imp: validBidRequests.map(bidRequest => getImpression(bidRequest)), - site: getSite(bidderRequest, firstPartyData), - device: getDevice(), - user: getUser(bidderRequest), - at: 1, - cur: ['USD'], - regs: getRegs(bidderRequest), - source: getSource(validBidRequests), - ext: getExt(firstPartyData) - } - - let url = BIDDER_ENDPOINT + bidderRequest.bids[0].params.supplySourceId; - - let serverRequest = { - method: 'POST', - url: url, - data: topLevel, - options: { - withCredentials: true - } - }; - - return serverRequest; - }, - - /** - * Format responses as Prebid bid responses - * - * Each bid can have the following elements: - * - requestId (required) - * - cpm (required) - * - width (required) - * - height (required) - * - ad (required) - * - ttl (required) - * - creativeId (required) - * - netRevenue (required) - * - currency (required) - * - vastUrl - * - vastImpUrl - * - vastXml - * - dealId - * - * @param {ttdResponseObj} bidResponse A successful response from ttd. - * @param {ServerRequest} serverRequest The result of buildRequests() that lead to this response. - * @return {Bid[]} An array of formatted bids. - */ - interpretResponse: function (response, serverRequest) { - let seatBidsInResponse = utils.deepAccess(response, 'body.seatbid'); - const currency = utils.deepAccess(response, 'body.cur'); - if (!seatBidsInResponse || seatBidsInResponse.length === 0) { - return []; - } - let bidResponses = []; - let requestedImpressions = utils.deepAccess(serverRequest, 'data.imp'); - - seatBidsInResponse.forEach(seatBid => { - seatBid.bid.forEach(bid => { - let matchingRequestedImpression = requestedImpressions.find(imp => imp.id === bid.impid); - - const cpm = bid.price || 0; - let bidResponse = { - requestId: bid.impid, - cpm: cpm, - creativeId: bid.crid, - dealId: bid.dealid || null, - currency: currency || 'USD', - netRevenue: true, - ttl: bid.ttl || 360, - meta: {}, - }; - - if (bid.adomain && bid.adomain.length > 0) { - bidResponse.meta.advertiserDomains = bid.adomain; - } - - if (bid.ext.mediatype === MEDIA_TYPE.BANNER) { - Object.assign( - bidResponse, - { - width: bid.w, - height: bid.h, - ad: utils.replaceAuctionPrice(bid.adm, cpm), - mediaType: BANNER - } - ); - } else if (bid.ext.mediatype === MEDIA_TYPE.VIDEO) { - Object.assign( - bidResponse, - { - width: matchingRequestedImpression.video.w, - height: matchingRequestedImpression.video.h, - mediaType: VIDEO - } - ); - if (bid.nurl) { - bidResponse.vastUrl = utils.replaceAuctionPrice(bid.nurl, cpm); - } else { - bidResponse.vastXml = utils.replaceAuctionPrice(bid.adm, cpm); - } - } - - bidResponses.push(bidResponse); - }); - }); - - return bidResponses; - }, - - /** - * Register the user sync pixels which should be dropped after the auction. - * - * @param {SyncOptions} syncOptions Which user syncs are allowed? - * @param {ServerResponse[]} serverResponses List of server's responses. - * @param {gdprConsent} gdprConsent GDPR consent object - * @param {uspConsent} uspConsent USP consent object - * @return {UserSync[]} The user syncs which should be dropped. - */ - getUserSyncs: function(syncOptions, serverResponses, gdprConsent = {}, uspConsent = '') { - const syncs = []; - - let gdprParams = `&gdpr=${gdprConsent.gdprApplies ? 1 : 0}&gdpr_consent=${encodeURIComponent(gdprConsent.consentString)}`; - - let url = `${USER_SYNC_ENDPOINT}/track/usersync?us_privacy=${encodeURIComponent(uspConsent)}${gdprParams}`; - - if (syncOptions.pixelEnabled) { - syncs.push({ - type: 'image', - url: url + '&ust=image' - }); - } else if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: url + '&ust=iframe' - }); - } - return syncs; - }, -}; - -registerBidder(spec) diff --git a/modules/ttdBidAdapter.md b/modules/ttdBidAdapter.md deleted file mode 100644 index 9c67f3267cb..00000000000 --- a/modules/ttdBidAdapter.md +++ /dev/null @@ -1,122 +0,0 @@ -# Overview - -``` -Module Name: The Trade Desk Bidder Adapter -Module Type: Bidder Adapter -Maintainer: prebid-maintainers@thetradedesk.com -``` - -# Description - -Module that connects to The Trade Desk's demand sources to fetch bids. - -The Trade Desk bid adapter supports Banner and Video. - -# Test Parameters - -```js - var adUnits = [ - // Banner adUnit with only required parameters - { - code: 'test-div-minimal', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - bids: [ - { - bidder: 'ttd', - params: { - supplySourceId: 'supplier', - publisherId: '1427ab10f2e448057ed3b422', - siteId: 'site-123', - placementId: 'footer1' - } - } - ] - }, - // Banner adUnit with all optional parameters provided - { - code: 'test-div-banner-optional-params', - mediaTypes: { - banner: { - sizes: [[728, 90]], - pos: 1 - } - }, - bids: [ - { - bidder: 'ttd', - params: { - supplySourceId: 'supplier', - publisherId: '1427ab10f2e448057ed3b422', - siteId: 'site-123', - placementId: 'footer1', - banner: { - expdir: [1, 3] - }, - } - } - ] - }, - // Video adUnit with only required parameters - { - code: 'test-div-video-minimal', - mediaTypes: { - video: { - maxduration: 30, - api: [1, 3], - mimes: ['video/mp4'], - placement: 3, - protocols: [2,3,5,6] - } - }, - bids: [ - { - bidder: 'ttd', - params: { - supplySourceId: 'supplier', - publisherId: '1427ab10f2e448057ed3b422', - siteId: 'site-123', - placementId: 'footer1' - } - } - ] - }, - // Video adUnit with all optional parameters provided - { - code: 'test-div-video-full', - mediaTypes: { - video: { - minduration: 1, - maxduration: 10, - playerSize: [640, 480], - api: [1, 3], - mimes: ['video/mp4'], - placement: 3, - protocols: [2, 3, 5, 6], - startdelay: 1, - playbackmethod: [1], - pos: 1, - minbitrate: 100, - maxbitrate: 500, - skip: 1, - skipmin: 5, - skipafter: 10 - } - }, - bids: [ - { - bidder: 'ttd', - params: { - supplySourceId: 'supplier', - publisherId: '1427ab10f2e448057ed3b422', - siteId: 'site-123', - placementId: 'footer1' - } - } - ] - } - ]; -``` diff --git a/modules/turktelekomBidAdapter.md b/modules/turktelekomBidAdapter.md new file mode 100644 index 00000000000..360e7f95230 --- /dev/null +++ b/modules/turktelekomBidAdapter.md @@ -0,0 +1,49 @@ +# Overview + +Module Name: Türk Telekom Bidder Adapter +Module Type: Bidder Adapter +Maintainer: turktelssp@gmail.com + +# Description + +Module that connects to Türk Telekom demand source to fetch bids. +Türk Telekom Bid Adapter supports Banner and Video (instream and outstream). + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [ + { + bidder: "turktelekom", + params: { + uid: 17, + priceType: 'gross' // by default is 'net' + } + } + ] + },{ + code: 'test-div', + mediaTypes: { + video: { + playerSize: [[640, 360]], + context: 'instream' + } + }, + bids: [ + { + bidder: "turktelekom", + params: { + uid: 19 + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index ec087d005d6..69cbbc697fc 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -1,9 +1,9 @@ -import { generateUUID, _each } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; import { config } from '../src/config.js'; - +import * as utils from '../src/utils.js'; +const storage = getStorageManager(); const COOKIE_NAME = 'ucf_uid'; const VER = 'ADGENT_PREBID-2018011501'; const BIDDER_CODE = 'ucfunnel'; @@ -13,7 +13,6 @@ const VIDEO_CONTEXT = { INSTREAM: 0, OUSTREAM: 2 } -const storage = getStorageManager({bidderCode: BIDDER_CODE}); export const spec = { code: BIDDER_CODE, @@ -284,7 +283,7 @@ function getRequestData(bid, bidderRequest) { ucfUid = storage.getCookie(COOKIE_NAME); bidData.ucfUid = ucfUid; } else { - ucfUid = generateUUID(); + ucfUid = utils.generateUUID(); bidData.ucfUid = ucfUid; storage.setCookie(COOKIE_NAME, ucfUid); } @@ -336,7 +335,7 @@ function getRequestData(bid, bidderRequest) { function addUserId(bidData, userId) { bidData['eids'] = ''; - _each(userId, (userIdObjectOrValue, userIdProviderKey) => { + utils._each(userId, (userIdObjectOrValue, userIdProviderKey) => { switch (userIdProviderKey) { case 'haloId': if (userIdObjectOrValue.haloId) { diff --git a/modules/uid2IdSystem.js b/modules/uid2IdSystem.js index 23656639532..053b57cb76d 100644 --- a/modules/uid2IdSystem.js +++ b/modules/uid2IdSystem.js @@ -5,7 +5,7 @@ * @requires module:modules/userId */ -import { logInfo } from '../src/utils.js'; +import * as utils from '../src/utils.js' import {submodule} from '../src/hook.js'; import { getStorageManager } from '../src/storageManager.js'; @@ -23,16 +23,16 @@ function readFromLocalStorage() { } function getStorage() { - return getStorageManager({gvlid: GVLID, moduleName: MODULE_NAME}); + return getStorageManager(GVLID, MODULE_NAME); } const storage = getStorage(); -const _logInfo = createLogInfo(LOG_PRE_FIX); +const logInfo = createLogInfo(LOG_PRE_FIX); function createLogInfo(prefix) { return function (...strings) { - logInfo(prefix + ' ', ...strings); + utils.logInfo(prefix + ' ', ...strings); } } @@ -48,7 +48,7 @@ function encodeId(value) { id: value } result.uid2 = bidIds; - _logInfo('Decoded value ' + JSON.stringify(result)); + logInfo('Decoded value ' + JSON.stringify(result)); return result; } return undefined; @@ -85,9 +85,9 @@ export const uid2IdSubmodule = { * @returns {uid2Id} */ getId(config, consentData) { - _logInfo('Creating UID 2.0'); + logInfo('Creating UID 2.0'); let value = readCookie() || readFromLocalStorage(); - _logInfo('The advertising token: ' + value); + logInfo('The advertising token: ' + value); return {id: value} }, diff --git a/modules/underdogmediaBidAdapter.js b/modules/underdogmediaBidAdapter.js index 2ca4de7a555..6268774bc12 100644 --- a/modules/underdogmediaBidAdapter.js +++ b/modules/underdogmediaBidAdapter.js @@ -1,4 +1,4 @@ -import { logMessage, flatten, parseSizesInput } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'underdogmedia'; @@ -7,7 +7,7 @@ const UDM_VENDOR_ID = '159'; const prebidVersion = '$prebid.version$'; let USER_SYNCED = false; -logMessage(`Initializing UDM Adapter. PBJS Version: ${prebidVersion} with adapter version: ${UDM_ADAPTER_VERSION} Updated 20191028`); +utils.logMessage(`Initializing UDM Adapter. PBJS Version: ${prebidVersion} with adapter version: ${UDM_ADAPTER_VERSION} Updated 20191028`); // helper function for testing user syncs export function resetUserSync() { @@ -29,7 +29,7 @@ export const spec = { validBidRequests.forEach(bidParam => { let bidParamSizes = bidParam.mediaTypes && bidParam.mediaTypes.banner && bidParam.mediaTypes.banner.sizes ? bidParam.mediaTypes.banner.sizes : bidParam.sizes; - sizes = flatten(sizes, parseSizesInput(bidParamSizes)); + sizes = utils.flatten(sizes, utils.parseSizesInput(bidParamSizes)); siteId = bidParam.params.siteId; }); @@ -99,7 +99,7 @@ export const spec = { var sizeNotFound = true; const bidParamSizes = bidParam.mediaTypes && bidParam.mediaTypes.banner && bidParam.mediaTypes.banner.sizes ? bidParam.mediaTypes.banner.sizes : bidParam.sizes - parseSizesInput(bidParamSizes).forEach(size => { + utils.parseSizesInput(bidParamSizes).forEach(size => { if (size === mid.width + 'x' + mid.height) { sizeNotFound = false; } diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index f86faf3fe4d..14a765206b6 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -12,20 +12,6 @@ const FRAME_USER_SYNC = 'https://cdn.undertone.com/js/usersync.html'; const PIXEL_USER_SYNC_1 = 'https://usr.undertone.com/userPixel/syncOne?id=1&of=2'; const PIXEL_USER_SYNC_2 = 'https://usr.undertone.com/userPixel/syncOne?id=2&of=2'; -function getBidFloor(bidRequest, mediaType) { - if (typeof bidRequest.getFloor !== 'function') { - return 0; - } - - const floor = bidRequest.getFloor({ - currency: 'USD', - mediaType: mediaType, - size: '*' - }); - - return (floor && floor.currency === 'USD' && floor.floor) || 0; -} - function getCanonicalUrl() { try { let doc = window.top.document; @@ -99,29 +85,18 @@ export const spec = { const vw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); const vh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); const pageSizeArray = vw == 0 || vh == 0 ? null : [vw, vh]; - const commons = { - 'adapterVersion': '$prebid.version$', - 'uids': validBidRequests[0].userId, - 'pageSize': pageSizeArray - }; - if (validBidRequests[0].schain) { - commons.schain = validBidRequests[0].schain; - } const payload = { 'x-ut-hb-params': [], - 'commons': commons + 'commons': { + 'adapterVersion': '$prebid.version$', + 'uids': validBidRequests[0].userId, + 'pageSize': pageSizeArray + } }; const referer = bidderRequest.refererInfo.referer; - const canonicalUrl = getCanonicalUrl(); - if (referer) { - commons.referrer = referer; - } - if (canonicalUrl) { - commons.canonicalUrl = canonicalUrl; - } const hostname = parseUrl(referer).hostname; let domain = extractDomainFromHost(hostname); - const pageUrl = canonicalUrl || referer; + const pageUrl = getCanonicalUrl() || referer; const pubid = validBidRequests[0].params.publisherId; let reqUrl = `${URL}?pid=${pubid}&domain=${domain}`; @@ -148,9 +123,6 @@ export const spec = { params: bidReq.params }; const videoMediaType = deepAccess(bidReq, 'mediaTypes.video'); - const mediaType = videoMediaType ? VIDEO : BANNER; - bid.mediaType = mediaType; - bid.bidfloor = getBidFloor(bidReq, mediaType); if (videoMediaType) { bid.video = { playerSize: deepAccess(bidReq, 'mediaTypes.video.playerSize') || null, @@ -159,6 +131,7 @@ export const spec = { maxDuration: deepAccess(bidReq, 'params.video.maxDuration') || null, skippable: deepAccess(bidReq, 'params.video.skippable') || null }; + bid.mediaType = 'video'; } payload['x-ut-hb-params'].push(bid); }); diff --git a/modules/undertoneBidAdapter.md b/modules/undertoneBidAdapter.md index 8e0b234fd7a..8ac84b77bd8 100644 --- a/modules/undertoneBidAdapter.md +++ b/modules/undertoneBidAdapter.md @@ -1,13 +1,9 @@ # Overview ``` -Module Name: Undertone Bidder Adapter +Module Name: Example Bidder Adapter Module Type: Bidder Adapter Maintainer: RampProgrammatic@perion.com -gdpr_supported: true -usp_supported: true -schain_supported: true -media_types: video, native ``` # Description diff --git a/modules/unicornBidAdapter.js b/modules/unicornBidAdapter.js index 977e694acf7..e74c4425626 100644 --- a/modules/unicornBidAdapter.js +++ b/modules/unicornBidAdapter.js @@ -1,14 +1,14 @@ -import { logInfo, deepAccess, generateUUID } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {BANNER} from '../src/mediaTypes.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {getStorageManager} from '../src/storageManager.js'; +const storage = getStorageManager(); const BIDDER_CODE = 'unicorn'; const UNICORN_ENDPOINT = 'https://ds.uncn.jp/pb/0/bid.json'; const UNICORN_DEFAULT_CURRENCY = 'JPY'; const UNICORN_PB_COOKIE_KEY = '__pb_unicorn_aud'; -const UNICORN_PB_VERSION = '1.1'; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); +const UNICORN_PB_VERSION = '1.0'; /** * Placement ID and Account ID are required. @@ -39,8 +39,8 @@ export const buildRequests = (validBidRequests, bidderRequest) => { * @returns {string} */ function buildOpenRtbBidRequestPayload(validBidRequests, bidderRequest) { - logInfo('[UNICORN] buildOpenRtbBidRequestPayload.validBidRequests:', validBidRequests); - logInfo('[UNICORN] buildOpenRtbBidRequestPayload.bidderRequest:', bidderRequest); + utils.logInfo('[UNICORN] buildOpenRtbBidRequestPayload.validBidRequests:', validBidRequests); + utils.logInfo('[UNICORN] buildOpenRtbBidRequestPayload.bidderRequest:', bidderRequest); const imp = validBidRequests.map(br => { return { id: br.bidId, @@ -49,7 +49,7 @@ function buildOpenRtbBidRequestPayload(validBidRequests, bidderRequest) { w: br.sizes[0][0], h: br.sizes[0][1] }, - tagid: deepAccess(br, 'params.placementId') || br.adUnitCode, + tagid: utils.deepAccess(br, 'params.placementId') || br.adUnitCode, secure: 1, bidfloor: parseFloat(0) }; @@ -58,11 +58,11 @@ function buildOpenRtbBidRequestPayload(validBidRequests, bidderRequest) { id: bidderRequest.auctionId, at: 1, imp, - cur: [UNICORN_DEFAULT_CURRENCY], + cur: UNICORN_DEFAULT_CURRENCY, site: { - id: deepAccess(validBidRequests[0], 'params.mediaId') || '', + id: utils.deepAccess(validBidRequests[0], 'params.mediaId') || '', publisher: { - id: String(deepAccess(validBidRequests[0], 'params.publisherId') || 0) + id: utils.deepAccess(validBidRequests[0], 'params.publisherId') || 0 }, domain: window.location.hostname, page: window.location.href, @@ -75,7 +75,7 @@ function buildOpenRtbBidRequestPayload(validBidRequests, bidderRequest) { user: { id: getUid() }, - bcat: deepAccess(validBidRequests[0], 'params.bcat') || [], + bcat: utils.deepAccess(validBidRequests[0], 'params.bcat') || [], source: { ext: { stype: 'prebid_uncn', @@ -84,16 +84,16 @@ function buildOpenRtbBidRequestPayload(validBidRequests, bidderRequest) { } }, ext: { - accountId: deepAccess(validBidRequests[0], 'params.accountId') + accountId: utils.deepAccess(validBidRequests[0], 'params.accountId') } }; - logInfo('[UNICORN] OpenRTB Formatted Request:', request); + utils.logInfo('[UNICORN] OpenRTB Formatted Request:', request); return JSON.stringify(request); } const interpretResponse = (serverResponse, request) => { - logInfo('[UNICORN] interpretResponse.serverResponse:', serverResponse); - logInfo('[UNICORN] interpretResponse.request:', request); + utils.logInfo('[UNICORN] interpretResponse.serverResponse:', serverResponse); + utils.logInfo('[UNICORN] interpretResponse.request:', request); const res = serverResponse.body; var bids = [] if (res) { @@ -119,7 +119,7 @@ const interpretResponse = (serverResponse, request) => { }) }); } - logInfo('[UNICORN] interpretResponse bids:', bids); + utils.logInfo('[UNICORN] interpretResponse bids:', bids); return bids; }; @@ -132,7 +132,7 @@ const getUid = () => { return JSON.parse(ck)['uid']; } else { const newCk = { - uid: generateUUID() + uid: utils.generateUUID() }; const expireIn = new Date(Date.now() + 24 * 60 * 60 * 10000).toUTCString(); storage.setCookie(UNICORN_PB_COOKIE_KEY, JSON.stringify(newCk), expireIn); diff --git a/modules/unifiedIdSystem.js b/modules/unifiedIdSystem.js index 8ec5fcd3f90..bc033f37992 100644 --- a/modules/unifiedIdSystem.js +++ b/modules/unifiedIdSystem.js @@ -5,7 +5,7 @@ * @requires module:modules/userId */ -import { logError } from '../src/utils.js'; +import * as utils from '../src/utils.js' import {ajax} from '../src/ajax.js'; import {submodule} from '../src/hook.js' @@ -40,7 +40,7 @@ export const unifiedIdSubmodule = { getId(config) { const configParams = (config && config.params) || {}; if (!configParams || (typeof configParams.partner !== 'string' && typeof configParams.url !== 'string')) { - logError('User ID - unifiedId submodule requires either partner or url to be defined'); + utils.logError('User ID - unifiedId submodule requires either partner or url to be defined'); return; } // use protocol relative urls for http or https @@ -54,13 +54,13 @@ export const unifiedIdSubmodule = { try { responseObj = JSON.parse(response); } catch (error) { - logError(error); + utils.logError(error); } } callback(responseObj); }, error: error => { - logError(`${MODULE_NAME}: ID fetch encountered an error`, error); + utils.logError(`${MODULE_NAME}: ID fetch encountered an error`, error); callback(); } }; diff --git a/modules/unrulyBidAdapter.js b/modules/unrulyBidAdapter.js index 77160bb01e6..d04192acf15 100644 --- a/modules/unrulyBidAdapter.js +++ b/modules/unrulyBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, logError } from '../src/utils.js'; +import * as utils from '../src/utils.js' import {Renderer} from '../src/Renderer.js' import {registerBidder} from '../src/adapters/bidderFactory.js' import {VIDEO, BANNER} from '../src/mediaTypes.js' @@ -41,7 +41,7 @@ const addBidFloorInfo = (validBid) => { }; const RemoveDuplicateSizes = (validBid) => { - let bannerMediaType = deepAccess(validBid, 'mediaTypes.banner'); + let bannerMediaType = utils.deepAccess(validBid, 'mediaTypes.banner'); if (bannerMediaType) { let seenSizes = {}; let newSizesArray = []; @@ -87,12 +87,12 @@ const handleBidResponseByMediaType = (bids) => { bids.forEach((bid) => { let parsedBidResponse; - let bidMediaType = deepAccess(bid, 'meta.mediaType'); + let bidMediaType = utils.deepAccess(bid, 'meta.mediaType'); if (bidMediaType && bidMediaType.toLowerCase() === 'banner') { bid.mediaType = BANNER; parsedBidResponse = handleBannerBid(bid); } else if (bidMediaType && bidMediaType.toLowerCase() === 'video') { - let context = deepAccess(bid, 'meta.videoContext'); + let context = utils.deepAccess(bid, 'meta.videoContext'); bid.mediaType = VIDEO; if (context === 'instream') { parsedBidResponse = handleInStreamBid(bid); @@ -111,7 +111,7 @@ const handleBidResponseByMediaType = (bids) => { const handleBannerBid = (bid) => { if (!bid.ad) { - logError(new Error('UnrulyBidAdapter: Missing ad config.')); + utils.logError(new Error('UnrulyBidAdapter: Missing ad config.')); return; } @@ -120,7 +120,7 @@ const handleBannerBid = (bid) => { const handleInStreamBid = (bid) => { if (!(bid.vastUrl || bid.vastXml)) { - logError(new Error('UnrulyBidAdapter: Missing vastUrl or vastXml config.')); + utils.logError(new Error('UnrulyBidAdapter: Missing vastUrl or vastXml config.')); return; } @@ -128,19 +128,19 @@ const handleInStreamBid = (bid) => { }; const handleOutStreamBid = (bid) => { - const hasConfig = !!deepAccess(bid, 'ext.renderer.config'); - const hasSiteId = !!deepAccess(bid, 'ext.renderer.config.siteId'); + const hasConfig = !!utils.deepAccess(bid, 'ext.renderer.config'); + const hasSiteId = !!utils.deepAccess(bid, 'ext.renderer.config.siteId'); if (!hasConfig) { - logError(new Error('UnrulyBidAdapter: Missing renderer config.')); + utils.logError(new Error('UnrulyBidAdapter: Missing renderer config.')); return; } if (!hasSiteId) { - logError(new Error('UnrulyBidAdapter: Missing renderer siteId.')); + utils.logError(new Error('UnrulyBidAdapter: Missing renderer siteId.')); return; } - const exchangeRenderer = deepAccess(bid, 'ext.renderer'); + const exchangeRenderer = utils.deepAccess(bid, 'ext.renderer'); configureUniversalTag(exchangeRenderer, bid.requestId); configureRendererQueue(); @@ -152,7 +152,7 @@ const handleOutStreamBid = (bid) => { bid, { renderer: rendererInstance, - adUnitCode: deepAccess(bid, 'ext.adUnitCode') + adUnitCode: utils.deepAccess(bid, 'ext.adUnitCode') } ); @@ -165,8 +165,8 @@ const handleOutStreamBid = (bid) => { }; const isMediaTypesValid = (bid) => { - const mediaTypeVideoData = deepAccess(bid, 'mediaTypes.video'); - const mediaTypeBannerData = deepAccess(bid, 'mediaTypes.banner'); + const mediaTypeVideoData = utils.deepAccess(bid, 'mediaTypes.video'); + const mediaTypeBannerData = utils.deepAccess(bid, 'mediaTypes.banner'); let isValid = !!(mediaTypeVideoData || mediaTypeBannerData); if (isValid && mediaTypeVideoData) { isValid = isVideoMediaTypeValid(mediaTypeVideoData); @@ -193,9 +193,8 @@ const isBannerMediaTypeValid = (mediaTypeBannerData) => { export const adapter = { code: 'unruly', supportedMediaTypes: [VIDEO, BANNER], - gvlid: 36, isBidRequestValid: function (bid) { - let siteId = deepAccess(bid, 'params.siteId'); + let siteId = utils.deepAccess(bid, 'params.siteId'); let isBidValid = siteId && isMediaTypesValid(bid); return !!isBidValid; }, @@ -203,7 +202,7 @@ export const adapter = { buildRequests: function (validBidRequests, bidderRequest) { let endPoint = 'https://targeting.unrulymedia.com/unruly_prebid'; if (validBidRequests[0]) { - endPoint = deepAccess(validBidRequests[0], 'params.endpoint') || endPoint; + endPoint = utils.deepAccess(validBidRequests[0], 'params.endpoint') || endPoint; } const url = endPoint; diff --git a/modules/userId/eids.js b/modules/userId/eids.js index 9c995a52fe3..71267616662 100644 --- a/modules/userId/eids.js +++ b/modules/userId/eids.js @@ -1,37 +1,16 @@ -import { pick, isFn, isStr, isPlainObject, deepAccess } from '../../src/utils.js'; +import * as utils from '../../src/utils.js'; // Each user-id sub-module is expected to mention respective config here -export const USER_IDS_CONFIG = { +const USER_IDS_CONFIG = { // key-name : {config} - // trustpid - 'trustpid': { - source: 'trustpid.com', - atype: 1, - getValue: function (data) { - return data; - }, - }, - // intentIqId 'intentIqId': { source: 'intentiq.com', atype: 1 }, - // naveggId - 'naveggId': { - source: 'navegg.com', - atype: 1 - }, - - // justId - 'justId': { - source: 'justtag.com', - atype: 1 - }, - // pubCommonId 'pubcid': { source: 'pubcid.org', @@ -63,20 +42,6 @@ export const USER_IDS_CONFIG = { } }, - // ftrack - 'ftrackId': { - source: 'flashtalking.com', - atype: 1, - getValue: function(data) { - return data.uid - }, - getUidExt: function(data) { - if (data.ext) { - return data.ext; - } - } - }, - // parrableId 'parrableId': { source: 'parrable.com', @@ -93,7 +58,7 @@ export const USER_IDS_CONFIG = { return null; }, getUidExt: function(parrableId) { - const extendedData = pick(parrableId, [ + const extendedData = utils.pick(parrableId, [ 'ibaOptout', 'ccpaOptout' ]); @@ -175,13 +140,7 @@ export const USER_IDS_CONFIG = { atype: 1 }, - // hadronId - 'hadronId': { - source: 'audigent.com', - atype: 1 - }, - - // haloId (deprecated in 7.0, use hadronId) + // haloId 'haloId': { source: 'audigent.com', atype: 1 @@ -216,18 +175,15 @@ export const USER_IDS_CONFIG = { source: 'neustar.biz', atype: 1 }, - // MediaWallah OpenLink 'mwOpenLinkId': { source: 'mediawallahscript.com', atype: 1 }, - 'tapadId': { source: 'tapad.com', atype: 1 }, - // Novatiq Snowflake 'novatiq': { getValue: function(data) { @@ -236,7 +192,6 @@ export const USER_IDS_CONFIG = { source: 'novatiq.com', atype: 1 }, - 'uid2': { source: 'uidapi.com', atype: 3, @@ -244,76 +199,37 @@ export const USER_IDS_CONFIG = { return data.id; } }, - + 'deepintentId': { + source: 'deepintent.com', + atype: 3 + }, // Akamai Data Activation Platform (DAP) 'dapId': { source: 'akamai.com', atype: 1 }, - - 'deepintentId': { - source: 'deepintent.com', - atype: 3 - }, - // Admixer Id 'admixerId': { source: 'admixer.net', atype: 3 }, - // Adtelligent Id 'adtelligentId': { source: 'adtelligent.com', atype: 3 }, - amxId: { source: 'amxrtb.com', atype: 1, }, - - 'publinkId': { - source: 'epsilon.com', - atype: 3 - }, - 'kpuid': { source: 'kpuid.com', atype: 3 }, - 'imuid': { source: 'intimatemerger.com', atype: 1 - }, - - // Yahoo ConnectID - 'connectId': { - source: 'yahoo.com', - atype: 3 - }, - - // Adquery ID - 'qid': { - source: 'adquery.io', - atype: 1 - }, - - // DAC ID - 'dacId': { - source: 'impact-ad.jp', - atype: 1 - }, - - // 33across ID - '33acrossId': { - source: '33across.com', - atype: 1, - getValue: function(data) { - return data.envelope; - } - }, + } }; // this function will create an eid object for the given UserId sub-module @@ -322,11 +238,11 @@ function createEidObject(userIdData, subModuleKey) { if (conf && userIdData) { let eid = {}; eid.source = conf['source']; - const value = isFn(conf['getValue']) ? conf['getValue'](userIdData) : userIdData; - if (isStr(value)) { + const value = utils.isFn(conf['getValue']) ? conf['getValue'](userIdData) : userIdData; + if (utils.isStr(value)) { const uid = { id: value, atype: conf['atype'] }; // getUidExt - if (isFn(conf['getUidExt'])) { + if (utils.isFn(conf['getUidExt'])) { const uidExt = conf['getUidExt'](userIdData); if (uidExt) { uid.ext = uidExt; @@ -334,7 +250,7 @@ function createEidObject(userIdData, subModuleKey) { } eid.uids = [uid]; // getEidExt - if (isFn(conf['getEidExt'])) { + if (utils.isFn(conf['getEidExt'])) { const eidExt = conf['getEidExt'](userIdData); if (eidExt) { eid.ext = eidExt; @@ -371,11 +287,11 @@ export function createEidsArray(bidRequestUserId) { */ export function buildEidPermissions(submodules) { let eidPermissions = []; - submodules.filter(i => isPlainObject(i.idObj) && Object.keys(i.idObj).length) + submodules.filter(i => utils.isPlainObject(i.idObj) && Object.keys(i.idObj).length) .forEach(i => { Object.keys(i.idObj).forEach(key => { - if (deepAccess(i, 'config.bidders') && Array.isArray(i.config.bidders) && - deepAccess(USER_IDS_CONFIG, key + '.source')) { + if (utils.deepAccess(i, 'config.bidders') && Array.isArray(i.config.bidders) && + utils.deepAccess(USER_IDS_CONFIG, key + '.source')) { eidPermissions.push( { source: USER_IDS_CONFIG[key].source, diff --git a/modules/userId/eids.md b/modules/userId/eids.md index 45237ac5f26..ab454c54d30 100644 --- a/modules/userId/eids.md +++ b/modules/userId/eids.md @@ -2,21 +2,6 @@ ``` userIdAsEids = [ - { - source: '33across.com', - uids: [{ - id: 'some-random-id-value', - atype: 1 - }] - }, - { - source: 'trustpid.com', - uids: [{ - id: 'some-random-id-value', - atype: 1 - }] - }, - { source: 'pubcid.org', uids: [{ @@ -36,22 +21,6 @@ userIdAsEids = [ }] }, - { - source: 'navegg.com', - uids: [{ - id: 'naveggId', - atype: 1 - }] - }, - - { - source: 'justtag.com', - uids: [{ - id: 'justId', - atype: 1 - }] - }, - { source: 'neustar.biz', uids: [{ @@ -72,13 +41,6 @@ userIdAsEids = [ }] }, - { - source: 'flashtalking.com', - uids: [{ - id: 'some-random-id-value', - atype: 1 - }, - { source: 'parrable.com', uids: [{ @@ -214,17 +176,17 @@ userIdAsEids = [ }] }, { - source: 'akamai.com', + source: 'admixer.net', uids: [{ id: 'some-random-id-value', - atype: 1 + atype: 3 }] }, { - source: 'admixer.net', + source: 'akamai.com', uids: [{ id: 'some-random-id-value', - atype: 3 + atype: 1 }] }, { @@ -233,20 +195,13 @@ userIdAsEids = [ id: 'some-random-id-value', atype: 3 }] - }, + }, { source: 'kpuid.com', uids: [{ id: 'some-random-id-value', atype: 3 }] - }, - { - source: 'yahoo.com', - uids: [{ - id: 'some-random-id-value', - atype: 3 - }] } ] ``` diff --git a/modules/userId/index.js b/modules/userId/index.js index 045786f59ec..a6a824fe89e 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -125,32 +125,23 @@ * @property {(function|undefined)} callback - function that will return an id */ -import {find, includes} from '../../src/polyfill.js'; -import {config} from '../../src/config.js'; -import * as events from '../../src/events.js'; -import {getGlobal} from '../../src/prebidGlobal.js'; -import {gdprDataHandler} from '../../src/adapterManager.js'; +/** + * @typedef {Object} RefreshUserIdsOptions + * @property {(string[]|undefined)} submoduleNames - submodules to refresh + */ + +import find from 'core-js-pure/features/array/find.js'; +import { config } from '../../src/config.js'; +import events from '../../src/events.js'; +import * as utils from '../../src/utils.js'; +import { getGlobal } from '../../src/prebidGlobal.js'; +import { gdprDataHandler } from '../../src/adapterManager.js'; import CONSTANTS from '../../src/constants.json'; -import {hook, module} from '../../src/hook.js'; -import {buildEidPermissions, createEidsArray, USER_IDS_CONFIG} from './eids.js'; -import {getCoreStorageManager} from '../../src/storageManager.js'; -import { - cyrb53Hash, - deepAccess, - delayExecution, - getPrebidInternal, - isArray, - isEmptyStr, - isFn, - isGptPubadsDefined, - isNumber, - isPlainObject, - logError, - logInfo, - logWarn, - timestamp, - isEmpty -} from '../../src/utils.js'; +import { module, hook } from '../../src/hook.js'; +import { createEidsArray, buildEidPermissions } from './eids.js'; +import { getCoreStorageManager } from '../../src/storageManager.js'; +import {getPrebidInternal} from '../../src/utils.js'; +import includes from 'core-js-pure/features/array/includes.js'; const MODULE_NAME = 'User ID'; const COOKIE = 'cookie'; @@ -191,11 +182,6 @@ export let syncDelay; /** @type {(number|undefined)} */ export let auctionDelay; -/** @type {(string|undefined)} */ -let ppidSource; - -let configListener; - /** @param {Submodule[]} submodules */ export function setSubmoduleRegistry(submodules) { submoduleRegistry = submodules; @@ -213,7 +199,7 @@ export function setStoredValue(submodule, value) { const domainOverride = (typeof submodule.submodule.domainOverride === 'function') ? submodule.submodule.domainOverride() : null; try { - const valueStr = isPlainObject(value) ? JSON.stringify(value) : value; + const valueStr = utils.isPlainObject(value) ? JSON.stringify(value) : value; const expiresStr = (new Date(Date.now() + (storage.expires * (60 * 60 * 24 * 1000)))).toUTCString(); if (storage.type === COOKIE) { coreStorage.setCookie(storage.name, valueStr, expiresStr, 'Lax', domainOverride); @@ -228,13 +214,13 @@ export function setStoredValue(submodule, value) { } } } catch (error) { - logError(error); + utils.logError(error); } } function setPrebidServerEidPermissions(initializedSubmodules) { let setEidPermissions = getPrebidInternal().setEidPermissions; - if (typeof setEidPermissions === 'function' && isArray(initializedSubmodules)) { + if (typeof setEidPermissions === 'function' && utils.isArray(initializedSubmodules)) { setEidPermissions(buildEidPermissions(initializedSubmodules)); } } @@ -267,7 +253,7 @@ function getStoredValue(storage, key = undefined) { storedValue = JSON.parse(storedValue); } } catch (e) { - logError(e); + utils.logError(e); } return storedValue; } @@ -292,7 +278,7 @@ function makeStoredConsentDataHash(consentData) { storedConsentData.apiVersion = consentData.apiVersion; } - return cyrb53Hash(JSON.stringify(storedConsentData)); + return utils.cyrb53Hash(JSON.stringify(storedConsentData)); } /** @@ -304,7 +290,7 @@ export function setStoredConsentData(consentData) { const expiresStr = (new Date(Date.now() + (CONSENT_DATA_COOKIE_STORAGE_CONFIG.expires * (60 * 60 * 24 * 1000)))).toUTCString(); coreStorage.setCookie(CONSENT_DATA_COOKIE_STORAGE_CONFIG.name, makeStoredConsentDataHash(consentData), expiresStr, 'Lax'); } catch (error) { - logError(error); + utils.logError(error); } } @@ -316,7 +302,7 @@ function getStoredConsentData() { try { return coreStorage.getCookie(CONSENT_DATA_COOKIE_STORAGE_CONFIG.name); } catch (e) { - logError(e); + utils.logError(e); } } @@ -346,10 +332,10 @@ function hasGDPRConsent(consentData) { if (!consentData.consentString) { return false; } - if (consentData.apiVersion === 1 && deepAccess(consentData, 'vendorData.purposeConsents.1') === false) { + if (consentData.apiVersion === 1 && utils.deepAccess(consentData, 'vendorData.purposeConsents.1') === false) { return false; } - if (consentData.apiVersion === 2 && deepAccess(consentData, 'vendorData.purpose.consents.1') === false) { + if (consentData.apiVersion === 2 && utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === false) { return false; } } @@ -377,7 +363,7 @@ export function findRootDomain(fullDomain = window.location.hostname) { const TEST_COOKIE_VALUE = 'writeable'; do { rootDomain = domainParts.slice(startIndex).join('.'); - let expirationDate = new Date(timestamp() + 10 * 1000).toUTCString(); + let expirationDate = new Date(utils.timestamp() + 10 * 1000).toUTCString(); // Write a test cookie coreStorage.setCookie( @@ -417,7 +403,7 @@ export function findRootDomain(fullDomain = window.location.hostname) { function processSubmoduleCallbacks(submodules, cb) { let done = () => {}; if (cb) { - done = delayExecution(() => { + done = utils.delayExecution(() => { clearTimeout(timeoutID); cb(); }, submodules.length); @@ -432,7 +418,7 @@ function processSubmoduleCallbacks(submodules, cb) { // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.submodule.decode(idObj, submodule.config); } else { - logInfo(`${MODULE_NAME}: ${submodule.submodule.name} - request id responded with an empty value`); + utils.logInfo(`${MODULE_NAME}: ${submodule.submodule.name} - request id responded with an empty value`); } done(); }); @@ -450,7 +436,7 @@ function getCombinedSubmoduleIds(submodules) { if (!Array.isArray(submodules) || !submodules.length) { return {}; } - const combinedSubmoduleIds = submodules.filter(i => isPlainObject(i.idObj) && Object.keys(i.idObj).length).reduce((carry, i) => { + const combinedSubmoduleIds = submodules.filter(i => utils.isPlainObject(i.idObj) && Object.keys(i.idObj).length).reduce((carry, i) => { Object.keys(i.idObj).forEach(key => { carry[key] = i.idObj[key]; }); @@ -460,20 +446,6 @@ function getCombinedSubmoduleIds(submodules) { return combinedSubmoduleIds; } -/** - * This function will return a submodule ID object for particular source name - * @param {SubmoduleContainer[]} submodules - * @param {string} sourceName - */ -function getSubmoduleId(submodules, sourceName) { - if (!Array.isArray(submodules) || !submodules.length) { - return {}; - } - const submodule = submodules.filter(sub => isPlainObject(sub.idObj) && - Object.keys(sub.idObj).length && USER_IDS_CONFIG[Object.keys(sub.idObj)[0]]?.source === sourceName); - return !isEmpty(submodule) ? submodule[0].idObj : []; -} - /** * This function will create a combined object for bidder with allowed subModule Ids * @param {SubmoduleContainer[]} submodules @@ -484,8 +456,8 @@ function getCombinedSubmoduleIdsForBidder(submodules, bidder) { return {}; } return submodules - .filter(i => !i.config.bidders || !isArray(i.config.bidders) || includes(i.config.bidders, bidder)) - .filter(i => isPlainObject(i.idObj) && Object.keys(i.idObj).length) + .filter(i => !i.config.bidders || !utils.isArray(i.config.bidders) || includes(i.config.bidders, bidder)) + .filter(i => utils.isPlainObject(i.idObj) && Object.keys(i.idObj).length) .reduce((carry, i) => { Object.keys(i.idObj).forEach(key => { carry[key] = i.idObj[key]; @@ -503,7 +475,7 @@ function addIdDataToAdUnitBids(adUnits, submodules) { return; } adUnits.forEach(adUnit => { - if (adUnit.bids && isArray(adUnit.bids)) { + if (adUnit.bids && utils.isArray(adUnit.bids)) { adUnit.bids.forEach(bid => { const combinedSubmoduleIds = getCombinedSubmoduleIdsForBidder(submodules, bid.bidder); if (Object.keys(combinedSubmoduleIds).length) { @@ -516,135 +488,59 @@ function addIdDataToAdUnitBids(adUnits, submodules) { }); } -function delayFor(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} +/** + * This is a common function that will initialize subModules if not already done and it will also execute subModule callbacks + */ +function initializeSubmodulesAndExecuteCallbacks(continueAuction) { + let delayed = false; -const INIT_CANCELED = {}; + // initialize submodules only when undefined + if (typeof initializedSubmodules === 'undefined') { + initializedSubmodules = initSubmodules(submodules, gdprDataHandler.getConsentData()); + if (initializedSubmodules.length) { + setPrebidServerEidPermissions(initializedSubmodules); + // list of submodules that have callbacks that need to be executed + const submodulesWithCallbacks = initializedSubmodules.filter(item => utils.isFn(item.callback)); -function idSystemInitializer({delay = delayFor} = {}) { - /** - * @returns a {promise, resolve, reject} trio where `promise` is resolved by calling `resolve` or `reject`. - */ - function breakpoint() { - const [SUCCESS, FAIL, RESULT] = [0, 1, 2]; - const status = {}; - - function finisher(slot) { - return function (val) { - if (status[slot] != null) { - status[slot](val); - } else { - status[slot] = true; - status[RESULT] = val; - } - } - } + if (submodulesWithCallbacks.length) { + if (continueAuction && auctionDelay > 0) { + // delay auction until ids are available + delayed = true; + let continued = false; + const continueCallback = function () { + if (!continued) { + continued = true; + continueAuction(); + } + } + utils.logInfo(`${MODULE_NAME} - auction delayed by ${auctionDelay} at most to fetch ids`); - return { - promise: new Promise((resolve, reject) => { - if (status[SUCCESS] != null) { - resolve(status[RESULT]); - } else if (status[FAIL] != null) { - reject(status[RESULT]); + timeoutID = setTimeout(continueCallback, auctionDelay); + processSubmoduleCallbacks(submodulesWithCallbacks, continueCallback); } else { - status[SUCCESS] = resolve; - status[FAIL] = reject; + // wait for auction complete before processing submodule callbacks + events.on(CONSTANTS.EVENTS.AUCTION_END, function auctionEndHandler() { + events.off(CONSTANTS.EVENTS.AUCTION_END, auctionEndHandler); + + // when syncDelay is zero, process callbacks now, otherwise delay process with a setTimeout + if (syncDelay > 0) { + setTimeout(function () { + processSubmoduleCallbacks(submodulesWithCallbacks); + }, syncDelay); + } else { + processSubmoduleCallbacks(submodulesWithCallbacks); + } + }); } - }), - resolve: finisher(SUCCESS), - reject: finisher(FAIL) - } - } - - const startInit = breakpoint(); - const startCallbacks = breakpoint(); - let cancel; - let initialized = false; - - function cancelAndTry(promise) { - if (cancel != null) { - cancel.reject(INIT_CANCELED); - } - cancel = breakpoint(); - return Promise.race([promise, cancel.promise]); - } - - // grab a reference to global vars so that the promise chains remain isolated; - // multiple calls to `init` (from tests) might otherwise cause them to interfere with each other - let initModules = initializedSubmodules; - let allModules = submodules; - - function checkRefs(fn) { - // unfortunately tests have their own global state that needs to be guarded, so even if we keep ours tidy, - // we cannot let things like submodule callbacks run (they pollute things like the global `server` XHR mock) - return function(...args) { - if (initModules === initializedSubmodules && allModules === submodules) { - return fn(...args); } } } - let done = cancelAndTry( - startInit.promise - .then(() => gdprDataHandler.promise) - .then(checkRefs((consentData) => { - initSubmodules(initModules, allModules, consentData); - })) - .then(() => startCallbacks.promise) - .then(checkRefs(() => { - const modWithCb = initModules.filter(item => isFn(item.callback)); - if (modWithCb.length) { - return new Promise((resolve) => processSubmoduleCallbacks(modWithCb, resolve)); - } - })) - ); - - /** - * with `ready` = true, starts initialization; with `refresh` = true, reinitialize submodules (optionally - * filtered by `submoduleNames`). - */ - return function ({refresh = false, submoduleNames = null, ready = false} = {}) { - if (ready && !initialized) { - initialized = true; - startInit.resolve(); - // submodule callbacks should run immediately if `auctionDelay` > 0, or `syncDelay` ms after the - // auction ends otherwise - if (auctionDelay > 0) { - startCallbacks.resolve(); - } else { - events.on(CONSTANTS.EVENTS.AUCTION_END, function auctionEndHandler() { - events.off(CONSTANTS.EVENTS.AUCTION_END, auctionEndHandler); - delay(syncDelay).then(startCallbacks.resolve); - }); - } - } - if (refresh) { - done = cancelAndTry( - done - .catch(() => null) - .then(() => gdprDataHandler.promise) // fetch again in case a refresh was forced before this was resolved - .then(checkRefs((consentData) => { - const cbModules = initSubmodules( - initModules, - allModules.filter((sm) => submoduleNames == null || submoduleNames.includes(sm.submodule.name)), - consentData, - true - ).filter((sm) => { - return sm.callback != null; - }); - if (cbModules.length) { - return new Promise((resolve) => processSubmoduleCallbacks(cbModules, resolve)); - } - })) - ); - } - return done; - }; + if (continueAuction && !delayed) { + continueAuction(); + } } -let initIdSystem; - /** * Hook is executed before adapters, but after consentManagement. Consent data is requied because * this module requires GDPR consent with Purpose #1 to save data locally. @@ -654,33 +550,11 @@ let initIdSystem; * @param {Object} reqBidsConfigObj required; This is the same param that's used in pbjs.requestBids. * @param {function} fn required; The next function in the chain, used by hook.js */ -export function requestBidsHook(fn, reqBidsConfigObj, {delay = delayFor} = {}) { - Promise.race([ - getUserIdsAsync(), - delay(auctionDelay) - ]).then(() => { +export function requestBidsHook(fn, reqBidsConfigObj) { + // initialize submodules only when undefined + initializeSubmodulesAndExecuteCallbacks(function () { // pass available user id data to bid adapters addIdDataToAdUnitBids(reqBidsConfigObj.adUnits || getGlobal().adUnits, initializedSubmodules); - - // userSync.ppid should be one of the 'source' values in getUserIdsAsEids() eg pubcid.org or id5-sync.com - const matchingUserId = ppidSource && (getUserIdsAsEids() || []).find(userID => userID.source === ppidSource); - if (matchingUserId && typeof deepAccess(matchingUserId, 'uids.0.id') === 'string') { - const ppidValue = matchingUserId.uids[0].id.replace(/[\W_]/g, ''); - if (ppidValue.length >= 32 && ppidValue.length <= 150) { - if (isGptPubadsDefined()) { - window.googletag.pubads().setPublisherProvidedId(ppidValue); - } else { - window.googletag = window.googletag || {}; - window.googletag.cmd = window.googletag.cmd || []; - window.googletag.cmd.push(function() { - window.googletag.pubads().setPublisherProvidedId(ppidValue); - }); - } - } else { - logWarn(`User ID - Googletag Publisher Provided ID for ${ppidSource} is not between 32 and 150 characters - ${ppidValue}`); - } - } - // calling fn allows prebid to continue processing fn.call(this, reqBidsConfigObj); }); @@ -691,7 +565,9 @@ export function requestBidsHook(fn, reqBidsConfigObj, {delay = delayFor} = {}) { * Simple use case will be passing these UserIds to A9 wrapper solution */ function getUserIds() { - return getCombinedSubmoduleIds(initializedSubmodules) + // initialize submodules only when undefined + initializeSubmodulesAndExecuteCallbacks(); + return getCombinedSubmoduleIds(initializedSubmodules); } /** @@ -699,115 +575,63 @@ function getUserIds() { * Simple use case will be passing these UserIds to A9 wrapper solution */ function getUserIdsAsEids() { - return createEidsArray(getUserIds()) + // initialize submodules only when undefined + initializeSubmodulesAndExecuteCallbacks(); + return createEidsArray(getCombinedSubmoduleIds(initializedSubmodules)); } /** - * This function will be exposed in global-name-space so that userIds stored by Prebid UserId module can be used by external codes as well. - * Simple use case will be passing these UserIds to A9 wrapper solution - */ +* This function will be exposed in the global-name-space so that userIds can be refreshed after initialization. +* @param {RefreshUserIdsOptions} options +*/ +function refreshUserIds(options, callback) { + let submoduleNames = options ? options.submoduleNames : null; + if (!submoduleNames) { + submoduleNames = []; + } -function getUserIdsAsEidBySource(sourceName) { - return createEidsArray(getSubmoduleId(initializedSubmodules, sourceName))[0]; -} + initializeSubmodulesAndExecuteCallbacks(function() { + let consentData = gdprDataHandler.getConsentData() -/** - * This function will be exposed in global-name-space so that userIds for a source can be exposed - * Sample use case is exposing this function to ESP - */ -function getEncryptedEidsForSource(source, encrypt, customFunction) { - return initIdSystem().then(() => { - let eidsSignals = {}; - - if (isFn(customFunction)) { - logInfo(`${MODULE_NAME} - Getting encrypted signal from custom function : ${customFunction.name} & source : ${source} `); - // Publishers are expected to define a common function which will be proxy for signal function. - const customSignals = customFunction(source); - eidsSignals[source] = customSignals ? encryptSignals(customSignals) : null; // by default encrypt using base64 to avoid JSON errors - } else { - // initialize signal with eids by default - const eid = getUserIdsAsEidBySource(source); - logInfo(`${MODULE_NAME} - Getting encrypted signal for eids :${JSON.stringify(eid)}`); - if (!isEmpty(eid)) { - eidsSignals[eid.source] = encrypt === true ? encryptSignals(eid) : eid.uids[0].id; // If encryption is enabled append version (1||) and encrypt entire object - } + // gdpr consent with purpose one is required, otherwise exit immediately + let {userIdModules, hasValidated} = validateGdprEnforcement(submodules, consentData); + if (!hasValidated && !hasGDPRConsent(consentData)) { + utils.logWarn(`${MODULE_NAME} - gdpr permission not valid for local storage or cookies, exit module`); + return; } - logInfo(`${MODULE_NAME} - Fetching encrypted eids: ${eidsSignals[source]}`); - return eidsSignals[source]; - }) -} -function encryptSignals(signals, version = 1) { - let encryptedSig = ''; - switch (version) { - case 1: // Base64 Encryption - encryptedSig = typeof signals === 'object' ? window.btoa(JSON.stringify(signals)) : window.btoa(signals); // Test encryption. To be replaced with better algo - break; - default: - break; - } - return `${version}||${encryptedSig}`; -} + // we always want the latest consentData stored, even if we don't execute any submodules + const storedConsentData = getStoredConsentData(); + setStoredConsentData(consentData); -/** -* This function will be exposed in the global-name-space so that publisher can register the signals-ESP. -*/ -function registerSignalSources() { - if (!isGptPubadsDefined()) { - return; - } - window.googletag.encryptedSignalProviders = window.googletag.encryptedSignalProviders || []; - const encryptedSignalSources = config.getConfig('userSync.encryptedSignalSources'); - if (encryptedSignalSources) { - const registerDelay = encryptedSignalSources.registerDelay || 0; - setTimeout(() => { - encryptedSignalSources['sources'] && encryptedSignalSources['sources'].forEach(({ source, encrypt, customFunc }) => { - source.forEach((src) => { - window.googletag.encryptedSignalProviders.push({ - id: src, - collectorFunction: () => getEncryptedEidsForSource(src, encrypt, customFunc) - }); - }); - }) - }, registerDelay) - } else { - logWarn(`${MODULE_NAME} - ESP : encryptedSignalSources config not defined under userSync Object`); - } -} + let callbackSubmodules = []; + for (let submodule of userIdModules) { + if (submoduleNames.length > 0 && + submoduleNames.indexOf(submodule.submodule.name) === -1) { + continue; + } -/** - * Force (re)initialization of ID submodules. - * - * This will force a refresh of the specified ID submodules regardless of `auctionDelay` / `syncDelay` settings, and - * return a promise that resolves to the same value as `getUserIds()` when the refresh is complete. - * If a refresh is already in progress, it will be canceled (rejecting promises returned by previous calls to `refreshUserIds`). - * - * @param submoduleNames? submodules to refresh. If omitted, refresh all submodules. - * @param callback? called when the refresh is complete - */ -function refreshUserIds({submoduleNames} = {}, callback) { - return initIdSystem({refresh: true, submoduleNames}) - .then(() => { - if (callback && isFn(callback)) { - callback(); + utils.logInfo(`${MODULE_NAME} - refreshing ${submodule.submodule.name}`); + populateSubmoduleId(submodule, consentData, storedConsentData, true); + updateInitializedSubmodules(submodule); + + if (initializedSubmodules.length) { + setPrebidServerEidPermissions(initializedSubmodules); } - return getUserIds(); - }); -} -/** - * @returns a promise that resolves to the same value as `getUserIds()`, but only once all ID submodules have completed - * initialization. This can also be used to synchronize calls to other ID accessors, e.g. - * - * ``` - * pbjs.getUserIdsAsync().then(() => { - * const eids = pbjs.getUserIdsAsEids(); // guaranteed to be completely initialized at this point - * }); - * ``` - */ + if (utils.isFn(submodule.callback)) { + callbackSubmodules.push(submodule); + } + } + + if (callbackSubmodules.length > 0) { + processSubmoduleCallbacks(callbackSubmodules); + } -function getUserIdsAsync() { - return initIdSystem().then(() => getUserIds(), (e) => e === INIT_CANCELED ? getUserIdsAsync() : Promise.reject(e)); + if (callback) { + callback(); + } + }); } /** @@ -839,7 +663,7 @@ function populateSubmoduleId(submodule, consentData, storedConsentData, forceRef response = submodule.submodule.extendId(submodule.config, consentData, storedId); } - if (isPlainObject(response)) { + if (utils.isPlainObject(response)) { if (response.id) { // A getId/extendId result assumed to be valid user id data, which should be saved to users local storage or cookies setStoredValue(submodule, response.id); @@ -861,18 +685,23 @@ function populateSubmoduleId(submodule, consentData, storedConsentData, forceRef submodule.idObj = submodule.config.value; } else { const response = submodule.submodule.getId(submodule.config, consentData, undefined); - if (isPlainObject(response)) { + if (utils.isPlainObject(response)) { if (typeof response.callback === 'function') { submodule.callback = response.callback; } if (response.id) { submodule.idObj = submodule.submodule.decode(response.id, submodule.config); } } } } -function initSubmodules(dest, submodules, consentData, forceRefresh = false) { +/** + * @param {SubmoduleContainer[]} submodules + * @param {ConsentData} consentData + * @returns {SubmoduleContainer[]} initialized submodules + */ +function initSubmodules(submodules, consentData) { // gdpr consent with purpose one is required, otherwise exit immediately let { userIdModules, hasValidated } = validateGdprEnforcement(submodules, consentData); if (!hasValidated && !hasGDPRConsent(consentData)) { - logWarn(`${MODULE_NAME} - gdpr permission not valid for local storage or cookies, exit module`); + utils.logWarn(`${MODULE_NAME} - gdpr permission not valid for local storage or cookies, exit module`); return []; } @@ -880,30 +709,25 @@ function initSubmodules(dest, submodules, consentData, forceRefresh = false) { const storedConsentData = getStoredConsentData(); setStoredConsentData(consentData); - const initialized = userIdModules.reduce((carry, submodule) => { - populateSubmoduleId(submodule, consentData, storedConsentData, forceRefresh); + return userIdModules.reduce((carry, submodule) => { + populateSubmoduleId(submodule, consentData, storedConsentData, false); carry.push(submodule); return carry; }, []); - if (initialized.length) { - setPrebidServerEidPermissions(initialized); - } - initialized.forEach(updateInitializedSubmodules.bind(null, dest)); - return initialized; } -function updateInitializedSubmodules(dest, submodule) { +function updateInitializedSubmodules(submodule) { let updated = false; - for (let i = 0; i < dest.length; i++) { - if (submodule.config.name.toLowerCase() === dest[i].config.name.toLowerCase()) { + for (let i = 0; i < initializedSubmodules.length; i++) { + if (submodule.config.name.toLowerCase() === initializedSubmodules[i].config.name.toLowerCase()) { updated = true; - dest[i] = submodule; + initializedSubmodules[i] = submodule; break; } } if (!updated) { - dest.push(submodule); + initializedSubmodules.push(submodule); } } @@ -922,17 +746,17 @@ function getValidSubmoduleConfigs(configRegistry, submoduleRegistry, activeStora } return configRegistry.reduce((carry, config) => { // every submodule config obj must contain a valid 'name' - if (!config || isEmptyStr(config.name)) { + if (!config || utils.isEmptyStr(config.name)) { return carry; } // Validate storage config contains 'type' and 'name' properties with non-empty string values // 'type' must be a value currently enabled in the browser if (config.storage && - !isEmptyStr(config.storage.type) && - !isEmptyStr(config.storage.name) && + !utils.isEmptyStr(config.storage.type) && + !utils.isEmptyStr(config.storage.name) && activeStorageTypes.indexOf(config.storage.type) !== -1) { carry.push(config); - } else if (isPlainObject(config.value)) { + } else if (utils.isPlainObject(config.value)) { carry.push(config); } else if (!config.storage && !config.value) { carry.push(config); @@ -952,9 +776,8 @@ function updateSubmodules() { // do this to avoid reprocessing submodules const addedSubmodules = submoduleRegistry.filter(i => !find(submodules, j => j.name === i.name)); - submodules.splice(0, submodules.length); // find submodule and the matching configuration, if found create and append a SubmoduleContainer - addedSubmodules.map(i => { + submodules = addedSubmodules.map(i => { const submoduleConfig = find(configs, j => j.name && (j.name.toLowerCase() === i.name.toLowerCase() || (i.aliasName && j.name.toLowerCase() === i.aliasName.toLowerCase()))); if (submoduleConfig && i.name !== submoduleConfig.name) submoduleConfig.name = i.name; @@ -965,13 +788,12 @@ function updateSubmodules() { callback: undefined, idObj: undefined } : null; - }).filter(submodule => submodule !== null) - .forEach((sm) => submodules.push(sm)); + }).filter(submodule => submodule !== null); if (!addedUserIdHook && submodules.length) { // priority value 40 will load after consentManagement with a priority of 50 getGlobal().requestBids.before(requestBidsHook, 40); - logInfo(`${MODULE_NAME} - usersync config updated for ${submodules.length} submodules: `, submodules.map(a => a.submodule.name)); + utils.logInfo(`${MODULE_NAME} - usersync config updated for ${submodules.length} submodules: `, submodules.map(a => a.submodule.name)); addedUserIdHook = true; } } @@ -992,17 +814,11 @@ export function attachIdSystem(submodule) { * so a callback is added to fire after the consentManagement module. * @param {{getConfig:function}} config */ -export function init(config, {delay = delayFor} = {}) { - ppidSource = undefined; +export function init(config) { submodules = []; configRegistry = []; addedUserIdHook = false; - initializedSubmodules = []; - initIdSystem = idSystemInitializer({delay}); - if (configListener != null) { - configListener(); - } - submoduleRegistry = []; + initializedSubmodules = undefined; // list of browser enabled storage types validStorageTypes = [ @@ -1012,36 +828,30 @@ export function init(config, {delay = delayFor} = {}) { // exit immediately if opt out cookie or local storage keys exists. if (validStorageTypes.indexOf(COOKIE) !== -1 && coreStorage.getCookie(PBJS_USER_ID_OPTOUT_NAME)) { - logInfo(`${MODULE_NAME} - opt-out cookie found, exit module`); + utils.logInfo(`${MODULE_NAME} - opt-out cookie found, exit module`); return; } if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && coreStorage.getDataFromLocalStorage(PBJS_USER_ID_OPTOUT_NAME)) { - logInfo(`${MODULE_NAME} - opt-out localStorage found, exit module`); + utils.logInfo(`${MODULE_NAME} - opt-out localStorage found, exit module`); return; } // listen for config userSyncs to be set - configListener = config.getConfig('userSync', conf => { + config.getConfig(conf => { // Note: support for 'usersync' was dropped as part of Prebid.js 4.0 const userSync = conf.userSync; - ppidSource = userSync.ppid; if (userSync && userSync.userIds) { configRegistry = userSync.userIds; - syncDelay = isNumber(userSync.syncDelay) ? userSync.syncDelay : DEFAULT_SYNC_DELAY; - auctionDelay = isNumber(userSync.auctionDelay) ? userSync.auctionDelay : NO_AUCTION_DELAY; + syncDelay = utils.isNumber(userSync.syncDelay) ? userSync.syncDelay : DEFAULT_SYNC_DELAY; + auctionDelay = utils.isNumber(userSync.auctionDelay) ? userSync.auctionDelay : NO_AUCTION_DELAY; updateSubmodules(); - initIdSystem({ready: true}); } }); // exposing getUserIds function in global-name-space so that userIds stored in Prebid can be used by external codes. (getGlobal()).getUserIds = getUserIds; (getGlobal()).getUserIdsAsEids = getUserIdsAsEids; - (getGlobal()).getEncryptedEidsForSource = getEncryptedEidsForSource; - (getGlobal()).registerSignalSources = registerSignalSources; (getGlobal()).refreshUserIds = refreshUserIds; - (getGlobal()).getUserIdsAsync = getUserIdsAsync; - (getGlobal()).getUserIdsAsEidBySource = getUserIdsAsEidBySource; } // init config update listener to start the application diff --git a/modules/userId/userId.md b/modules/userId/userId.md index bc0dad6462a..11bf74e5d87 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -1,22 +1,10 @@ ## User ID Example Configuration Example showing `cookie` storage for user id data for each of the submodules - ``` pbjs.setConfig({ userSync: { userIds: [{ - name: "33acrossId", - storage: { - type: "cookie", - name: "33acrossId", - expires: 90, - refreshInSeconds: 8*3600 - }, - params: { - pid: "0010b00002GYU4eBAH" // Example ID - } - }, { name: "pubCommonId", storage: { type: "cookie", @@ -56,17 +44,6 @@ pbjs.setConfig({ expires: 90, // Expiration in days refreshInSeconds: 8*3600 // User Id cache lifetime in seconds, defaulting to 'expires' }, - }, { - name: "ftrackId", - storage: { - type: "html5", - name: "ftrackId", - expires: 90, - refreshInSeconds: 8*3600 - }, - params: { - url: 'https://d9.flashtalking.com/d9core', // required, if not populated ftrack will not run - } }, { name: 'parrableId', params: { @@ -162,9 +139,6 @@ pbjs.setConfig({ name: "knssoId", expires: 30 }, - { - name: "dacId" - } ], syncDelay: 5000, auctionDelay: 1000 @@ -173,33 +147,10 @@ pbjs.setConfig({ ``` Example showing `localStorage` for user id data for some submodules - ``` pbjs.setConfig({ userSync: { userIds: [{ - name: "33acrossId", - storage: { - type: "html5", - name: "33acrossId", - expires: 90, - refreshInSeconds: 8*3600 - }, - params: { - pid: "0010b00002GYU4eBAH" // Example ID - } - }, { - name: 'trustpid', - params: { - maxDelayTime: 2500 - }, - bidders: ['adform'], - storage: { - type: 'html5', - name: 'trustpid', - expires: 60 - } - }, { name: "unifiedId", params: { partner: "prebid", @@ -327,33 +278,13 @@ pbjs.setConfig({ name: "knssoId", expires: 30 }, - } + } }, { name: 'imuid', params: { cid: 5126 // Set your Intimate Merger Customer ID here for production } - }, - { - name: 'connectId', - params: { - pixelId: 58776, - he: '0bef996248d63cea1529cb86de31e9547a712d9f380146e98bbd39beec70355a' - }, - storage: { - name: 'connectId', - type: 'html5', - expires: 15 - } - } - { - name: "qid", - storage: { - type: "html5", - name: "qid", - expires: 365 - } }], syncDelay: 5000 } @@ -361,7 +292,6 @@ pbjs.setConfig({ ``` Example showing how to configure a `value` object to pass directly to bid adapters - ``` pbjs.setConfig({ userSync: { @@ -386,9 +316,6 @@ pbjs.setConfig({ { name: "novatiq", value: { "snowflake": "81b001ec-8914-488c-a96e-8c220d4ee08895ef" } - }, - { - name: 'naveggId', }], syncDelay: 5000 } diff --git a/modules/userIdTargeting.js b/modules/userIdTargeting.js index b7fd137779b..e15c9ddaca2 100644 --- a/modules/userIdTargeting.js +++ b/modules/userIdTargeting.js @@ -1,7 +1,7 @@ import {config} from '../src/config.js'; import {getGlobal} from '../src/prebidGlobal.js'; import CONSTANTS from '../src/constants.json'; -import * as events from '../src/events.js'; +import events from '../src/events.js'; import { isStr, isPlainObject, isBoolean, isFn, hasOwn, logInfo } from '../src/utils.js'; const MODULE_NAME = 'userIdTargeting'; diff --git a/modules/validationFpdModule/config.js b/modules/validationFpdModule/config.js index c87265fa1df..f6adfea70eb 100644 --- a/modules/validationFpdModule/config.js +++ b/modules/validationFpdModule/config.js @@ -85,21 +85,7 @@ export const ORTB_MAP = { }, publisher: { type: TYPES.object, - isArray: false, - children: { - id: { type: TYPES.string }, - name: { type: TYPES.string }, - cat: { - type: TYPES.object, - isArray: true, - childType: TYPES.string - }, - domain: { type: TYPES.string }, - ext: { - type: TYPES.object, - isArray: false - } - } + isArray: false }, } }, @@ -135,15 +121,5 @@ export const ORTB_MAP = { } } } - }, - bcat: { - type: TYPES.object, - isArray: true, - childType: TYPES.string - }, - badv: { - type: TYPES.object, - isArray: true, - childType: TYPES.string } } diff --git a/modules/validationFpdModule/index.js b/modules/validationFpdModule/index.js index 2db170c1bd1..c23f7e09316 100644 --- a/modules/validationFpdModule/index.js +++ b/modules/validationFpdModule/index.js @@ -3,7 +3,7 @@ * @module modules/firstPartyData */ import { config } from '../../src/config.js'; -import { isEmpty, isNumber, logWarn, deepAccess } from '../../src/utils.js'; +import * as utils from '../../src/utils.js'; import { ORTB_MAP } from './config.js'; import { submodule } from '../../src/hook.js'; import { getStorageManager } from '../../src/storageManager.js'; @@ -19,9 +19,9 @@ let optout; function isEmptyData(data) { let check = true; - if (typeof data === 'object' && !isEmpty(data)) { + if (typeof data === 'object' && !utils.isEmpty(data)) { check = false; - } else if (typeof data !== 'object' && (isNumber(data) || data)) { + } else if (typeof data !== 'object' && (utils.isNumber(data) || data)) { check = false; } @@ -42,7 +42,7 @@ function getRequiredData(obj, required, parent, i) { required.forEach(key => { if (!obj[key] || isEmptyData(obj[key])) { check = false; - logWarn(`Filtered ${parent}[] value at index ${i} in ortb2 data: missing required property ${key}`); + utils.logWarn(`Filtered ${parent}[] value at index ${i} in ortb2 data: missing required property ${key}`); } }); @@ -91,22 +91,21 @@ export function filterArrayData(arr, child, path, parent) { return true; } - logWarn(`Filtered ${parent}[] value at index ${i} in ortb2 data: expected type ${child.type}`); + utils.logWarn(`Filtered ${parent}[] value at index ${i} in ortb2 data: expected type ${child.type}`); }).filter((index, i) => { let requiredCheck = true; - let mapping = deepAccess(ORTB_MAP, path); + let mapping = utils.deepAccess(ORTB_MAP, path); if (mapping && mapping.required) requiredCheck = getRequiredData(index, mapping.required, parent, i); if (requiredCheck) return true; }).reduce((result, value, i) => { let typeBool = false; - let mapping = deepAccess(ORTB_MAP, path); + let mapping = utils.deepAccess(ORTB_MAP, path); switch (child.type) { case 'string': result.push(value); - typeBool = true; break; case 'object': if (mapping && mapping.children) { @@ -126,7 +125,7 @@ export function filterArrayData(arr, child, path, parent) { break; } - if (!typeBool) logWarn(`Filtered ${parent}[] value at index ${i} in ortb2 data: expected type ${child.type}`); + if (!typeBool) utils.logWarn(`Filtered ${parent}[] value at index ${i} in ortb2 data: expected type ${child.type}`); return result; }, []); @@ -146,26 +145,26 @@ export function validateFpd(fpd, path = '', parent = '') { // Filter out imp property if exists let validObject = Object.assign({}, Object.keys(fpd).filter(key => { - let mapping = deepAccess(ORTB_MAP, path + key); + let mapping = utils.deepAccess(ORTB_MAP, path + key); if (!mapping || !mapping.invalid) return key; - logWarn(`Filtered ${parent}${key} property in ortb2 data: invalid property`); + utils.logWarn(`Filtered ${parent}${key} property in ortb2 data: invalid property`); }).filter(key => { - let mapping = deepAccess(ORTB_MAP, path + key); + let mapping = utils.deepAccess(ORTB_MAP, path + key); // let typeBool = false; let typeBool = (mapping) ? typeValidation(fpd[key], {type: mapping.type, isArray: mapping.isArray}) : true; if (typeBool || !mapping) return key; - logWarn(`Filtered ${parent}${key} property in ortb2 data: expected type ${(mapping.isArray) ? 'array' : mapping.type}`); + utils.logWarn(`Filtered ${parent}${key} property in ortb2 data: expected type ${(mapping.isArray) ? 'array' : mapping.type}`); }).reduce((result, key) => { - let mapping = deepAccess(ORTB_MAP, path + key); + let mapping = utils.deepAccess(ORTB_MAP, path + key); let modified = {}; if (mapping) { if (mapping.optoutApplies && optout) { - logWarn(`Filtered ${parent}${key} data: pubcid optout found`); + utils.logWarn(`Filtered ${parent}${key} data: pubcid optout found`); return result; } @@ -176,7 +175,7 @@ export function validateFpd(fpd, path = '', parent = '') { // Check if modified data has data and return (!isEmptyData(modified)) ? result[key] = modified - : logWarn(`Filtered ${parent}${key} property in ortb2 data: empty data found`); + : utils.logWarn(`Filtered ${parent}${key} property in ortb2 data: empty data found`); } else { result[key] = fpd[key]; } diff --git a/modules/vdoaiBidAdapter.js b/modules/vdoaiBidAdapter.js index 40e3b3322a7..4bf5a27c002 100644 --- a/modules/vdoaiBidAdapter.js +++ b/modules/vdoaiBidAdapter.js @@ -1,4 +1,4 @@ -import { getAdUnitSizes } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; @@ -32,7 +32,7 @@ export const spec = { } return validBidRequests.map(bidRequest => { - const sizes = getAdUnitSizes(bidRequest); + const sizes = utils.getAdUnitSizes(bidRequest); const payload = { placementId: bidRequest.params.placementId, sizes: sizes, diff --git a/modules/ventes.md b/modules/ventes.md deleted file mode 100644 index 5f0f571ecd8..00000000000 --- a/modules/ventes.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -layout: bidder -title: ventes -description: Prebid ventes Bidder Adapter -pbjs: false -biddercode: ventes -gdpr_supported: false -usp_supported: false -media_types: banner -coppa_supported: false -schain_supported: false -dchain_supported: false -prebid_member: false ---- - -### BidParams -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-----------------|----------|-----------------------------------------------------------|----------------------------------------------|---------------| -| `placementId` | required | Placement ID from Ventes Avenues | `'VA-062-0013-0183'` | `string` | -| `publisherId` | required | Publisher ID from Ventes Avenues | `'VA-062'` | `string` | -| `user` | optional | Object that specifies information about an external user. | `user: { age: 25, gender: 0, dnt: true}` | `object` | -| `app` | optional | Object containing mobile app parameters. | `app : { id: 'app-id'}` | `object` | - -#### User Object - -{: .table .table-bordered .table-striped } -| Name | Description | Example | Type | -|-------------------|-------------------------------------------------------------------------------------------|-----------------------|-----------------------| -| `age` | The age of the user. | `35` | `integer` | -| `externalUid` | Specifies a string that corresponds to an external user ID for this user. | `'1234567890abcdefg'` | `string` | -| `segments` | Specifies the segments to which the user belongs. | `[1, 2]` | `Array` | -| `gender` | Specifies the gender of the user. Allowed values: Unknown: `0`; Male: `1`; Female: `2` | `1` | `integer` | -| `dnt` | Do not track flag. Indicates if tracking cookies should be disabled for this auction | `true` | `boolean` | -| `language` | Two-letter ANSI code for this user's language. | `EN` | `string` | - - -### Ad Unit Setup for Banner -```javascript -var adUnits = [ -{ - code: 'test-hb-ad-11111-1', - mediaTypes: { - banner: { - sizes: [ - [300, 250] - ] - } - }, - bids: [{ - bidder: 'ventes', - params: { - placementId: 'VA-062-0013-0183', - publisherId: '5cebea3c9eea646c7b623d5e', - IABCategories: "['IAB1', 'IAB5']", - device:{ - ip: '123.145.167.189', - ifa:"AEBE52E7-03EE-455A-B3C4-E57283966239", - }, - app: { - id: "agltb3B1Yi1pbmNyDAsSA0FwcBiJkfIUDA", - name: "Yahoo Weather", - bundle: 'com.kiloo.subwaysurf', - storeurl: 'https://play.google.com/store/apps/details?id=com.kiloo.subwaysurf&hl=en', - domain: 'somoaudience.com', - } - } - }] - } -] -``` diff --git a/modules/ventesBidAdapter.js b/modules/ventesBidAdapter.js deleted file mode 100644 index 42292ddaed3..00000000000 --- a/modules/ventesBidAdapter.js +++ /dev/null @@ -1,397 +0,0 @@ -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {convertCamelToUnderscore, isArray, isNumber, isPlainObject, isStr, replaceAuctionPrice} from '../src/utils.js'; -import {find} from '../src/polyfill.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; - -const BID_METHOD = 'POST'; -const BIDDER_URL = 'http://13.234.201.146:8088/va/ad'; - -const DOMAIN_REGEX = new RegExp('//([^/]*)'); - -function groupBy(values, key) { - const groups = values.reduce((acc, value) => { - const groupId = value[key]; - - if (!acc[groupId]) acc[groupId] = []; - acc[groupId].push(value); - - return acc; - }, {}); - - return Object - .keys(groups) - .map(id => ({ - id, - key, - values: groups[id] - })); -} - -function validateMediaTypes(mediaTypes, allowedMediaTypes) { - if (!isPlainObject(mediaTypes)) return false; - if (!allowedMediaTypes.some(mediaType => mediaType in mediaTypes)) return false; - - if (isBanner(mediaTypes)) { - if (!validateBanner(mediaTypes.banner)) return false; - } - return true; -} - -function isBanner(mediaTypes) { - return isPlainObject(mediaTypes) && isPlainObject(mediaTypes.banner); -} - -function validateBanner(banner) { - return isPlainObject(banner) && - isArray(banner.sizes) && - (banner.sizes.length > 0) && - banner.sizes.every(validateMediaSizes); -} - -function validateMediaSizes(mediaSize) { - return isArray(mediaSize) && - (mediaSize.length === 2) && - mediaSize.every(size => (isNumber(size) && size >= 0)); -} - -function hasUserInfo(bid) { - return !!bid.params.user; -} - -function validateParameters(parameters) { - if (!(parameters.placementId)) { - return false; - } - if (!(parameters.publisherId)) { - return false; - } - - return true; -} - -function extractSiteDomainFromURL(url) { - if (!url || !isStr(url)) return null; - - const domain = url.match(DOMAIN_REGEX); - - if (isArray(domain) && domain.length === 2) return domain[1]; - - return null; -} - -function generateSiteFromAdUnitContext(bidRequests, adUnitContext) { - if (!adUnitContext || !adUnitContext.refererInfo) return null; - - const domain = extractSiteDomainFromURL(adUnitContext.refererInfo.referer); - const publisherId = bidRequests[0].params.publisherId; - - if (!domain) return null; - - return { - page: adUnitContext.refererInfo.referer, - domain: domain, - name: domain, - publisher: { - id: publisherId - } - }; -} - -function validateServerRequest(serverRequest) { - return isPlainObject(serverRequest) && - isPlainObject(serverRequest.data) && - isArray(serverRequest.data.imp) -} - -function createServerRequestFromAdUnits(adUnits, bidRequestId, adUnitContext) { - return { - method: BID_METHOD, - url: BIDDER_URL, - data: generateBidRequestsFromAdUnits(adUnits, bidRequestId, adUnitContext), - options: { - contentType: 'application/json', - withCredentials: false, - } - } -} - -function generateBidRequestsFromAdUnits(bidRequests, bidRequestId, adUnitContext) { - const userObjBid = find(bidRequests, hasUserInfo); - let userObj = {}; - if (userObjBid) { - Object.keys(userObjBid.params.user) - .forEach((param) => { - let uparam = convertCamelToUnderscore(param); - if (param === 'segments' && isArray(userObjBid.params.user[param])) { - let segs = []; - userObjBid.params.user[param].forEach(val => { - if (isNumber(val)) { - segs.push({ - 'id': val - }); - } else if (isPlainObject(val)) { - segs.push(val); - } - }); - userObj[uparam] = segs; - } else if (param !== 'segments') { - userObj[uparam] = userObjBid.params.user[param]; - } - }); - } - - const deviceObjBid = find(bidRequests, hasDeviceInfo); - let deviceObj; - if (deviceObjBid && deviceObjBid.params && deviceObjBid.params.device) { - deviceObj = {}; - Object.keys(deviceObjBid.params.device) - .forEach(param => deviceObj[param] = deviceObjBid.params.device[param]); - if (!deviceObjBid.hasOwnProperty('ua')) { - deviceObj.ua = navigator.userAgent; - } - if (!deviceObjBid.hasOwnProperty('language')) { - deviceObj.language = navigator.language; - } - } else { - deviceObj = {}; - deviceObj.ua = navigator.userAgent; - deviceObj.language = navigator.language; - } - - const payload = {} - payload.id = bidRequestId - payload.at = 1 - payload.cur = ['USD'] - payload.imp = bidRequests.reduce(generateImpressionsFromAdUnit, []) - const appDeviceObjBid = find(bidRequests, hasAppInfo); - if (!appDeviceObjBid) { - payload.site = generateSiteFromAdUnitContext(bidRequests, adUnitContext) - } else { - let appIdObj; - if (appDeviceObjBid && appDeviceObjBid.params && appDeviceObjBid.params.app && appDeviceObjBid.params.app.id) { - appIdObj = {}; - Object.keys(appDeviceObjBid.params.app) - .forEach(param => appIdObj[param] = appDeviceObjBid.params.app[param]); - } - payload.app = appIdObj; - } - payload.device = deviceObj; - payload.user = userObj - return payload -} - -function generateImpressionsFromAdUnit(acc, adUnit) { - const { - bidId, - mediaTypes, - params - } = adUnit; - const { - placementId - } = params; - const pmp = {}; - - if (placementId) pmp.deals = [{ id: placementId }] - - const imps = Object - .keys(mediaTypes) - .reduce((acc, mediaType) => { - const data = mediaTypes[mediaType]; - const impId = `${bidId}`; - - if (mediaType === 'banner') return acc.concat(generateBannerFromAdUnit(impId, data, params)); - }, []); - - return acc.concat(imps); -} - -function generateBannerFromAdUnit(impId, data, params) { - const { - position, - placementId - } = params; - const pos = position || 0; - const pmp = {}; - const ext = { - placementId - }; - - if (placementId) pmp.deals = [{ id: placementId }] - - return data.sizes.map(([w, h]) => ({ - id: `${impId}`, - banner: { - format: [{ - w, - h - }], - w, - h, - pos - }, - pmp, - ext, - tagid: placementId - })); -} - -function validateServerResponse(serverResponse) { - return isPlainObject(serverResponse) && - isPlainObject(serverResponse.body) && - isStr(serverResponse.body.cur) && - isArray(serverResponse.body.seatbid); -} - -function seatBidsToAds(seatBid, bidResponse, serverRequest) { - return seatBid.bid - .filter(bid => validateBids(bid)) - .map(bid => generateAdFromBid(bid, bidResponse)); -} - -function validateBids(bid) { - if (!isPlainObject(bid)) return false; - if (!isStr(bid.impid)) return false; - if (!isStr(bid.crid)) return false; - if (!isNumber(bid.price)) return false; - if (!isNumber(bid.w)) return false; - if (!isNumber(bid.h)) return false; - if (!bid.adm) return false; - if (bid.adm) { - if (!isStr(bid.adm)) return false; - } - return true; -} - -function getMediaType(adm) { - const videoRegex = new RegExp(/VAST\s+version/); - - if (videoRegex.test(adm)) { - return VIDEO; - } - - const markup = safeJSONparse(adm.replace(/\\/g, '')); - - if (markup && isPlainObject(markup.native)) { - return NATIVE; - } - - return BANNER; -} - -function safeJSONparse(...args) { - try { - return JSON.parse(...args); - } catch (_) { - return undefined; - } -} - -function generateAdFromBid(bid, bidResponse) { - const mediaType = getMediaType(bid.adm); - const base = { - requestId: bid.impid, - cpm: bid.price, - currency: bidResponse.cur, - ttl: 10, - creativeId: bid.crid, - mediaType: mediaType, - netRevenue: true - }; - - if (bid.adomain) { - base.meta = { - advertiserDomains: bid.adomain - }; - } - - const size = getSizeFromBid(bid); - const creative = getCreativeFromBid(bid); - - return { - ...base, - height: size.height, - width: size.width, - ad: creative.markup, - adUrl: creative.markupUrl, - renderer: creative.renderer - }; -} - -function getSizeFromBid(bid) { - if (isNumber(bid.w) && isNumber(bid.h)) { - return { - width: bid.w, - height: bid.h - }; - } - return { - width: null, - height: null - }; -} - -function getCreativeFromBid(bid) { - const shouldUseAdMarkup = !!bid.adm; - const price = bid.price; - return { - markup: shouldUseAdMarkup ? replaceAuctionPrice(bid.adm, price) : null, - markupUrl: !shouldUseAdMarkup ? replaceAuctionPrice(bid.nurl, price) : null - }; -} - -function hasDeviceInfo(bid) { - if (bid.params) { - return !!bid.params.device - } -} - -function hasAppInfo(bid) { - if (bid.params) { - return !!bid.params.app - } -} - -const venavenBidderSpec = { - code: 'ventes', - supportedMediaTypes: [BANNER], - isBidRequestValid(adUnit) { - const allowedBidderCodes = [this.code]; - - return isPlainObject(adUnit) && - allowedBidderCodes.indexOf(adUnit.bidder) !== -1 && - isStr(adUnit.adUnitCode) && - isStr(adUnit.bidderRequestId) && - isStr(adUnit.bidId) && - validateMediaTypes(adUnit.mediaTypes, this.supportedMediaTypes) && - validateParameters(adUnit.params); - }, - buildRequests(bidRequests, bidderRequest) { - if (!bidRequests) return null; - - return groupBy(bidRequests, 'bidderRequestId').map(group => { - const bidRequestId = group.id; - const adUnits = groupBy(group.values, 'bidId').map((group) => { - const length = group.values.length; - return length > 0 && group.values[length - 1] - }); - - return createServerRequestFromAdUnits(adUnits, bidRequestId, bidderRequest) - }); - }, - interpretResponse(serverResponse, serverRequest) { - if (!validateServerRequest(serverRequest)) return []; - if (!validateServerResponse(serverResponse)) return []; - - const bidResponse = serverResponse.body; - - return bidResponse.seatbid - .filter(seatBid => isPlainObject(seatBid) && isArray(seatBid.bid)) - .reduce((acc, seatBid) => acc.concat(seatBidsToAds(seatBid, bidResponse, serverRequest)), []); - } -}; - -registerBidder(venavenBidderSpec); - -export { - venavenBidderSpec as spec -}; diff --git a/modules/ventesBidAdapter.md b/modules/ventesBidAdapter.md deleted file mode 100644 index c79ef080cd1..00000000000 --- a/modules/ventesBidAdapter.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -layout: bidder -title: ventes -description: Prebid ventes Bidder Adapter -pbjs: false -biddercode: ventes -gdpr_supported: false -usp_supported: false -media_types: banner -coppa_supported: false -schain_supported: false -dchain_supported: false -prebid_member: false ---- - -### BidParams -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-----------------|----------|-----------------------------------------------------------|----------------------------------------------|---------------| -| `placementId` | required | Placement ID from Ventes Avenues | `'VA-062-0013-0183'` | `string` | -| `publisherId` | required | Publisher ID from Ventes Avenues | `'VA-062'` | `string` | -| `user` | optional | Object that specifies information about an external user. | `user: { age: 25, gender: 0, dnt: true}` | `object` | -| `app` | required | Object containing mobile app parameters. | `app : { id: 'app-id'}` | `object` | -| `device` | required | Object containing device info mandatory for mobile devices| `device : { ifa: 'device-id'}` | `object` | - -#### User Object - -{: .table .table-bordered .table-striped } -| Name | Description | Example | Type | -|-------------------|-------------------------------------------------------------------------------------------|-----------------------|-----------------------| -| `age` | The age of the user. | `35` | `integer` | -| `externalUid` | Specifies a string that corresponds to an external user ID for this user. | `'1234567890abcdefg'` | `string` | -| `segments` | Specifies the segments to which the user belongs. | `[1, 2]` | `Array` | -| `gender` | Specifies the gender of the user. Allowed values: Unknown: `0`; Male: `1`; Female: `2` | `1` | `integer` | -| `dnt` | Do not track flag. Indicates if tracking cookies should be disabled for this auction | `true` | `boolean` | -| `language` | Two-letter ANSI code for this user's language. | `EN` | `string` | - - -### Ad Unit Setup for Banner through mobile devices -```javascript -var adUnits = [ -{ - code: 'test-hb-ad-11111-1', - mediaTypes: { - banner: { - sizes: [ - [300, 250] - ] - } - }, - bids: [{ - bidder: 'ventes', - params: { - placementId: 'VA-062-0013-0183', - publisherId: '5cebea3c9eea646c7b623d5e', - IABCategories: "['IAB1', 'IAB5']", - device:{ - ifa:"AEBE52E7-03EE-455A-B3C4-E57283966239", - }, - app: { - id: "agltb3B1Yi1pbmNyDAsSA0FwcBiJkfIUDA", - name: "Yahoo Weather", - bundle: 'com.kiloo.subwaysurf', - storeurl: 'https://play.google.com/store/apps/details?id=com.kiloo.subwaysurf&hl=en', - domain: 'somoaudience.com', - } - } - }] - } -] -``` - -### Ad Unit Setup for Banner through Websites -```javascript -var adUnits = [ -{ - code: 'test-hb-ad-11111-1', - mediaTypes: { - banner: { - sizes: [ - [300, 250] - ] - } - }, - bids: [{ - bidder: 'ventes', - params: { - placementId: 'VA-002-0007-0799', - publisherId: '5cebea3c9eea646c7b623d5e', - } - }] - } -] diff --git a/modules/verizonMediaIdSystem.js b/modules/verizonMediaIdSystem.js index 27577ad0de4..ca395087d2d 100644 --- a/modules/verizonMediaIdSystem.js +++ b/modules/verizonMediaIdSystem.js @@ -7,8 +7,8 @@ import {ajax} from '../src/ajax.js'; import {submodule} from '../src/hook.js'; -import {formatQS, logError} from '../src/utils.js'; -import {includes} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import includes from 'core-js-pure/features/array/includes.js'; const MODULE_NAME = 'verizonMediaId'; const VENDOR_ID = 25; @@ -51,7 +51,7 @@ export const verizonMediaIdSubmodule = { const params = config.params || {}; if (!params || typeof params.he !== 'string' || (typeof params.pixelId === 'undefined' && typeof params.endpoint === 'undefined')) { - logError('The verizonMediaId submodule requires the \'he\' and \'pixelId\' parameters to be defined.'); + utils.logError('The verizonMediaId submodule requires the \'he\' and \'pixelId\' parameters to be defined.'); return; } @@ -75,18 +75,18 @@ export const verizonMediaIdSubmodule = { try { responseObj = JSON.parse(response); } catch (error) { - logError(error); + utils.logError(error); } } callback(responseObj); }, error: error => { - logError(`${MODULE_NAME}: ID fetch encountered an error`, error); + utils.logError(`${MODULE_NAME}: ID fetch encountered an error`, error); callback(); } }; const endpoint = VMCID_ENDPOINT.replace(PLACEHOLDER, params.pixelId); - let url = `${params.endpoint || endpoint}?${formatQS(data)}`; + let url = `${params.endpoint || endpoint}?${utils.formatQS(data)}`; verizonMediaIdSubmodule.getAjaxFn()(url, callbacks, null, {method: 'GET', withCredentials: true}); }; return {callback: resp}; diff --git a/modules/vibrantmediaBidAdapter.js b/modules/vibrantmediaBidAdapter.js deleted file mode 100644 index 0613f722af8..00000000000 --- a/modules/vibrantmediaBidAdapter.js +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Vibrant Media Ltd. - * - * Prebid Adapter for sending bid requests to the prebid server and bid responses back to the client - * - * Note: Only BANNER and VIDEO are currently supported by the prebid server. - */ - -import {logError, triggerPixel} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {OUTSTREAM} from '../src/video.js'; - -const BIDDER_CODE = 'vibrantmedia'; -const VIBRANT_MEDIA_PREBID_URL = 'https://prebid.intellitxt.com/prebid'; -const VALID_PIXEL_URL_REGEX = /^https?:\/\/[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+([/?].*)?$/; -const SUPPORTED_MEDIA_TYPES = [BANNER, NATIVE, VIDEO]; - -/** - * Returns whether the given bid request contains at least one supported media request, which has valid data. (We can - * ignore invalid/unsupported ones, as they will be filtered out by the prebid server.) - * - * @param {*} bidRequest the bid requests sent by the Prebid API. - * - * @return {boolean} true if the given bid request contains at least one supported media request with valid details, - * otherwise false. - */ -const areValidSupportedMediaTypesPresent = function(bidRequest) { - const mediaTypes = Object.keys(bidRequest.mediaTypes); - - return mediaTypes.some(function(mediaType) { - if (mediaType === BANNER) { - return true; - } else if (mediaType === VIDEO) { - return (bidRequest.mediaTypes[VIDEO].context === OUTSTREAM); - } else if (mediaType === NATIVE) { - return !!bidRequest.mediaTypes[NATIVE].image; - } - - return false; - }); -}; - -/** - * Returns whether the given URL contains just a domain, and not (for example) a subdirectory or query parameters. - * @param {string} url the URL to check. - * @returns {boolean} whether the URL contains just a domain. - */ -const isBaseUrl = function(url) { - const urlMinusScheme = url.substring(url.indexOf('://') + 3); - const endOfDomain = urlMinusScheme.indexOf('/'); - return (endOfDomain === -1) || (endOfDomain === (urlMinusScheme.length - 1)); -}; - -const isValidPixelUrl = function (candidateUrl) { - return VALID_PIXEL_URL_REGEX.test(candidateUrl); -}; - -/** - * Returns transformed bid requests that are in a format native to the prebid server. - * - * @param {*[]} bidRequests the bid requests sent by the Prebid API. - * - * @returns {*[]} the transformed bid requests. - */ -const transformBidRequests = function(bidRequests) { - const transformedBidRequests = []; - - bidRequests.forEach(function(bidRequest) { - const params = bidRequest.params || {}; - const transformedBidRequest = { - code: bidRequest.adUnitCode || bidRequest.code, - id: bidRequest.placementId || params.placementId || params.invCode, - requestId: bidRequest.bidId || bidRequest.transactionId, - bidder: bidRequest.bidder, - mediaTypes: bidRequest.mediaTypes, - bids: bidRequest.bids, - sizes: bidRequest.sizes - }; - - transformedBidRequests.push(transformedBidRequest); - }); - - return transformedBidRequests; -}; - -/** @type {BidderSpec} */ -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: SUPPORTED_MEDIA_TYPES, - - /** - * Transforms the 'raw' bid params into ones that this adapter can use, prior to creating the bid request. - * - * @param {object} bidParams the params to transform. - * - * @returns {object} the bid params. - */ - transformBidParams: function(bidParams) { - return bidParams; - }, - - /** - * Determines whether or not the given bid request is valid. For all bid requests passed to the buildRequests - * function, each will have been passed to this function and this function will have returned true. - * - * @param {object} bid the bid params to validate. - * - * @return {boolean} true if this is a valid bid, otherwise false. - * @see SUPPORTED_MEDIA_TYPES - */ - isBidRequestValid: function(bid) { - const areBidRequestParamsValid = !!(bid.params.placementId || (bid.params.member && bid.params.invCode)); - return areBidRequestParamsValid && areValidSupportedMediaTypesPresent(bid); - }, - - /** - * Return a prebid server request from the list of bid requests. - * - * @param {BidRequest[]} validBidRequests an array of bids validated via the isBidRequestValid function. - * @param {BidderRequest} bidderRequest an object with data common to all bid requests. - * - * @return ServerRequest Info describing the request to the prebid server. - */ - buildRequests: function(validBidRequests, bidderRequest) { - const transformedBidRequests = transformBidRequests(validBidRequests); - - var url = window.parent.location.href; - - if ((window.self === window.top) && (!url || (url.substr(0, 4) !== 'http') || isBaseUrl(url))) { - url = document.URL; - } - - url = encodeURIComponent(url); - - const prebidData = { - url, - gdpr: bidderRequest.gdprConsent, - usp: bidderRequest.uspConsent, - window: { - width: window.innerWidth, - height: window.innerHeight, - }, - biddata: transformedBidRequests, - }; - - return { - method: 'POST', - url: VIBRANT_MEDIA_PREBID_URL, - data: JSON.stringify(prebidData) - }; - }, - - /** - * Translate the Kormorant prebid server response into a list of bids. - * - * @param {ServerResponse} serverResponse a successful response from the prebid server. - * @param {BidRequest} bidRequest the original bid request associated with this response. - * - * @return {Bid[]} an array of bids returned by the prebid server, translated into the expected Prebid.js format. - */ - interpretResponse: function(serverResponse, bidRequest) { - const bids = serverResponse.body; - - bids.forEach(function(bid) { - bid.adResponse = serverResponse; - }); - - return bids; - }, - - /** - * Called if the Prebid API gives up waiting for a prebid server response. - * - * Example timeout data: - * - * [{ - * "bidder": "example", - * "bidId": "51ef8751f9aead", - * "params": { - * ... - * }, - * "adUnitCode": "div-gpt-ad-1460505748561-0", - * "timeout": 3000, - * "auctionId": "18fd8b8b0bd757" - * }] - * - * @param {{}} timeoutData data relating to the timeout. - */ - onTimeout: function(timeoutData) { - logError('Timed out waiting for bids: ' + JSON.stringify(timeoutData)); - }, - - /** - * Called when a bid returned by the prebid server is successful. - * - * Example bid won data: - * - * { - * "bidder": "example", - * "width": 300, - * "height": 250, - * "adId": "330a22bdea4cac", - * "mediaType": "banner", - * "cpm": 0.28 - * "ad": "...", - * "requestId": "418b37f85e772c", - * "adUnitCode": "div-gpt-ad-1460505748561-0", - * "size": "350x250", - * "adserverTargeting": { - * "hb_bidder": "example", - * "hb_adid": "330a22bdea4cac", - * "hb_pb": "0.20", - * "hb_size": "350x250" - * } - * } - * - * @param {*} bidData the data associated with the won bid. See example above for data format. - */ - onBidWon: function(bidData) { - if (bidData && bidData.meta && isValidPixelUrl(bidData.meta.wp)) { - triggerPixel(`${bidData.meta.wp}${bidData.status}`); - } - } -}; - -registerBidder(spec); diff --git a/modules/vibrantmediaBidAdapter.md b/modules/vibrantmediaBidAdapter.md deleted file mode 100644 index ce5db42fdb5..00000000000 --- a/modules/vibrantmediaBidAdapter.md +++ /dev/null @@ -1,92 +0,0 @@ -## Overview - -**Module Name:** Vibrant Media Bidder Adapter - -**Module Type:** Bidder Adapter - -**Maintainer:** kormorant@vibrantmedia.com - -## Description - -Module that allows Vibrant Media to provide ad bids for banner, native and video (outstream only). - -## Test Parameters - -```javascript -var adUnits = [ - // Banner ad unit - { - code: 'test-banner', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - bids: [{ - bidder: 'vibrantmedia', - params: { - placementId: 12345 - } - }] - }, - - // Video (outstream) ad unit - { - code: 'test-video-outstream', - sizes: [[300, 250]], - mediaTypes: { - video: { - playerSize: [[300, 250]], - context: 'outstream', - minduration: 1, // Minimum ad duration, in seconds - maxduration: 60, // Maximum ad duration, in seconds - skip: 0, // 1 - true, 0 - false - skipafter: 5, // Number of seconds before the video can be skipped - playbackmethod: [2], // Auto-play without sound - protocols: [1, 2, 3] // VAST 1.0, 2.0 and 3.0 - } - }, - bids: [ - { - bidder: 'vibrantmedia', - params: { - placementId: 67890, - video: { - skippable: true, - playback_method: 'auto_play_sound_off' - } - } - } - ] - }, - - // Native ad unit - { - code: 'test-native', - mediaTypes: { - native: { - image: { - required: true, - sizes: [300, 250] - }, - title: { - required: true - }, - sponsoredBy: { - required: true - }, - clickUrl: { - required: true - }, - } - }, - bids: [{ - bidder: 'vibrantmedia', - params: { - placementId: 13579, - allowSmallerSizes: true - } - }] - } -]; -``` diff --git a/modules/vidazooBidAdapter.js b/modules/vidazooBidAdapter.js index cf252bda2dc..3fb94870d3f 100644 --- a/modules/vidazooBidAdapter.js +++ b/modules/vidazooBidAdapter.js @@ -1,4 +1,4 @@ -import { _each, deepAccess, parseSizesInput } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; @@ -24,7 +24,7 @@ export const SUPPORTED_ID_SYSTEMS = { 'pubcid': 1, 'tdid': 1, }; -const storage = getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE}); +const storage = getStorageManager(GVLID); export function createDomain(subDomain = DEFAULT_SUB_DOMAIN) { return `https://${subDomain}.cootlogix.com`; @@ -48,7 +48,7 @@ function isBidRequestValid(bid) { } function buildRequest(bid, topWindowUrl, sizes, bidderRequest) { - const { params, bidId, userId, adUnitCode, schain } = bid; + const { params, bidId, userId, adUnitCode } = bid; const { bidFloor, ext } = params; const hashUrl = hashCode(topWindowUrl); const dealId = getNextDealId(hashUrl); @@ -71,8 +71,7 @@ function buildRequest(bid, topWindowUrl, sizes, bidderRequest) { uniqueDealId: uniqueDealId, bidderVersion: BIDDER_VERSION, prebidVersion: '$prebid.version$', - res: `${screen.width}x${screen.height}`, - schain: schain + res: `${screen.width}x${screen.height}` }; appendUserIdsToRequestPayload(data, userId); @@ -95,7 +94,7 @@ function buildRequest(bid, topWindowUrl, sizes, bidderRequest) { data: data }; - _each(ext, (value, key) => { + utils._each(ext, (value, key) => { dto.data['ext.' + key] = value; }); @@ -104,13 +103,13 @@ function buildRequest(bid, topWindowUrl, sizes, bidderRequest) { function appendUserIdsToRequestPayload(payloadRef, userIds) { let key; - _each(userIds, (userId, idSystemProviderName) => { + utils._each(userIds, (userId, idSystemProviderName) => { if (SUPPORTED_ID_SYSTEMS[idSystemProviderName]) { key = `uid.${idSystemProviderName}`; switch (idSystemProviderName) { case 'digitrustid': - payloadRef[key] = deepAccess(userId, 'data.id'); + payloadRef[key] = utils.deepAccess(userId, 'data.id'); break; case 'lipb': payloadRef[key] = userId.lipbid; @@ -132,7 +131,7 @@ function buildRequests(validBidRequests, bidderRequest) { const topWindowUrl = bidderRequest.refererInfo.referer; const requests = []; validBidRequests.forEach(validBidRequest => { - const sizes = parseSizesInput(validBidRequest.sizes); + const sizes = utils.parseSizesInput(validBidRequest.sizes); const request = buildRequest(validBidRequest, topWindowUrl, sizes, bidderRequest); requests.push(request); }); diff --git a/modules/videobyteBidAdapter.js b/modules/videobyteBidAdapter.js index 6e99b5bc42a..076329d1c8b 100644 --- a/modules/videobyteBidAdapter.js +++ b/modules/videobyteBidAdapter.js @@ -1,5 +1,5 @@ -import { logMessage, logError, deepAccess, isFn, isPlainObject, isStr, isNumber, isArray, deepSetValue } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import {VIDEO} from '../src/mediaTypes.js'; const BIDDER_CODE = 'videobyte'; @@ -27,7 +27,7 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: [VIDEO], VERSION: '1.0.0', - ENDPOINT: 'https://x.videobyte.com/ortbhb', + ENDPOINT: 'https://x.videobyte.com/ortb/', /** * Determines whether or not the given bid request is valid. @@ -53,22 +53,13 @@ export const spec = { return bidRequests.map(bidRequest => { const {params} = bidRequest; let pubId = params.pubId; - const placementId = params.placementId; - const nId = params.nid; if (bidRequest.params.video && bidRequest.params.video.e2etest) { - logMessage('E2E test mode enabled'); + utils.logMessage('E2E test mode enabled'); pubId = 'e2etest' } - let baseEndpoint = spec.ENDPOINT + '?pid=' + pubId; - if (placementId) { - baseEndpoint += '&placementId=' + placementId - } - if (nId) { - baseEndpoint += '&nid=' + nId - } return { method: 'POST', - url: baseEndpoint, + url: spec.ENDPOINT + pubId, data: JSON.stringify(buildRequestData(bidRequest, bidderRequest)), } }); @@ -106,6 +97,8 @@ export const spec = { }; bidResponses.push(bidResponse) } + } else { + utils.logError('invalid server response received'); } return bidResponses; }, @@ -125,7 +118,7 @@ export const spec = { } serverResponses.forEach(resp => { - const userSync = deepAccess(resp, 'body.ext.usersync'); + const userSync = utils.deepAccess(resp, 'body.ext.usersync'); if (userSync) { let syncDetails = []; Object.keys(userSync).forEach(key => { @@ -159,8 +152,8 @@ export const spec = { function buildRequestData(bidRequest, bidderRequest) { const {params} = bidRequest; - const videoAdUnit = deepAccess(bidRequest, 'mediaTypes.video', {}); - const videoBidderParams = deepAccess(bidRequest, 'params.video', {}); + const videoAdUnit = utils.deepAccess(bidRequest, 'mediaTypes.video', {}); + const videoBidderParams = utils.deepAccess(bidRequest, 'params.video', {}); const videoParams = { ...videoAdUnit, @@ -201,7 +194,7 @@ function buildRequestData(bidRequest, bidderRequest) { size: '*' }; let floorData = bidRequest.params - if (isFn(bidRequest.getFloor)) { + if (utils.isFn(bidRequest.getFloor)) { floorData = bidRequest.getFloor(bidFloorRequest); } else { if (params.bidfloor) { @@ -233,41 +226,41 @@ function buildRequestData(bidRequest, bidderRequest) { }; // content - if (videoParams.content && isPlainObject(videoParams.content)) { + if (videoParams.content && utils.isPlainObject(videoParams.content)) { openrtbRequest.site.content = {}; - const contentStringKeys = ['id', 'title', 'series', 'season', 'genre', 'contentrating', 'language', 'url']; + const contentStringKeys = ['id', 'title', 'series', 'season', 'genre', 'contentrating', 'language']; const contentNumberkeys = ['episode', 'prodq', 'context', 'livestream', 'len']; const contentArrayKeys = ['cat']; const contentObjectKeys = ['ext']; for (const contentKey in videoBidderParams.content) { if ( - (contentStringKeys.indexOf(contentKey) > -1 && isStr(videoParams.content[contentKey])) || - (contentNumberkeys.indexOf(contentKey) > -1 && isNumber(videoParams.content[contentKey])) || - (contentObjectKeys.indexOf(contentKey) > -1 && isPlainObject(videoParams.content[contentKey])) || - (contentArrayKeys.indexOf(contentKey) > -1 && isArray(videoParams.content[contentKey]) && - videoParams.content[contentKey].every(catStr => isStr(catStr)))) { + (contentStringKeys.indexOf(contentKey) > -1 && utils.isStr(videoParams.content[contentKey])) || + (contentNumberkeys.indexOf(contentKey) > -1 && utils.isNumber(videoParams.content[contentKey])) || + (contentObjectKeys.indexOf(contentKey) > -1 && utils.isPlainObject(videoParams.content[contentKey])) || + (contentArrayKeys.indexOf(contentKey) > -1 && utils.isArray(videoParams.content[contentKey]) && + videoParams.content[contentKey].every(catStr => utils.isStr(catStr)))) { openrtbRequest.site.content[contentKey] = videoParams.content[contentKey]; } else { - logMessage('videobyte bid adapter validation error: ', contentKey, ' is either not supported is OpenRTB V2.5 or value is undefined'); + utils.logMessage('videobyte bid adapter validation error: ', contentKey, ' is either not supported is OpenRTB V2.5 or value is undefined'); } } } // adding schain object if (bidRequest.schain) { - deepSetValue(openrtbRequest, 'source.ext.schain', bidRequest.schain); + utils.deepSetValue(openrtbRequest, 'source.ext.schain', bidRequest.schain); openrtbRequest.source.ext.schain.nodes[0].rid = openrtbRequest.id; } // Attaching GDPR Consent Params if (bidderRequest.gdprConsent) { - deepSetValue(openrtbRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(openrtbRequest, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + utils.deepSetValue(openrtbRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(openrtbRequest, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); } // CCPA if (bidderRequest.uspConsent) { - deepSetValue(openrtbRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(openrtbRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); } return openrtbRequest; } @@ -278,12 +271,12 @@ function validateVideo(bidRequest) { } if (!bidRequest.params.pubId) { - logError('failed validation: pubId not declared'); + utils.logError('failed validation: publisher id not declared'); return false; } - const videoAdUnit = deepAccess(bidRequest, 'mediaTypes.video', {}); - const videoBidderParams = deepAccess(bidRequest, 'params.video', {}); + const videoAdUnit = utils.deepAccess(bidRequest, 'mediaTypes.video', {}); + const videoBidderParams = utils.deepAccess(bidRequest, 'params.video', {}); if (videoBidderParams && videoBidderParams.e2etest) { return true; @@ -295,16 +288,16 @@ function validateVideo(bidRequest) { }; if (!videoParams.context) { - logError('failed validation: context id not declared'); + utils.logError('failed validation: context id not declared'); return false; } if (videoParams.context !== 'instream') { - logError('failed validation: only context instream is supported '); + utils.logError('failed validation: only context instream is supported '); return false; } if (typeof videoParams.playerSize === 'undefined' || !Array.isArray(videoParams.playerSize) || !Array.isArray(videoParams.playerSize[0])) { - logError('failed validation: player size not declared or is not in format [[w,h]]'); + utils.logError('failed validation: player size not declared or is not in format [[w,h]]'); return false; } diff --git a/modules/videobyteBidAdapter.md b/modules/videobyteBidAdapter.md index d0037b0972a..fc2b0bce4b5 100644 --- a/modules/videobyteBidAdapter.md +++ b/modules/videobyteBidAdapter.md @@ -49,55 +49,6 @@ Module that connects to VideoByte's demand sources ] ``` -## Instream Video adUnit with placement, nid and content params -``` - var adUnits = [ - { - code: 'video1', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - mimes: ['video/mp4', 'application/javascript'], - protocols: [2,5], - api: [2], - position: 1, - delivery: [2], - minduration: 10, - maxduration: 30, - placement: 1, - playbackmethod: [1,5], - protocols: [2,5], - api: [2], - } - }, - bids: [ - { - bidder: 'videobyte', - params: { - bidfloor: 0.5, - pubId: 'e2etest', - placementId: '1234567', - nid: '1234', - video: { - content:{ - id: "uuid", - url: "https://videobyte.com/awesome-video.mp4", - title: "Awesome video", - genre: "Comedy", - language: "en", - season: "1", - series: "1", - - } - } - } - } - ] - } - ] -``` - # End To End testing mode By passing bid.params.video.e2etest = true you will be able to receive a test creative diff --git a/modules/videoreachBidAdapter.js b/modules/videoreachBidAdapter.js index 61ecd55a2ef..c307fc3e865 100644 --- a/modules/videoreachBidAdapter.js +++ b/modules/videoreachBidAdapter.js @@ -1,5 +1,5 @@ -import { getValue, getBidIdParameter } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +const utils = require('../src/utils.js'); const BIDDER_CODE = 'videoreach'; const ENDPOINT_URL = 'https://a.videoreach.com/hb/'; const GVLID = 547; @@ -17,12 +17,12 @@ export const spec = { let data = { data: validBidRequests.map(function(bid) { return { - TagId: getValue(bid.params, 'TagId'), - adUnitCode: getBidIdParameter('adUnitCode', bid), - bidId: getBidIdParameter('bidId', bid), - bidderRequestId: getBidIdParameter('bidderRequestId', bid), - auctionId: getBidIdParameter('auctionId', bid), - transactionId: getBidIdParameter('transactionId', bid) + TagId: utils.getValue(bid.params, 'TagId'), + adUnitCode: utils.getBidIdParameter('adUnitCode', bid), + bidId: utils.getBidIdParameter('bidId', bid), + bidderRequestId: utils.getBidIdParameter('bidderRequestId', bid), + auctionId: utils.getBidIdParameter('auctionId', bid), + transactionId: utils.getBidIdParameter('transactionId', bid) } }) }; diff --git a/modules/vidoomyBidAdapter.js b/modules/vidoomyBidAdapter.js index d268f7a9d64..b579de8618b 100644 --- a/modules/vidoomyBidAdapter.js +++ b/modules/vidoomyBidAdapter.js @@ -1,49 +1,31 @@ -import { logError, deepAccess, parseSizesInput } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; +import * as utils from '../src/utils.js'; import { Renderer } from '../src/Renderer.js'; import { INSTREAM, OUTSTREAM } from '../src/video.js'; const ENDPOINT = `https://d.vidoomy.com/api/rtbserver/prebid/`; const BIDDER_CODE = 'vidoomy'; const GVLID = 380; - -const COOKIE_SYNC_FALLBACK_URLS = [ - 'https://x.bidswitch.net/sync?ssp=vidoomy', - 'https://ib.adnxs.com/getuid?https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dadnxs%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D%24UID', - 'https://pixel-sync.sitescout.com/dmp/pixelSync?nid=120&redir=https%3A%2F%2Fa.vidoomy.com%2Fapi%2Frtbserver%2Fcookie%3Fi%3DCEN%26uid%3D%7BuserId%7D', - 'https://sync.1rx.io/usersync2/vidoomy?redir=https%3A%2F%2Fa.vidoomy.com%2Fapi%2Frtbserver%2Fcookie%3Fi%3DUN%26uid%3D%5BRX_UUID%5D', - 'https://rtb.openx.net/sync/prebid?gdpr={{GDPR}}&gdpr_consent={{GDPR_CONSENT}}&r=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dopenx%26uid%3D$%7BUID%7D', - 'https://ads.pubmatic.com/AdServer/js/user_sync.html?gdpr={{GDPR}}&gdpr_consent={{GDPR_CONSENT}}&us_privacy=&predirect=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D', - 'https://cm.adform.net/cookie?redirect_url=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dadf%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D%24UID', - 'https://ups.analytics.yahoo.com/ups/58531/occ?gdpr={{GDPR}}&gdpr_consent={{GDPR_CONSENT}}', - 'https://ap.lijit.com/pixel?redir=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dsovrn%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D%24UID' -]; - const isBidRequestValid = bid => { if (!bid.params) { - logError(BIDDER_CODE + ': bid.params should be non-empty'); + utils.logError(BIDDER_CODE + ': bid.params should be non-empty'); return false; } if (!+bid.params.pid) { - logError(BIDDER_CODE + ': bid.params.pid should be non-empty Number'); + utils.logError(BIDDER_CODE + ': bid.params.pid should be non-empty Number'); return false; } if (!+bid.params.id) { - logError(BIDDER_CODE + ': bid.params.id should be non-empty Number'); + utils.logError(BIDDER_CODE + ': bid.params.id should be non-empty Number'); return false; } if (bid.params && bid.params.mediaTypes && bid.params.mediaTypes.video && bid.params.mediaTypes.video.context === INSTREAM && !bid.params.mediaTypes.video.playerSize) { - logError(BIDDER_CODE + ': bid.params.mediaType.video should have a playerSize property to tell player size when is INSTREAM'); - return false; - } - - if (bid.params.bidfloor && (isNaN(bid.params.bidfloor) || bid.params.bidfloor < 0)) { - logError(BIDDER_CODE + ': bid.params.bidfloor should be a number equal or greater than zero'); + utils.logError(BIDDER_CODE + ': bid.params.mediaType.video should have a playerSize property to tell player size when is INSTREAM'); return false; } @@ -51,14 +33,14 @@ const isBidRequestValid = bid => { }; const isBidResponseValid = bid => { - if (!bid || !bid.requestId || !bid.cpm || !bid.ttl || !bid.currency) { + if (!bid.requestId || !bid.cpm || !bid.ttl || !bid.currency) { return false; } switch (bid.mediaType) { case BANNER: return Boolean(bid.width && bid.height && bid.ad); case VIDEO: - return Boolean(bid.vastUrl || bid.vastXml); + return Boolean(bid.vastUrl); default: return false; } @@ -67,53 +49,56 @@ const isBidResponseValid = bid => { const buildRequests = (validBidRequests, bidderRequest) => { const serverRequests = validBidRequests.map(bid => { let adType = BANNER; - let sizes; + let w, h; if (bid.mediaTypes && bid.mediaTypes[BANNER] && bid.mediaTypes[BANNER].sizes) { - sizes = bid.mediaTypes[BANNER].sizes; + [w, h] = bid.mediaTypes[BANNER].sizes[0]; adType = BANNER; } else if (bid.mediaTypes && bid.mediaTypes[VIDEO] && bid.mediaTypes[VIDEO].playerSize) { - sizes = bid.mediaTypes[VIDEO].playerSize; + [w, h] = bid.mediaTypes[VIDEO].playerSize; adType = VIDEO; } - const [w, h] = (parseSizesInput(sizes)[0] || '0x0').split('x'); - - const aElement = document.createElement('a'); - aElement.href = (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) || top.location.href; - const hostname = aElement.hostname - - const videoContext = deepAccess(bid, 'mediaTypes.video.context'); - const bidfloor = deepAccess(bid, `params.bidfloor`, 0); - - const queryParams = { - id: bid.params.id, - adtype: adType, - auc: bid.adUnitCode, - w, - h, - pos: parseInt(bid.params.position) || 1, - ua: navigator.userAgent, - l: navigator.language && navigator.language.indexOf('-') !== -1 ? navigator.language.split('-')[0] : '', - dt: /Mobi/.test(navigator.userAgent) ? 2 : 1, - pid: bid.params.pid, - requestId: bid.bidId, - schain: bid.schain || '', - bidfloor, - d: getDomainWithoutSubdomain(hostname), // 'vidoomy.com', - sp: encodeURIComponent(aElement.href), - usp: bidderRequest.uspConsent || '', - coppa: !!config.getConfig('coppa'), - videoContext: videoContext || '' - }; + let host = ''; + try { + host = bidderRequest.refererInfo.referer.split('#')[0].replace(/^(https\:\/\/|http\:\/\/)|(\/)$/g, '').split('/')[0]; + } catch (eBidRequest) { + try { + host = window.location.href.replace(/^(https\:\/\/|http\:\/\/)|(\/)$/g, '').split('/')[0]; + } catch (eLocationHref) { + host = window.location.href; + } + } + const hostname = host.split(':')[0]; + + const videoContext = utils.deepAccess(bid, 'mediaTypes.video.context'); + + const queryParams = []; + queryParams.push(['id', bid.params.id]); + queryParams.push(['adtype', adType]); + queryParams.push(['w', w]); + queryParams.push(['h', h]); + queryParams.push(['pos', parseInt(bid.params.position) || 1]); + queryParams.push(['ua', navigator.userAgent]); + queryParams.push(['l', navigator.language && navigator.language.indexOf('-') !== -1 ? navigator.language.split('-')[0] : '']); + queryParams.push(['dt', /Mobi/.test(navigator.userAgent) ? 2 : 1]); + queryParams.push(['pid', bid.params.pid]); + queryParams.push(['requestId', bid.bidId]); + queryParams.push(['d', hostname]); + queryParams.push(['sp', encodeURIComponent(bidderRequest.refererInfo.referer)]); if (bidderRequest.gdprConsent) { - queryParams.gdpr = bidderRequest.gdprConsent.gdprApplies; - queryParams.gdprcs = bidderRequest.gdprConsent.consentString; + queryParams.push(['gdpr', bidderRequest.gdprConsent.gdprApplies]); + queryParams.push(['gdprcs', bidderRequest.gdprConsent.consentString]); } + queryParams.push(['usp', bidderRequest.uspConsent || '']); + queryParams.push(['coppa', !!config.getConfig('coppa')]); + + const rawQueryParams = queryParams.map(qp => qp.join('=')).join('&'); + const url = `${ENDPOINT}?${rawQueryParams}`; return { method: 'GET', - url: ENDPOINT, - data: queryParams + url: url, + data: {videoContext} } }); return serverRequests; @@ -135,9 +120,8 @@ const render = (bid) => { const interpretResponse = (serverResponse, bidRequest) => { try { let responseBody = serverResponse.body; - if (!responseBody) return; if (responseBody.mediaType === 'video') { - responseBody.ad = responseBody.vastUrl || responseBody.vastXml; + responseBody.ad = responseBody.vastUrl; const videoContext = bidRequest.data.videoContext; if (videoContext === OUTSTREAM) { @@ -153,12 +137,13 @@ const interpretResponse = (serverResponse, bidRequest) => { responseBody.renderer = renderer; } catch (e) { - responseBody.ad = responseBody.vastUrl || responseBody.vastXml; - logError(BIDDER_CODE + ': error while installing renderer to show outstream ad'); + responseBody.ad = responseBody.vastUrl; + utils.logError(BIDDER_CODE + ': error while installing renderer to show outstream ad'); } } } const bid = { + vastUrl: responseBody.vastUrl, ad: responseBody.ad, renderer: responseBody.renderer, mediaType: responseBody.mediaType, @@ -187,42 +172,22 @@ const interpretResponse = (serverResponse, bidRequest) => { secondaryCatIds: responseBody.meta.secondaryCatIds } }; - if (responseBody.vastUrl) { - bid.vastUrl = responseBody.vastUrl; - } else if (responseBody.vastXml) { - bid.vastXml = responseBody.vastXml; - } const bids = []; if (isBidResponseValid(bid)) { bids.push(bid); } else { - logError(BIDDER_CODE + ': server returns invalid response'); + utils.logError(BIDDER_CODE + ': server returns invalid response'); } return bids; } catch (e) { - logError(BIDDER_CODE + ': error parsing server response to Prebid format'); + utils.logError(BIDDER_CODE + ': error parsing server response to Prebid format'); return []; } }; -function getUserSyncs (syncOptions, responses, gdprConsent, uspConsent) { - if (syncOptions.iframeEnabled || syncOptions.pixelEnabled) { - const pixelType = syncOptions.pixelEnabled ? 'image' : 'iframe'; - const urls = deepAccess(responses, '0.body.pixels') || COOKIE_SYNC_FALLBACK_URLS; - - return [].concat(urls).map(url => ({ - type: pixelType, - url: url - .replace('{{GDPR}}', gdprConsent ? (gdprConsent.gdprApplies ? '1' : '0') : '0') - .replace('{{GDPR_CONSENT}}', gdprConsent ? encodeURIComponent(gdprConsent.consentString) : '') - .replace('{{USP_CONSENT}}', uspConsent ? encodeURIComponent(uspConsent) : '') - })); - } -}; - export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER, VIDEO], @@ -230,19 +195,6 @@ export const spec = { buildRequests, interpretResponse, gvlid: GVLID, - getUserSyncs, }; registerBidder(spec); - -function getDomainWithoutSubdomain (hostname) { - const parts = hostname.split('.'); - const newParts = []; - for (let i = parts.length - 1; i >= 0; i--) { - newParts.push(parts[i]); - if (newParts.length !== 1 && parts[i].length > 3) { - break; - } - } - return newParts.reverse().join('.'); -} diff --git a/modules/vidoomyBidAdapter.md b/modules/vidoomyBidAdapter.md index d91ace5a7b9..11e0ad40dbb 100644 --- a/modules/vidoomyBidAdapter.md +++ b/modules/vidoomyBidAdapter.md @@ -26,8 +26,7 @@ var adUnits = [ bidder: 'vidoomy', params: { id: '123123', - pid: '123123', - bidfloor: 0.5 // This is optional + pid: '123123' } } ] @@ -51,8 +50,7 @@ var adUnits = [ bidder: 'vidoomy', params: { id: '123123', - pid: '123123', - bidfloor: 0.5 // This is optional + pid: '123123' } } ] diff --git a/modules/viewability.js b/modules/viewability.js deleted file mode 100644 index 39b2ee3da16..00000000000 --- a/modules/viewability.js +++ /dev/null @@ -1,177 +0,0 @@ -import {insertHtmlIntoIframe, isFn, isStr, logInfo, logWarn, triggerPixel} from '../src/utils.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import {find} from '../src/polyfill.js'; - -export const MODULE_NAME = 'viewability'; - -export function init() { - (getGlobal()).viewability = { - startMeasurement: startMeasurement, - stopMeasurement: stopMeasurement, - }; - - listenMessagesFromCreative(); -} - -const observers = {}; - -function isValid(vid, element, tracker, criteria) { - if (!element) { - logWarn(`${MODULE_NAME}: no html element provided`); - return false; - } - - let validTracker = tracker && - ((tracker.method === 'img' && isStr(tracker.value)) || - (tracker.method === 'js' && isStr(tracker.value)) || - (tracker.method === 'callback' && isFn(tracker.value))); - - if (!validTracker) { - logWarn(`${MODULE_NAME}: invalid tracker`, tracker); - return false; - } - - if (!criteria || !criteria.inViewThreshold || !criteria.timeInView) { - logWarn(`${MODULE_NAME}: missing criteria`, criteria); - return false; - } - - if (!vid || observers[vid]) { - logWarn(`${MODULE_NAME}: must provide an unregistered vid`, vid); - return false; - } - - return true; -} - -function stopObserving(observer, vid, element) { - observer.unobserve(element); - observers[vid].done = true; -} - -function fireViewabilityTracker(element, tracker) { - switch (tracker.method) { - case 'img': - triggerPixel(tracker.value, () => { - logInfo(`${MODULE_NAME}: viewability pixel fired`, tracker.value); - }); - break; - case 'js': - insertHtmlIntoIframe(``); - break; - case 'callback': - tracker.value(element); - break; - } -} - -function viewabilityCriteriaMet(observer, vid, element, tracker) { - stopObserving(observer, vid, element); - fireViewabilityTracker(element, tracker); -} - -/** - * Start measuring viewability of an element - * @typedef {{ method: string='img','js','callback', value: string|function }} ViewabilityTracker { method: 'img', value: 'http://my.tracker/123' } - * @typedef {{ inViewThreshold: number, timeInView: number }} ViewabilityCriteria { inViewThreshold: 0.5, timeInView: 1000 } - * @param {string} vid unique viewability identifier - * @param {HTMLElement} element - * @param {ViewabilityTracker} tracker - * @param {ViewabilityCriteria} criteria - */ -export function startMeasurement(vid, element, tracker, criteria) { - if (!isValid(vid, element, tracker, criteria)) { - return; - } - - const options = { - root: null, - rootMargin: '0px', - threshold: criteria.inViewThreshold, - }; - - let observer; - let viewable = false; - let stateChange = (entries) => { - viewable = entries[0].isIntersecting; - - if (viewable) { - observers[vid].timeoutId = window.setTimeout(() => { - viewabilityCriteriaMet(observer, vid, element, tracker); - }, criteria.timeInView); - } else if (observers[vid].timeoutId) { - window.clearTimeout(observers[vid].timeoutId); - } - }; - - observer = new IntersectionObserver(stateChange, options); - observers[vid] = { - observer: observer, - element: element, - timeoutId: null, - done: false, - }; - - observer.observe(element); - - logInfo(`${MODULE_NAME}: startMeasurement called with:`, arguments); -} - -/** - * Stop measuring viewability of an element - * @param {string} vid unique viewability identifier - */ -export function stopMeasurement(vid) { - if (!vid || !observers[vid]) { - logWarn(`${MODULE_NAME}: must provide a registered vid`, vid); - return; - } - - observers[vid].observer.unobserve(observers[vid].element); - if (observers[vid].timeoutId) { - window.clearTimeout(observers[vid].timeoutId); - } - - // allow the observer under this vid to be created again - if (!observers[vid].done) { - delete observers[vid]; - } -} - -function listenMessagesFromCreative() { - window.addEventListener('message', receiveMessage, false); -} - -/** - * Recieve messages from creatives - * @param {MessageEvent} evt - */ -export function receiveMessage(evt) { - var key = evt.message ? 'message' : 'data'; - var data = {}; - try { - data = JSON.parse(evt[key]); - } catch (e) { - return; - } - - if (!data || data.message !== 'Prebid Viewability') { - return; - } - - switch (data.action) { - case 'startMeasurement': - let element = data.elementId && document.getElementById(data.elementId); - if (!element) { - element = find(document.getElementsByTagName('IFRAME'), iframe => (iframe.contentWindow || iframe.contentDocument.defaultView) == evt.source); - } - - startMeasurement(data.vid, element, data.tracker, data.criteria); - break; - case 'stopMeasurement': - stopMeasurement(data.vid); - break; - } -} - -init(); diff --git a/modules/viewability.md b/modules/viewability.md deleted file mode 100644 index df93b5c40db..00000000000 --- a/modules/viewability.md +++ /dev/null @@ -1,87 +0,0 @@ -# Overview - -Module Name: Viewability - -Purpose: Track when a given HTML element becomes viewable - -Maintainer: atrajkovic@magnite.com - -# Configuration - -Module does not need any configuration, as long as you include it in your PBJS bundle. -Viewability module has only two functions `startMeasurement` and `stopMeasurement` which can be used to enable more complex viewability measurements. Since it allows tracking from within creative (possibly inside a safe frame) this module registers a message listener, for messages with a format that is described bellow. - -## `startMeasurement` - -| startMeasurement Arg Object | Scope | Type | Description | Example | -| --------------------- | -------- | ------------ | -------------------------------------------------------------------------------- | --------- | -| vid | Required | String | Unique viewability identifier, used to reference particular observer | `"ae0f9"` | -| element | Required | HTMLElement | Reference to an HTML element that needs to be tracked | `document.getElementById('test_div')` | -| tracker | Required | ViewabilityTracker | How viewaility event is communicated back to the parties of interest | `{ method: 'img', value: 'http://my.tracker/123' }` | -| criteria | Required | ViewabilityCriteria| Defines custom viewability criteria using the threshold and duration provided | `{ inViewThreshold: 0.5, timeInView: 1000 }` | - -| ViewabilityTracker | Scope | Type | Description | Example | -| --------------------- | -------- | ------------ | -------------------------------------------------------------------------------- | --------- | -| method | Required | String | Type of method for Tracker | `'img' OR 'js' OR 'callback'` | -| value | Required | String | URL string for 'img' and 'js' Trackers, or a function for 'callback' Tracker | `'http://my.tracker/123'` | - -| ViewabilityCriteria | Scope | Type | Description | Example | -| --------------------- | -------- | ------------ | -------------------------------------------------------------------------------- | --------- | -| inViewThreshold | Required | Number | Represents a percentage threshold for the Element to be registered as in view | `0.5` | -| timeInView | Required | Number | Number of milliseconds that a given element needs to be in view continuously, above the threshold | `1000` | - -## Please Note: -- `vid` allows for multiple trackers, with different criteria to be registered for a given HTML element, independently. It's not autogenerated by `startMeasurement()`, it needs to be provided by the caller so that it doesn't have to be posted back to the source iframe (in case viewability is started from within the creative). -- In case of 'callback' method, HTML element is being passed back to the callback function. -- When a tracker needs to be started, without direct access to pbjs, postMessage mechanism can be used to invoke `startMeasurement`, with a following payload: `vid`, `tracker` and `criteria` as described above, but also with `message: 'Prebid Viewability'` and `action: 'startMeasurement'`. Optionally payload can provide `elementId`, if available at that time (for ad servers where name of the iframe is known, or adservers that render outside an iframe). If `elementId` is not provided, viewability module will try to find the iframe that corresponds to the message source. - - -## `stopMeasurement` - -| stopMeasurement Arg Object | Scope | Type | Description | Example | -| --------------------- | -------- | ------------ | -------------------------------------------------------------------------------- | --------- | -| vid | Required | String | Unique viewability identifier, referencing an already started viewability tracker. | `"ae0f9"` | - -## Please Note: -- When a tracker needs to be stopped, without direct access to pbjs, postMessage mechanism can be used here as well. To invoke `stopMeasurement`, you provide the payload with `vid`, `message: 'Prebid Viewability'` and `action: 'stopMeasurement`. Check the example bellow. - -# Examples - -## Example of starting a viewability measurement, when you have direct access to pbjs -``` -pbjs.viewability.startMeasurement( - 'ae0f9', - document.getElementById('test_div'), - { method: 'img', value: 'http://my.tracker/123' }, - { inViewThreshold: 0.5, timeInView: 1000 } -); -``` - -## Example of starting a viewability measurement from within a rendered creative -``` -let viewabilityRecord = { - vid: 'ae0f9', - tracker: { method: 'img', value: 'http://my.tracker/123'}, - criteria: { inViewThreshold: 0.5, timeInView: 1000 }, - message: 'Prebid Viewability', - action: 'startMeasurement' -} - -window.parent.postMessage(JSON.stringify(viewabilityRecord), '*'); -``` - -## Example of stopping the viewability measurement, when you have direct access to pbjs -``` -pbjs.viewability.stopMeasurement('ae0f9'); -``` - -## Example of stopping the viewability measurement from within a rendered creative -``` -let viewabilityRecord = { - vid: 'ae0f9', - message: 'Prebid Viewability', - action: 'stopMeasurement' -} - -window.parent.postMessage(JSON.stringify(viewabilityRecord), '*'); -``` diff --git a/modules/viewdeosDXBidAdapter.js b/modules/viewdeosDXBidAdapter.js index 9e0cb91af9b..212759642f5 100644 --- a/modules/viewdeosDXBidAdapter.js +++ b/modules/viewdeosDXBidAdapter.js @@ -1,8 +1,8 @@ -import {deepAccess, flatten, isArray, logError, parseSizesInput} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import {VIDEO, BANNER} from '../src/mediaTypes.js'; import {Renderer} from '../src/Renderer.js'; -import {findIndex} from '../src/polyfill.js'; +import findIndex from 'core-js-pure/features/array/find-index.js'; const URL = 'https://ghb.sync.viewdeos.com/auction/'; const OUTSTREAM_SRC = 'https://player.sync.viewdeos.com/outstream-unit/2.01/outstream.min.js'; @@ -16,7 +16,7 @@ export const spec = { gvlid: 924, supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid: function (bid) { - return !!deepAccess(bid, 'params.aid'); + return !!utils.deepAccess(bid, 'params.aid'); }, getUserSyncs: function (syncOptions, serverResponses) { const syncs = []; @@ -43,9 +43,9 @@ export const spec = { } if (syncOptions.pixelEnabled || syncOptions.iframeEnabled) { - isArray(serverResponses) && serverResponses.forEach((response) => { + utils.isArray(serverResponses) && serverResponses.forEach((response) => { if (response.body) { - if (isArray(response.body)) { + if (utils.isArray(response.body)) { response.body.forEach(b => { addSyncs(b); }) @@ -81,12 +81,12 @@ export const spec = { serverResponse = serverResponse.body; let bids = []; - if (!isArray(serverResponse)) { + if (!utils.isArray(serverResponse)) { return parseRTBResponse(serverResponse, bidderRequest); } serverResponse.forEach(serverBidResponse => { - bids = flatten(bids, parseRTBResponse(serverBidResponse, bidderRequest)); + bids = utils.flatten(bids, parseRTBResponse(serverBidResponse, bidderRequest)); }); return bids; @@ -94,7 +94,7 @@ export const spec = { }; function parseRTBResponse(serverResponse, bidderRequest) { - const isInvalidValidResp = !serverResponse || !isArray(serverResponse.bids); + const isInvalidValidResp = !serverResponse || !utils.isArray(serverResponse.bids); const bids = []; @@ -102,7 +102,7 @@ function parseRTBResponse(serverResponse, bidderRequest) { const extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; const errorMessage = `in response for ${bidderRequest.bidderCode} adapter ${extMessage}`; - logError(errorMessage); + utils.logError(errorMessage); return bids; } @@ -125,15 +125,15 @@ function parseRTBResponse(serverResponse, bidderRequest) { function bidToTag(bidRequests, bidderRequest) { const tag = { - domain: deepAccess(bidderRequest, 'refererInfo.referer') + domain: utils.deepAccess(bidderRequest, 'refererInfo.referer') }; - if (deepAccess(bidderRequest, 'gdprConsent.gdprApplies')) { + if (utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies')) { tag.gdpr = 1; - tag.gdpr_consent = deepAccess(bidderRequest, 'gdprConsent.consentString'); + tag.gdpr_consent = utils.deepAccess(bidderRequest, 'gdprConsent.consentString'); } - if (deepAccess(bidderRequest, 'bidderRequest.uspConsent')) { + if (utils.deepAccess(bidderRequest, 'bidderRequest.uspConsent')) { tag.us_privacy = bidderRequest.uspConsent; } @@ -151,14 +151,14 @@ function bidToTag(bidRequests, bidderRequest) { * @returns {object} */ function prepareRTBRequestParams(_index, bid) { - const mediaType = deepAccess(bid, 'mediaTypes.video') ? VIDEO : DISPLAY; + const mediaType = utils.deepAccess(bid, 'mediaTypes.video') ? VIDEO : DISPLAY; const index = !_index ? '' : `${_index + 1}`; - const sizes = bid.sizes ? bid.sizes : (mediaType === VIDEO ? deepAccess(bid, 'mediaTypes.video.playerSize') : deepAccess(bid, 'mediaTypes.banner.sizes')); + const sizes = bid.sizes ? bid.sizes : (mediaType === VIDEO ? utils.deepAccess(bid, 'mediaTypes.video.playerSize') : utils.deepAccess(bid, 'mediaTypes.banner.sizes')); return { ['callbackId' + index]: bid.bidId, ['aid' + index]: bid.params.aid, ['ad_type' + index]: mediaType, - ['sizes' + index]: parseSizesInput(sizes).join() + ['sizes' + index]: utils.parseSizesInput(sizes).join() }; } @@ -168,8 +168,8 @@ function prepareRTBRequestParams(_index, bid) { * @returns {object} */ function getMediaType(bidderRequest) { - const videoMediaType = deepAccess(bidderRequest, 'mediaTypes.video'); - const context = deepAccess(bidderRequest, 'mediaTypes.video.context'); + const videoMediaType = utils.deepAccess(bidderRequest, 'mediaTypes.video'); + const context = utils.deepAccess(bidderRequest, 'mediaTypes.video.context'); return !videoMediaType ? DISPLAY : context === OUTSTREAM ? OUTSTREAM : VIDEO; } diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 696d54e4b52..535beb8af3c 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -1,22 +1,21 @@ -import { triggerPixel, parseSizesInput, deepAccess, logError, getGptSlotInfoForAdUnitCode } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { INSTREAM as VIDEO_INSTREAM } from '../src/video.js'; +const { parseSizesInput, getKeys, logError, deepAccess } = utils; const BIDDER_CODE = 'visx'; const GVLID = 154; const BASE_URL = 'https://t.visx.net'; -const DEBUG_URL = 'https://t-stage.visx.net'; -const ENDPOINT_PATH = '/hb_post'; +const ENDPOINT_URL = BASE_URL + '/hb'; const TIME_TO_LIVE = 360; const DEFAULT_CUR = 'EUR'; -const ADAPTER_SYNC_PATH = '/push_sync'; -const TRACK_TIMEOUT_PATH = '/track/bid_timeout'; +const ADAPTER_SYNC_URL = BASE_URL + '/push_sync'; +const TRACK_TIMEOUT_URL = BASE_URL + '/track/bid_timeout'; const LOG_ERROR_MESS = { noAuid: 'Bid from response has no auid parameter - ', noAdm: 'Bid from response has no adm parameter - ', noBid: 'Array of bid objects is empty', - noImpId: 'Bid from response has no impid parameter - ', noPlacementCode: 'Can\'t find in requested bids the bid with auid - ', emptyUids: 'Uids should not be empty', emptySeatbid: 'Seatbid array from response has an empty item', @@ -29,6 +28,7 @@ const LOG_ERROR_MESS = { videoMissing: 'Bid request videoType property is missing - ' }; const currencyWhiteList = ['EUR', 'USD', 'GBP', 'PLN']; +const RE_EMPTY_OR_ONLY_COMMAS = /^,*$/; export const spec = { code: BIDDER_CODE, gvlid: GVLID, @@ -42,58 +42,94 @@ export const spec = { } } } - return !!bid.params.uid && !isNaN(parseInt(bid.params.uid)); + return !!bid.params.uid; }, buildRequests: function(validBidRequests, bidderRequest) { const auids = []; const bidsMap = {}; + const slotsMapByUid = {}; + const sizeMap = {}; const bids = validBidRequests || []; const currency = config.getConfig(`currency.bidderCurrencyDefault.${BIDDER_CODE}`) || config.getConfig('currency.adServerCurrency') || DEFAULT_CUR; - let reqId; let payloadSchain; let payloadUserId; - let payloadUserEids; - let timeout; + const videoTypes = _initVideoTypes(bids); if (currencyWhiteList.indexOf(currency) === -1) { logError(LOG_ERROR_MESS.notAllowedCurrency + currency); return; } - const imp = []; - bids.forEach(bid => { reqId = bid.bidderRequestId; - - const impObj = buildImpObject(bid); - if (impObj) { - imp.push(impObj); - bidsMap[bid.bidId] = bid; - } - - const { params: { uid }, schain, userId, userIdAsEids } = bid; - + const {params: {uid}, adUnitCode, schain, userId} = bid; + auids.push(uid); if (!payloadSchain && schain) { payloadSchain = schain; } - if (!payloadUserEids && userIdAsEids) { - payloadUserEids = userIdAsEids; - } - if (!payloadUserId && userId) { payloadUserId = userId; } - auids.push(uid); + const sizesId = parseSizesInput(bid.sizes); + + if (!slotsMapByUid[uid]) { + slotsMapByUid[uid] = {}; + } + const slotsMap = slotsMapByUid[uid]; + if (!slotsMap[adUnitCode]) { + slotsMap[adUnitCode] = {adUnitCode, bids: [bid], parents: []}; + } else { + slotsMap[adUnitCode].bids.push(bid); + } + const slot = slotsMap[adUnitCode]; + + sizesId.forEach((sizeId) => { + sizeMap[sizeId] = true; + if (!bidsMap[uid]) { + bidsMap[uid] = {}; + } + + if (!bidsMap[uid][sizeId]) { + bidsMap[uid][sizeId] = [slot]; + } else { + bidsMap[uid][sizeId].push(slot); + } + slot.parents.push({parent: bidsMap[uid], key: sizeId, uid}); + }); }); - const payload = {}; + const payload = { + pt: 'net', + auids: auids.join(','), + sizes: getKeys(sizeMap).join(','), + r: reqId, + cur: currency, + wrapperType: 'Prebid_js', + wrapperVersion: '$prebid.version$', + ...videoTypes + }; + + if (payloadSchain) { + payload.schain = JSON.stringify(payloadSchain); + } + + if (payloadUserId) { + if (payloadUserId.tdid) { + payload.tdid = payloadUserId.tdid; + } + if (payloadUserId.id5id && payloadUserId.id5id.uid) { + payload.id5 = payloadUserId.id5id.uid; + } + if (payloadUserId.digitrustid && payloadUserId.digitrustid.data && payloadUserId.digitrustid.data.id) { + payload.dtid = payloadUserId.digitrustid.data.id; + } + } if (bidderRequest) { - timeout = bidderRequest.timeout; if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { payload.u = bidderRequest.refererInfo.referer; } @@ -107,50 +143,19 @@ export const spec = { } } - const bidderTimeout = Number(config.getConfig('bidderTimeout')) || timeout; - const tmax = timeout ? Math.min(bidderTimeout, timeout) : bidderTimeout; - const source = { - ext: { - wrapperType: 'Prebid_js', - wrapperVersion: '$prebid.version$', - ...(payloadSchain && { schain: payloadSchain }) - } - }; - const user = { - ext: { - ...(payloadUserEids && { eids: payloadUserEids }), - ...(payload.gdpr_consent && { consent: payload.gdpr_consent }) - } - }; - const regs = ('gdpr_applies' in payload) && { - ext: { - gdpr: payload.gdpr_applies - } - }; - - const request = { - id: reqId, - imp, - tmax, - cur: [currency], - source, - site: { page: payload.u }, - ...(Object.keys(user.ext).length && { user }), - ...(regs && { regs }) - }; - return { - method: 'POST', - url: buildUrl(ENDPOINT_PATH) + '?auids=' + encodeURIComponent(auids.join(',')), - data: request, - bidsMap + method: 'GET', + url: ENDPOINT_URL, + data: payload, + bidsMap: bidsMap, }; }, interpretResponse: function(serverResponse, bidRequest) { serverResponse = serverResponse && serverResponse.body; const bidResponses = []; + const bidsWithoutSizeMatching = []; const bidsMap = bidRequest.bidsMap; - const currency = bidRequest.data.cur[0]; + const currency = bidRequest.data.cur; let errorMessage; @@ -161,116 +166,50 @@ export const spec = { if (!errorMessage && serverResponse.seatbid) { serverResponse.seatbid.forEach(respItem => { - _addBidResponse(_getBidFromResponse(respItem), bidsMap, currency, bidResponses); + _addBidResponse(_getBidFromResponse(respItem), bidsMap, currency, bidResponses, bidsWithoutSizeMatching); + }); + bidsWithoutSizeMatching.forEach(serverBid => { + _addBidResponse(serverBid, bidsMap, currency, bidResponses); }); } if (errorMessage) logError(errorMessage); return bidResponses; }, getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { - var query = []; - if (gdprConsent) { - if (gdprConsent.consentString) { - query.push('gdpr_consent=' + encodeURIComponent(gdprConsent.consentString)); + if (syncOptions.pixelEnabled) { + var query = []; + if (gdprConsent) { + if (gdprConsent.consentString) { + query.push('gdpr_consent=' + encodeURIComponent(gdprConsent.consentString)); + } + query.push('gdpr_applies=' + encodeURIComponent( + (typeof gdprConsent.gdprApplies === 'boolean') + ? Number(gdprConsent.gdprApplies) : 1)); } - query.push('gdpr_applies=' + encodeURIComponent( - (typeof gdprConsent.gdprApplies === 'boolean') - ? Number(gdprConsent.gdprApplies) : 1)); - } - if (syncOptions.iframeEnabled) { - return [{ - type: 'iframe', - url: buildUrl(ADAPTER_SYNC_PATH) + '?iframe=1' + (query.length ? '&' + query.join('&') : '') - }]; - } else if (syncOptions.pixelEnabled) { return [{ type: 'image', - url: buildUrl(ADAPTER_SYNC_PATH) + (query.length ? '?' + query.join('&') : '') + url: ADAPTER_SYNC_URL + (query.length ? '?' + query.join('&') : '') }]; } }, onSetTargeting: function(bid) { // Call '/track/pending' with the corresponding bid.requestId if (bid.ext && bid.ext.events && bid.ext.events.pending) { - triggerPixel(bid.ext.events.pending); + utils.triggerPixel(bid.ext.events.pending); } }, onBidWon: function(bid) { // Call '/track/win' with the corresponding bid.requestId if (bid.ext && bid.ext.events && bid.ext.events.win) { - triggerPixel(bid.ext.events.win); + utils.triggerPixel(bid.ext.events.win); } }, onTimeout: function(timeoutData) { // Call '/track/bid_timeout' with timeout data - timeoutData.forEach(({ params }) => { - if (params) { - params.forEach((item) => { - if (item && item.uid) { - item.uid = parseInt(item.uid); - } - }); - } - }); - triggerPixel(buildUrl(TRACK_TIMEOUT_PATH) + '//' + JSON.stringify(timeoutData)); + utils.triggerPixel(TRACK_TIMEOUT_URL + '?data=' + JSON.stringify(timeoutData)); } }; -function buildUrl(path) { - return (config.getConfig('devMode') ? DEBUG_URL : BASE_URL) + path; -} - -function makeBanner(bannerParams) { - const bannerSizes = bannerParams && bannerParams.sizes; - if (bannerSizes) { - const sizes = parseSizesInput(bannerSizes); - if (sizes.length) { - const format = sizes.map(size => { - const [ width, height ] = size.split('x'); - const w = parseInt(width, 10); - const h = parseInt(height, 10); - return { w, h }; - }); - - return { format }; - } - } -} - -function makeVideo(videoParams = {}) { - const video = Object.keys(videoParams).filter((param) => param !== 'context' && param !== 'playerSize') - .reduce((result, param) => { - result[param] = videoParams[param]; - return result; - }, { w: deepAccess(videoParams, 'playerSize.0.0'), h: deepAccess(videoParams, 'playerSize.0.1') }); - - if (video.w && video.h) { - return video; - } -} - -function buildImpObject(bid) { - const { params: { uid }, bidId, mediaTypes, sizes, adUnitCode } = bid; - const video = mediaTypes && _isVideoBid(bid) && _isValidVideoBid(bid) && makeVideo(mediaTypes.video); - const banner = makeBanner((mediaTypes && mediaTypes.banner) || (!video && { sizes })); - const impObject = { - id: bidId, - ...(banner && { banner }), - ...(video && { video }), - ext: { - bidder: { uid: parseInt(uid) }, - } - }; - - if (impObject.banner) { - impObject.ext.bidder.adslotExists = _isAdSlotExists(adUnitCode); - } - - if (impObject.ext.bidder.uid && (impObject.banner || impObject.video)) { - return impObject; - } -} - function _getBidFromResponse(respItem) { if (!respItem) { logError(LOG_ERROR_MESS.emptySeatbid); @@ -282,52 +221,69 @@ function _getBidFromResponse(respItem) { return respItem && respItem.bid && respItem.bid[0]; } -function _addBidResponse(serverBid, bidsMap, currency, bidResponses) { +function _addBidResponse(serverBid, bidsMap, currency, bidResponses, bidsWithoutSizeMatching) { if (!serverBid) return; let errorMessage; if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); - if (!serverBid.impid) errorMessage = LOG_ERROR_MESS.noImpId + JSON.stringify(serverBid); if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); else { const reqCurrency = currency || DEFAULT_CUR; - const bid = bidsMap[serverBid.impid]; - if (bid) { + const awaitingBids = bidsMap[serverBid.auid]; + if (awaitingBids) { if (serverBid.cur && serverBid.cur !== reqCurrency) { errorMessage = LOG_ERROR_MESS.currencyMismatch + reqCurrency + ' - ' + serverBid.cur; } else { - const bidResponse = { - requestId: bid.bidId, - cpm: serverBid.price, - width: serverBid.w, - height: serverBid.h, - creativeId: serverBid.auid, - currency: reqCurrency, - netRevenue: true, - ttl: TIME_TO_LIVE, - dealId: serverBid.dealid, - meta: { - advertiserDomains: serverBid.advertiserDomains ? serverBid.advertiserDomains : [], - mediaType: serverBid.mediaType - }, - }; - - if (serverBid.ext && serverBid.ext.prebid) { - bidResponse.ext = serverBid.ext.prebid; - } + const sizeId = bidsWithoutSizeMatching ? `${serverBid.w}x${serverBid.h}` : Object.keys(awaitingBids)[0]; + if (awaitingBids[sizeId]) { + const slot = awaitingBids[sizeId][0]; + + const bid = slot.bids.shift(); + const bidResponse = { + requestId: bid.bidId, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, + currency: reqCurrency, + netRevenue: true, + ttl: TIME_TO_LIVE, + dealId: serverBid.dealid, + meta: { + advertiserDomains: serverBid.advertiserDomains ? serverBid.advertiserDomains : [], + mediaType: serverBid.mediaType + }, + }; + + if (serverBid.ext && serverBid.ext.prebid) { + bidResponse.ext = serverBid.ext.prebid; + } - const visxTargeting = deepAccess(serverBid, 'ext.prebid.targeting'); - if (visxTargeting) { - bidResponse.adserverTargeting = visxTargeting; - } + if (!_isVideoInstreamBid(bid)) { + bidResponse.ad = serverBid.adm; + } else { + bidResponse.vastXml = serverBid.adm; + bidResponse.mediaType = 'video'; + } - if (!_isVideoInstreamBid(bid)) { - bidResponse.ad = serverBid.adm; + bidResponses.push(bidResponse); + + if (!slot.bids.length) { + slot.parents.forEach(({parent, key, uid}) => { + const index = parent[key].indexOf(slot); + if (index > -1) { + parent[key].splice(index, 1); + } + if (!parent[key].length) { + delete parent[key]; + if (!getKeys(parent).length) { + delete bidsMap[uid]; + } + } + }); + } } else { - bidResponse.vastXml = serverBid.adm; - bidResponse.mediaType = 'video'; + bidsWithoutSizeMatching && bidsWithoutSizeMatching.push(serverBid); } - - bidResponses.push(bidResponse); } } else { errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; @@ -365,20 +321,89 @@ function _isValidVideoBid(bid, logErrors = false) { } result = false; } + if (!videoMediaType.mimes) { + if (logErrors) { + logError(LOG_ERROR_MESS.videoMissing + 'mimes'); + } + result = false; + } + if (!videoMediaType.protocols) { + if (logErrors) { + logError(LOG_ERROR_MESS.videoMissing + 'protocols'); + } + result = false; + } return result; } -function _isAdSlotExists(adUnitCode) { - if (document.getElementById(adUnitCode)) { - return true; +function _initVideoTypes(bids) { + const result = {}; + let _playerSize = []; + let _protocols = []; + let _api = []; + let _mimes = []; + let _minduration = []; + let _maxduration = []; + let _skip = []; + if (bids && bids.length) { + bids.forEach(function (bid) { + const mediaTypes = deepAccess(bid, 'mediaTypes.video', {}); + let bidPlayerSize = ''; + let bidProtocols = ''; + let bidApi = ''; + let bidMimes = ''; + let bidMinduration = null; + let bidMaxduration = null; + let bidSkip = null; + if (_isVideoBid(bid) && _isValidVideoBid(bid)) { + bidPlayerSize = parseSizesInput(deepAccess(mediaTypes, 'playerSize', [])).join('|'); + bidProtocols = deepAccess(mediaTypes, 'protocols', []).join('|'); + bidApi = deepAccess(mediaTypes, 'api', []).join('|'); + bidMimes = deepAccess(mediaTypes, 'mimes', []).join('|'); + bidMinduration = deepAccess(mediaTypes, 'minduration', null); + bidMaxduration = deepAccess(mediaTypes, 'maxduration', null); + bidSkip = deepAccess(mediaTypes, 'skip', null); + } + _playerSize.push(bidPlayerSize); + _protocols.push(bidProtocols); + _api.push(bidApi); + _mimes.push(bidMimes); + _minduration.push(bidMinduration); + _maxduration.push(bidMaxduration); + _skip.push(bidSkip); + }); } - - const gptAdSlot = getGptSlotInfoForAdUnitCode(adUnitCode); - if (gptAdSlot && gptAdSlot.divId && document.getElementById(gptAdSlot.divId)) { - return true; + _playerSize = _playerSize.join(','); + _protocols = _protocols.join(','); + _api = _api.join(','); + _mimes = _mimes.join(','); + _minduration = _minduration.join(','); + _maxduration = _maxduration.join(','); + _skip = _skip.join(','); + + if (!RE_EMPTY_OR_ONLY_COMMAS.test(_playerSize)) { + result.playerSize = _playerSize; + } + if (!RE_EMPTY_OR_ONLY_COMMAS.test(_protocols)) { + result.protocols = _protocols; + } + if (!RE_EMPTY_OR_ONLY_COMMAS.test(_api)) { + result.api = _api; + } + if (!RE_EMPTY_OR_ONLY_COMMAS.test(_mimes)) { + result.mimes = _mimes; + } + if (!RE_EMPTY_OR_ONLY_COMMAS.test(_minduration)) { + result.minduration = _minduration; + } + if (!RE_EMPTY_OR_ONLY_COMMAS.test(_maxduration)) { + result.maxduration = _maxduration; + } + if (!RE_EMPTY_OR_ONLY_COMMAS.test(_skip)) { + result.skip = _skip; } - return false; + return result; } registerBidder(spec); diff --git a/modules/visxBidAdapter.md b/modules/visxBidAdapter.md index 34ebe9bb937..9578f7cc4a7 100644 --- a/modules/visxBidAdapter.md +++ b/modules/visxBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: YOC VIS.X Bidder Adapter Module Type: Bidder Adapter -Maintainer: supply.partners@yoc.com +Maintainer: service@yoc.com ``` # Description @@ -47,14 +47,16 @@ var adUnits = [ } ] }, - // In-stream video adUnit + // YOC In-stream adUnit { code: 'instream-test-div', mediaTypes: { video: { context: 'instream', - playerSize: [400, 300] - } + playerSize: [400, 300], + mimes: ['video/mp4'], + protocols: [3, 6] + }, }, bids: [ { diff --git a/modules/voxBidAdapter.js b/modules/voxBidAdapter.js index 25dbbda90cf..ba469c3c7ed 100644 --- a/modules/voxBidAdapter.js +++ b/modules/voxBidAdapter.js @@ -1,7 +1,7 @@ -import {_map, deepAccess, isArray, logWarn} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {find} from '../src/polyfill.js'; +import * as utils from '../src/utils.js' +import { registerBidder } from '../src/adapters/bidderFactory.js' +import {BANNER, VIDEO} from '../src/mediaTypes.js' +import find from 'core-js-pure/features/array/find.js'; import {auctionManager} from '../src/auctionManager.js'; import {Renderer} from '../src/Renderer.js'; @@ -11,7 +11,7 @@ const VIDEO_RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVi const TTL = 60; function buildBidRequests(validBidRequests) { - return _map(validBidRequests, function(validBidRequest) { + return utils._map(validBidRequests, function(validBidRequest) { const params = validBidRequest.params; const bidRequest = { bidId: validBidRequest.bidId, @@ -53,7 +53,7 @@ const createRenderer = (bid) => { try { renderer.setRender(outstreamRender); } catch (err) { - logWarn('Prebid Error calling setRender on renderer', err); + utils.logWarn('Prebid Error calling setRender on renderer', err); } return renderer; @@ -111,8 +111,8 @@ function hasVideoMandatoryParams(mediaTypes) { const isHasVideoContext = !!mediaTypes.video && (mediaTypes.video.context === 'instream' || mediaTypes.video.context === 'outstream'); const isPlayerSize = - !!deepAccess(mediaTypes, 'video.playerSize') && - isArray(deepAccess(mediaTypes, 'video.playerSize')); + !!utils.deepAccess(mediaTypes, 'video.playerSize') && + utils.isArray(utils.deepAccess(mediaTypes, 'video.playerSize')); return isHasVideoContext && isPlayerSize; } @@ -231,8 +231,8 @@ export const spec = { let bidRequests = JSON.parse(bidRequest.data).bidRequests; const serverBody = serverResponse.body; - if (serverBody && serverBody.bids && isArray(serverBody.bids)) { - return _map(serverBody.bids, function(bid) { + if (serverBody && serverBody.bids && utils.isArray(serverBody.bids)) { + return utils._map(serverBody.bids, function(bid) { let rawBid = find(bidRequests, function (item) { return item.bidId === bid.bidId; }); diff --git a/modules/vrtcalBidAdapter.js b/modules/vrtcalBidAdapter.js index d08ef52106e..d23a05e23ca 100644 --- a/modules/vrtcalBidAdapter.js +++ b/modules/vrtcalBidAdapter.js @@ -1,7 +1,6 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import {ajax} from '../src/ajax.js'; -import {isFn, isPlainObject} from '../src/utils.js'; export const spec = { code: 'vrtcal', @@ -11,17 +10,8 @@ export const spec = { }, buildRequests: function (bidRequests) { const requests = bidRequests.map(function (bid) { - let floor = 0; - - if (isFn(bid.getFloor)) { - const floorInfo = bid.getFloor({ currency: 'USD', mediaType: 'banner', size: bid.sizes.map(([w, h]) => ({w, h})) }); - - if (isPlainObject(floorInfo) && floorInfo.currency === 'USD' && !isNaN(parseFloat(floorInfo.floor))) { - floor = Math.max(floor, parseFloat(floorInfo.floor)); - } - } - const params = { + prebidJS: 1, prebidAdUnitCode: bid.adUnitCode, id: bid.bidId, @@ -29,7 +19,7 @@ export const spec = { id: '1', banner: { }, - bidfloor: floor + bidfloor: 0.75 }], site: { id: 'VRTCAL_FILLED', diff --git a/modules/vuukleBidAdapter.js b/modules/vuukleBidAdapter.js index ddf96b3e940..7a83bf4e331 100644 --- a/modules/vuukleBidAdapter.js +++ b/modules/vuukleBidAdapter.js @@ -1,4 +1,4 @@ -import { parseSizesInput } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'vuukle'; @@ -14,7 +14,7 @@ export const spec = { buildRequests: function(bidRequests) { const requests = bidRequests.map(function (bid) { - const parseSized = parseSizesInput(bid.sizes); + const parseSized = utils.parseSizesInput(bid.sizes); const arrSize = parseSized[0].split('x'); const params = { url: encodeURIComponent(window.location.href), diff --git a/modules/waardexBidAdapter.js b/modules/waardexBidAdapter.js index 1a97e3bd351..bc60e151e39 100644 --- a/modules/waardexBidAdapter.js +++ b/modules/waardexBidAdapter.js @@ -1,46 +1,46 @@ -import {deepAccess, getBidIdParameter, isArray, logError} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; -import {find} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import find from 'core-js-pure/features/array/find.js'; const ENDPOINT = `https://hb.justbidit.xyz:8843/prebid`; const BIDDER_CODE = 'waardex'; const isBidRequestValid = bid => { if (!bid.bidId) { - logError(BIDDER_CODE + ': bid.bidId should be non-empty'); + utils.logError(BIDDER_CODE + ': bid.bidId should be non-empty'); return false; } if (!bid.params) { - logError(BIDDER_CODE + ': bid.params should be non-empty'); + utils.logError(BIDDER_CODE + ': bid.params should be non-empty'); return false; } if (!+bid.params.zoneId) { - logError(BIDDER_CODE + ': bid.params.zoneId should be non-empty Number'); + utils.logError(BIDDER_CODE + ': bid.params.zoneId should be non-empty Number'); return false; } if (bid.mediaTypes && bid.mediaTypes.video) { if (!bid.mediaTypes.video.playerSize) { - logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be non-empty'); + utils.logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be non-empty'); return false; } - if (!isArray(bid.mediaTypes.video.playerSize)) { - logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be an Array'); + if (!utils.isArray(bid.mediaTypes.video.playerSize)) { + utils.logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be an Array'); return false; } if (!bid.mediaTypes.video.playerSize[0]) { - logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be non-empty'); + utils.logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be non-empty'); return false; } - if (!isArray(bid.mediaTypes.video.playerSize[0])) { - logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be non-empty Array'); + if (!utils.isArray(bid.mediaTypes.video.playerSize[0])) { + utils.logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be non-empty Array'); return false; } } @@ -139,22 +139,22 @@ const transformSizes = requestSizes => { const createVideoObject = (videoMediaTypes, videoParams) => { return { - w: deepAccess(videoMediaTypes, 'playerSize')[0][0], - h: deepAccess(videoMediaTypes, 'playerSize')[0][1], - mimes: getBidIdParameter('mimes', videoParams) || ['application/javascript', 'video/mp4', 'video/webm'], - minduration: getBidIdParameter('minduration', videoParams) || 0, - maxduration: getBidIdParameter('maxduration', videoParams) || 500, - protocols: getBidIdParameter('protocols', videoParams) || [2, 3, 5, 6], - startdelay: getBidIdParameter('startdelay', videoParams) || 0, - placement: getBidIdParameter('placement', videoParams) || videoMediaTypes.context === 'outstream' ? 3 : 1, - skip: getBidIdParameter('skip', videoParams) || 1, - skipafter: getBidIdParameter('skipafter', videoParams) || 0, - minbitrate: getBidIdParameter('minbitrate', videoParams) || 0, - maxbitrate: getBidIdParameter('maxbitrate', videoParams) || 3500, - delivery: getBidIdParameter('delivery', videoParams) || [2], - playbackmethod: getBidIdParameter('playbackmethod', videoParams) || [1, 2, 3, 4], - api: getBidIdParameter('api', videoParams) || [2], - linearity: getBidIdParameter('linearity', videoParams) || 1 + w: utils.deepAccess(videoMediaTypes, 'playerSize')[0][0], + h: utils.deepAccess(videoMediaTypes, 'playerSize')[0][1], + mimes: utils.getBidIdParameter('mimes', videoParams) || ['application/javascript', 'video/mp4', 'video/webm'], + minduration: utils.getBidIdParameter('minduration', videoParams) || 0, + maxduration: utils.getBidIdParameter('maxduration', videoParams) || 500, + protocols: utils.getBidIdParameter('protocols', videoParams) || [2, 3, 5, 6], + startdelay: utils.getBidIdParameter('startdelay', videoParams) || 0, + placement: utils.getBidIdParameter('placement', videoParams) || videoMediaTypes.context === 'outstream' ? 3 : 1, + skip: utils.getBidIdParameter('skip', videoParams) || 1, + skipafter: utils.getBidIdParameter('skipafter', videoParams) || 0, + minbitrate: utils.getBidIdParameter('minbitrate', videoParams) || 0, + maxbitrate: utils.getBidIdParameter('maxbitrate', videoParams) || 3500, + delivery: utils.getBidIdParameter('delivery', videoParams) || [2], + playbackmethod: utils.getBidIdParameter('playbackmethod', videoParams) || [1, 2, 3, 4], + api: utils.getBidIdParameter('api', videoParams) || [2], + linearity: utils.getBidIdParameter('linearity', videoParams) || 1 }; }; diff --git a/modules/weboramaBidAdapter.md b/modules/weboramaBidAdapter.md new file mode 100644 index 00000000000..5bdca0bfcd1 --- /dev/null +++ b/modules/weboramaBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +``` +Module Name: Weborama SSP Bidder Adapter +Module Type: Bidder Adapter +Maintainer: devweborama@gmail.com +``` + +# Description + +Module that connects to Weborama SSP demand sources + +# Test Parameters +``` + var adUnits = [{ + code: 'placementCode', + sizes: [[300, 250]], + bids: [{ + bidder: 'weborama', + params: { + placementId: 0, + traffic: 'banner' + } + }] + } + ]; +``` diff --git a/modules/weboramaRtdProvider.js b/modules/weboramaRtdProvider.js deleted file mode 100644 index 0885df02f05..00000000000 --- a/modules/weboramaRtdProvider.js +++ /dev/null @@ -1,619 +0,0 @@ -/** - * This module adds Weborama provider to the real time data module - * The {@link module:modules/realTimeData} module is required - * The module will fetch contextual data (page-centric) from Weborama server - * and may access user-centric data from local storage - * @module modules/weboramaRtdProvider - * @requires module:modules/realTimeData - */ - -/** onData callback type - * @callback dataCallback - * @param {Object} data profile data - * @param {Boolean} site true if site, else it is user - * @returns {void} - */ - -/** - * @typedef {Object} ModuleParams - * @property {?Boolean} setPrebidTargeting if true, will set the GAM targeting (default undefined) - * @property {?Boolean} sendToBidders if true, will send the contextual profile to all bidders (default undefined) - * @property {?dataCallback} onData callback - * @property {?WeboCtxConf} weboCtxConf - * @property {?WeboUserDataConf} weboUserDataConf - */ - -/** - * @typedef {Object} WeboCtxConf - * @property {string} token required token to be used on bigsea contextual API requests - * @property {?string} targetURL specify the target url instead use the referer - * @property {?Boolean} setPrebidTargeting if true, will set the GAM targeting (default params.setPrebidTargeting or true) - * @property {?Boolean} sendToBidders if true, will send the contextual profile to all bidders (default params.sendToBidders or true) - * @property {?dataCallback} onData callback - * @property {?object} defaultProfile to be used if the profile is not found - * @property {?Boolean} enabled if false, will ignore this configuration - */ - -/** - * @typedef {Object} WeboUserDataConf - * @property {?number} accountId wam account id - * @property {?Boolean} setPrebidTargeting if true, will set the GAM targeting (default params.setPrebidTargeting or true) - * @property {?Boolean} sendToBidders if true, will send the user-centric profile to all bidders (default params.sendToBidders or true) - * @property {?object} defaultProfile to be used if the profile is not found - * @property {?dataCallback} onData callback - * @property {?string} localStorageProfileKey can be used to customize the local storage key (default is 'webo_wam2gam_entry') - * @property {?Boolean} enabled if false, will ignore this configuration - */ - -import { - getGlobal -} from '../src/prebidGlobal.js'; -import { - deepSetValue, - deepAccess, - isEmpty, - mergeDeep, - logError, - logWarn, - tryAppendQueryString, - logMessage, - isFn -} from '../src/utils.js'; -import { - submodule -} from '../src/hook.js'; -import { - ajax -} from '../src/ajax.js'; -import { - getStorageManager -} from '../src/storageManager.js'; - -const adapterManager = require('../src/adapterManager.js').default; - -/** @type {string} */ -const MODULE_NAME = 'realTimeData'; -/** @type {string} */ -const SUBMODULE_NAME = 'weborama'; -/** @type {string} */ -export const DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY = 'webo_wam2gam_entry'; -/** @type {string} */ -const LOCAL_STORAGE_USER_TARGETING_SECTION = 'targeting'; -/** @type {number} */ -const GVLID = 284; -/** @type {object} */ -export const storage = getStorageManager({gvlid: GVLID, moduleName: SUBMODULE_NAME}); - -/** @type {null|Object} */ -let _weboContextualProfile = null; - -/** @type {Boolean} */ -let _weboCtxInitialized = false; - -/** @type {null|Object} */ -let _weboUserDataUserProfile = null; - -/** @type {Boolean} */ -let _weboUserDataInitialized = false; - -/** Initialize module - * @param {object} moduleConfig - * @return {Boolean} true if module was initialized with success - */ -function init(moduleConfig) { - moduleConfig = moduleConfig || {}; - const moduleParams = moduleConfig.params || {}; - const weboCtxConf = moduleParams.weboCtxConf; - const weboUserDataConf = moduleParams.weboUserDataConf; - - _weboCtxInitialized = initWeboCtx(moduleParams, weboCtxConf); - _weboUserDataInitialized = initWeboUserData(moduleParams, weboUserDataConf); - - return _weboCtxInitialized || _weboUserDataInitialized; -} - -/** Initialize contextual sub module - * @param {ModuleParams} moduleParams - * @param {WeboCtxConf} weboCtxConf - * @return {Boolean} true if sub module was initialized with success - */ -function initWeboCtx(moduleParams, weboCtxConf) { - if (!weboCtxConf || weboCtxConf.enabled === false) { - moduleParams.weboCtxConf = null; - - return false - } - - normalizeConf(moduleParams, weboCtxConf); - - _weboCtxInitialized = false; - _weboContextualProfile = null; - - if (!weboCtxConf.token) { - logWarn('missing param "token" for weborama contextual sub module initialization'); - return false; - } - - logMessage('weborama contextual intialized with success'); - - return true; -} - -/** Initialize weboUserData sub module - * @param {ModuleParams} moduleParams - * @param {WeboUserDataConf} weboUserDataConf - * @return {Boolean} true if sub module was initialized with success - */ -function initWeboUserData(moduleParams, weboUserDataConf) { - if (!weboUserDataConf || weboUserDataConf.enabled === false) { - moduleParams.weboUserDataConf = null; - - return false; - } - - normalizeConf(moduleParams, weboUserDataConf); - - _weboUserDataInitialized = false; - _weboUserDataUserProfile = null; - - let message = 'weborama user-centric intialized with success'; - if (weboUserDataConf.hasOwnProperty('accountId')) { - message = `weborama user-centric intialized with success for account: ${weboUserDataConf.accountId}`; - } - - logMessage(message); - - return true; -} - -/** @type {Object} */ -const globalDefaults = { - setPrebidTargeting: true, - sendToBidders: true, - onData: (data, kind, def) => logMessage('onData(data,kind,default)', data, kind, def), -} - -/** normalize submodule configuration - * @param {ModuleParams} moduleParams - * @param {WeboCtxConf|WeboUserDataConf} submoduleParams - * @return {void} - */ -function normalizeConf(moduleParams, submoduleParams) { - Object.entries(globalDefaults).forEach(([propertyName, globalDefaultValue]) => { - if (!submoduleParams.hasOwnProperty(propertyName)) { - const hasModuleParam = moduleParams.hasOwnProperty(propertyName); - submoduleParams[propertyName] = (hasModuleParam) ? moduleParams[propertyName] : globalDefaultValue; - } - }) -} - -/** function that provides ad server targeting data to RTD-core - * @param {Array} adUnitsCodes - * @param {Object} moduleConfig - * @returns {Object} target data - */ -function getTargetingData(adUnitsCodes, moduleConfig) { - moduleConfig = moduleConfig || {}; - const moduleParams = moduleConfig.params || {}; - const weboCtxConf = moduleParams.weboCtxConf || {}; - const weboUserDataConf = moduleParams.weboUserDataConf || {}; - const weboCtxConfTargeting = weboCtxConf.setPrebidTargeting; - const weboUserDataConfTargeting = weboUserDataConf.setPrebidTargeting; - - try { - const profile = getCompleteProfile(moduleParams, weboCtxConfTargeting, weboUserDataConfTargeting); - - if (isEmpty(profile)) { - return {}; - } - - const td = adUnitsCodes.reduce((data, adUnitCode) => { - if (adUnitCode) { - data[adUnitCode] = profile; - } - return data; - }, {}); - - return td; - } catch (e) { - logError('unable to format weborama rtd targeting data', e); - return {}; - } -} - -/** function that provides complete profile formatted to be used - * @param {ModuleParams} moduleParams - * @param {Boolean} weboCtxConfTargeting - * @param {Boolean} weboUserDataConfTargeting - * @returns {Object} complete profile - */ -function getCompleteProfile(moduleParams, weboCtxConfTargeting, weboUserDataConfTargeting) { - const profile = {}; - - if (weboCtxConfTargeting) { - const contextualProfile = getContextualProfile(moduleParams.weboCtxConf || {}); - mergeDeep(profile, contextualProfile); - } - - if (weboUserDataConfTargeting) { - const weboUserDataProfile = getWeboUserDataProfile(moduleParams.weboUserDataConf || {}); - mergeDeep(profile, weboUserDataProfile); - } - - return profile; -} - -/** return contextual profile - * @param {WeboCtxConf} weboCtxConf - * @returns {Object} contextual profile - */ -function getContextualProfile(weboCtxConf) { - const defaultContextualProfile = weboCtxConf.defaultProfile || {}; - return _weboContextualProfile || defaultContextualProfile; -} - -/** return weboUserData profile - * @param {WeboUserDataConf} weboUserDataConf - * @returns {Object} weboUserData profile - */ -function getWeboUserDataProfile(weboUserDataConf) { - const weboUserDataDefaultUserProfile = weboUserDataConf.defaultProfile || {}; - - if (storage.localStorageIsEnabled() && !_weboUserDataUserProfile) { - const localStorageProfileKey = weboUserDataConf.localStorageProfileKey || DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY; - - const entry = storage.getDataFromLocalStorage(localStorageProfileKey); - if (entry) { - const data = JSON.parse(entry); - if (data && Object.keys(data).length > 0) { - _weboUserDataUserProfile = data[LOCAL_STORAGE_USER_TARGETING_SECTION]; - } - } - } - - return _weboUserDataUserProfile || weboUserDataDefaultUserProfile; -} - -/** function that will allow RTD sub-modules to modify the AdUnit object for each auction - * @param {Object} reqBidsConfigObj - * @param {doneCallback} onDone - * @param {Object} moduleConfig - * @returns {void} - */ -export function getBidRequestData(reqBidsConfigObj, onDone, moduleConfig) { - moduleConfig = moduleConfig || {}; - const moduleParams = moduleConfig.params || {}; - const weboCtxConf = moduleParams.weboCtxConf || {}; - - const adUnits = reqBidsConfigObj.adUnits || getGlobal().adUnits; - - if (!_weboCtxInitialized) { - handleBidRequestData(adUnits, moduleParams); - - onDone(); - - return; - } - - fetchContextualProfile(weboCtxConf, (data) => { - logMessage('fetchContextualProfile on getBidRequestData is done'); - - setWeboContextualProfile(data); - }, () => { - handleBidRequestData(adUnits, moduleParams); - - onDone(); - }); -} - -/** function that handles bid request data - * @param {Object[]} adUnits - * @param {ModuleParams} moduleParams - * @returns {void} - */ - -function handleBidRequestData(adUnits, moduleParams) { - const weboCtxConf = moduleParams.weboCtxConf || {}; - const weboUserDataConf = moduleParams.weboUserDataConf || {}; - const weboCtxConfTargeting = weboCtxConf.sendToBidders; - const weboUserDataConfTargeting = weboUserDataConf.sendToBidders; - - if (weboCtxConfTargeting) { - const contextualProfile = getContextualProfile(weboCtxConf); - if (!isEmpty(contextualProfile)) { - setBidRequestProfile(adUnits, contextualProfile, true); - } - } - - if (weboUserDataConfTargeting) { - const weboUserDataProfile = getWeboUserDataProfile(weboUserDataConf); - if (!isEmpty(weboUserDataProfile)) { - setBidRequestProfile(adUnits, weboUserDataProfile, false); - } - } - - handleOnData(weboCtxConf, weboUserDataConf); -} - -/** function that handle with onData callbacks - * @param {WeboCtxConf} weboCtxConf - * @param {WeboUserDataConf} weboUserDataConf - */ - -function handleOnData(weboCtxConf, weboUserDataConf) { - const callbacks = [{ - onData: weboCtxConf.onData, - fetchData: () => getContextualProfile(weboCtxConf), - site: true, - }, { - onData: weboUserDataConf.onData, - fetchData: () => getWeboUserDataProfile(weboUserDataConf), - site: false, - }]; - - callbacks.filter(obj => isFn(obj.onData)).forEach(obj => { - try { - const data = obj.fetchData(); - obj.onData(data, obj.site); - } catch (e) { - const kind = (obj.site) ? 'site' : 'user'; - logError(`error while executure onData callback with ${kind}-based data:`, e); - } - }); -} - -/** function that set bid request data on each segment (site or user centric) - * @param {Object[]} adUnits - * @param {Object} profile - * @param {Boolean} site true if site centric, else it is user centric - * @returns {void} - */ -function setBidRequestProfile(adUnits, profile, site) { - setGlobalOrtb2(profile, site); - - adUnits.forEach(adUnit => { - if (adUnit.hasOwnProperty('bids')) { - const adUnitCode = adUnit.code || 'no code'; - adUnit.bids.forEach(bid => handleBid(adUnitCode, profile, site, bid)); - } - }); -} - -/** @type {string} */ -const APPNEXUS = 'appnexus'; - -/** @type {string} */ -const PUBMATIC = 'pubmatic'; - -/** @type {string} */ -const RUBICON = 'rubicon'; - -/** @type {string} */ -const SMARTADSERVER = 'smartadserver'; - -/** @type {Object} */ -const bidderAliasRegistry = adapterManager.aliasRegistry || {}; - -/** handle individual bid - * @param {string} adUnitCode - * @param {Object} profile - * @param {Boolean} site true if site centric, else it is user centric - * @param {Object} bid - * @returns {void} - */ -function handleBid(adUnitCode, profile, site, bid) { - const bidder = bidderAliasRegistry[bid.bidder] || bid.bidder; - - logMessage(`handling on adunit '${adUnitCode}', bidder '${bidder}' and bid`, bid); - - switch (bidder) { - case APPNEXUS: - handleAppnexusBid(profile, bid); - - break; - - case PUBMATIC: - handlePubmaticBid(profile, bid); - - break; - - case SMARTADSERVER: - handleSmartadserverBid(profile, bid); - - break; - case RUBICON: - handleRubiconBid(profile, site, bid); - - break; - default: - logMessage(`unsupported bidder '${bidder}', trying via bidder ortb2 fpd`); - const section = ((site) ? 'site' : 'user'); - const base = `ortb2.${section}.ext.data`; - - assignProfileToObject(bid, base, profile); - } -} - -/** - * set ortb2 global data - * @param {Object} profile - * @param {Boolean} site - * @returns {void} - */ -function setGlobalOrtb2(profile, site) { - const section = ((site) ? 'site' : 'user'); - const base = `${section}.ext.data`; - const addOrtb2 = {}; - - assignProfileToObject(addOrtb2, base, profile); - - if (!isEmpty(addOrtb2)) { - const testGlobal = getGlobal().getConfig('ortb2') || {}; - const ortb2 = { - ortb2: mergeDeep({}, testGlobal, addOrtb2) - }; - getGlobal().setConfig(ortb2); - } -} - -/** - * assign profile to object - * @param {Object} destination - * @param {string} base - * @param {Object} profile - * @returns {void} - */ -function assignProfileToObject(destination, base, profile) { - Object.keys(profile).forEach(key => { - const path = `${base}.${key}`; - deepSetValue(destination, path, profile[key]) - }) -} - -/** handle rubicon bid - * @param {Object} profile - * @param {Boolean} site - * @param {Object} bid - * @returns {void} - */ -function handleRubiconBid(profile, site, bid) { - const section = (site) ? 'inventory' : 'visitor'; - const base = `params.${section}`; - assignProfileToObject(bid, base, profile); -} - -/** handle appnexus/xandr bid - * @param {Object} profile - * @param {Object} bid - * @returns {void} - */ -function handleAppnexusBid(profile, bid) { - const base = 'params.keywords'; - assignProfileToObject(bid, base, profile); -} - -/** handle pubmatic bid - * @param {Object} profile - * @param {Object} bid - * @returns {void} - */ -function handlePubmaticBid(profile, bid) { - const sep = '|'; - const subsep = ','; - const bidKey = 'params.dctr'; - const target = []; - - const data = deepAccess(bid, bidKey); - if (data) { - data.split(sep).forEach(t => target.push(t)); - } - - Object.keys(profile).forEach(key => { - const value = profile[key].join(subsep); - const keyword = `${key}=${value}`; - if (target.indexOf(keyword) === -1) { - target.push(keyword); - } - }); - - deepSetValue(bid, bidKey, target.join(sep)); -} - -/** handle smartadserver bid - * @param {Object} profile - * @param {Object} bid - * @returns {void} - */ -function handleSmartadserverBid(profile, bid) { - const sep = ';'; - const bidKey = 'params.target'; - const target = []; - - const data = deepAccess(bid, bidKey); - if (data) { - data.split(sep).forEach(t => target.push(t)); - } - - Object.keys(profile).forEach(key => { - profile[key].forEach(value => { - const keyword = `${key}=${value}`; - if (target.indexOf(keyword) === -1) { - target.push(keyword); - } - }); - }); - deepSetValue(bid, bidKey, target.join(sep)); -} - -/** set bigsea contextual profile on module state - * @param {null|Object} data - * @returns {void} - */ -export function setWeboContextualProfile(data) { - if (data && Object.keys(data).length > 0) { - _weboContextualProfile = data; - } -} - -/** onSuccess callback type - * @callback successCallback - * @param {null|Object} data - * @returns {void} - */ - -/** onDone callback type - * @callback doneCallback - * @returns {void} - */ - -/** Fetch Bigsea Contextual Profile - * @param {WeboCtxConf} weboCtxConf - * @param {successCallback} onSuccess callback - * @param {doneCallback} onDone callback - * @returns {void} - */ -function fetchContextualProfile(weboCtxConf, onSuccess, onDone) { - const targetURL = weboCtxConf.targetURL || document.URL; - const token = weboCtxConf.token; - - let queryString = ''; - queryString = tryAppendQueryString(queryString, 'token', token); - queryString = tryAppendQueryString(queryString, 'url', targetURL); - - const url = `https://ctx.weborama.com/api/profile?${queryString}`; - - ajax(url, { - success: function(response, req) { - if (req.status === 200) { - try { - const data = JSON.parse(response); - onSuccess(data); - onDone(); - } catch (e) { - onDone(); - logError('unable to parse weborama data', e); - throw e; - } - } else if (req.status === 204) { - onDone(); - } - }, - error: function() { - onDone(); - logError('unable to get weborama data'); - } - }, - null, { - method: 'GET', - withCredentials: false, - }); -} - -export const weboramaSubmodule = { - name: SUBMODULE_NAME, - init: init, - getTargetingData: getTargetingData, - getBidRequestData: getBidRequestData, -}; - -submodule(MODULE_NAME, weboramaSubmodule); diff --git a/modules/weboramaRtdProvider.md b/modules/weboramaRtdProvider.md deleted file mode 100644 index 732944c6e1c..00000000000 --- a/modules/weboramaRtdProvider.md +++ /dev/null @@ -1,157 +0,0 @@ -# Weborama Real-Time Data Submodule - -``` -Module Name: Weborama Rtd Provider -Module Type: Rtd Provider -Maintainer: prebid-support@weborama.com -``` - -# Description - -Weborama provides a Semantic AI Contextual API that classifies in Real-time a web page seen by a web user within generic and custom topics. It enables publishers to better monetize their inventory and unlock it to programmatic. - -Contact prebid-support@weborama.com for information. - -### Publisher Usage - -Compile the Weborama RTD module into your Prebid build: - -`gulp build --modules=rtdModule,weboramaRtdProvider` - -Add the Weborama RTD provider to your Prebid config. - -```javascript -var pbjs = pbjs || {}; -pbjs.que = pbjs.que || []; - -pbjs.que.push(function () { - pbjs.setConfig({ - debug: true, - realTimeData: { - auctionDelay: 1000, - dataProviders: [{ - name: "weborama", - waitForIt: true, - params: { - setPrebidTargeting: true, // optional - sendToBidders: true, // optional - onData: function(data, site){ // optional - var kind = (site)? 'site' : 'user'; - console.log('onData', kind, data); - }, - weboCtxConf: { - token: "to-be-defined", // mandatory - targetURL: "https://prebid.org", // default is document.URL - setPrebidTargeting: true, // override param.setPrebidTargeting or default true - sendToBidders: true, // override param.sendToBidders or default true - defaultProfile: { // optional - webo_ctx: ['moon'], - webo_ds: ['bar'] - } - //, onData: function (data, ...) { ...} - }, - weboUserDataConf: { - accountId: 12345, // optional, used for logging - setPrebidTargeting: true, // override param.setPrebidTargeting or default true - sendToBidders: true, // override param.sendToBidders or default true - defaultProfile: { // optional - webo_cs: ['Red'], - webo_audiences: ['bam'] - }, - localStorageProfileKey: 'webo_wam2gam_entry' // default - //, onData: function (data, ...) { ...} - } - } - }] - } - }); -}); -``` - -### Parameter Descriptions for the Weborama Configuration Section - -| Name |Type | Description | Notes | -| :------------ | :------------ | :------------ |:------------ | -| name | String | Real time data module name | Mandatory. Always 'Weborama' | -| waitForIt | Boolean | Mandatory. Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false but recommended to true | -| params | Object | | Optional | -| params.setPrebidTargeting | Boolean | If true, may use the profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js | Optional. Affects the `weboCtxConf` and `weboUserDataConf` sections | -| params.sendToBidders | Boolean | If true, may send the profile to all bidders | Optional. Affects the `weboCtxConf` and `weboUserDataConf` sections | -| params.weboCtxConf | Object | Weborama Contextual Configuration | Optional -| params.weboUserDataConf | Object | Weborama User-Centric Configuration | Optional | -| params.onData | Callback | If set, will receive the profile and site flag | Optional. Affects the `weboCtxConf` and `weboUserDataConf` sections | - -#### Contextual Configuration - -| Name |Type | Description | Notes | -| :------------ | :------------ | :------------ |:------------ | -| token | String | Security Token provided by Weborama, unique per client | Mandatory | -| targetURL | String | Url to be profiled in the contextual api | Optional. Defaults to `document.URL` | -| setPrebidTargeting|Boolean|If true, will use the contextual profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js| Optional. Default is `params.setPrebidTargeting` (if any) or **true**.| -| sendToBidders|Boolean|If true, will send the contextual profile to all bidders| Optional. Default is `params.sendToBidders` (if any) or **true**.| -| defaultProfile | Object | default value of the profile to be used when there are no response from contextual api (such as timeout)| Optional. Default is `{}` | -| onData | Callback | If set, will receive the profile and site flag | Optional. Default is `params.onData` (if any) or log via prebid debug | -| enabled | Boolean| if false, will ignore this configuration| default true| - -#### User-Centric Configuration - -| Name |Type | Description | Notes | -| :------------ | :------------ | :------------ |:------------ | -| accountId|Number|WAM account id. If present, will be used on logging and statistics| Optional.| -| setPrebidTargeting|Boolean|If true, will use the user profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js| Optional. Default is `params.setPrebidTargeting` (if any) or **true**.| -| sendToBidders|Boolean|If true, will send the user profile to all bidders| Optional. Default is `params.sendToBidders` (if any) or **true**.| -| onData | Callback | If set, will receive the profile and site flag | Optional. Default is `params.onData` (if any) or log via prebid debug | -| defaultProfile | Object | default value of the profile to be used when there are no response from contextual api (such as timeout)| Optional. Default is `{}` | -| localStorageProfileKey| String | can be used to customize the local storage key | Optional | -| enabled | Boolean| if false, will ignore this configuration| default true| - -### Supported Bidders - -We currently support the following bidder adapters: -* SmartADServer SSP -* PubMatic SSP -* AppNexus SSP -* Rubicon SSP - -We also set the bidder and global ortb2 `site` and `user` sections. The following bidders may support it, to be sure, check the `First Party Data Support` on the feature list for the particular bidder from here: https://docs.prebid.org/dev-docs/bidders - -* Adagio -* AdformOpenRTB -* AdKernel -* AdMixer -* Adnuntius -* Adrelevantis -* adxcg -* AMX RTB -* Avocet -* BeOp -* Criteo -* Etarget -* Inmar -* Index Exchange -* Livewrapped -* Mediakeys -* NoBid -* OpenX -* Opt Out Advertising -* Ozone Project -* Proxistore -* Rise -* Smaato -* Sonobi -* TheMediaGrid -* TripleLift -* TrustX -* Yahoo SSP -* Yieldlab -* Zeta Global Ssp - -### Testing - -To view an example of available segments returned by Weborama's backends: - -`gulp serve --notest --nolint --modules=rtdModule,weboramaRtdProvider,smartadserverBidAdapter,pubmaticBidAdapter,appnexusBidAdapter,rubiconBidAdapter,criteoBidAdapter` - -and then point your browser at: - -`http://localhost:9999/integrationExamples/gpt/weboramaRtdProvider_example.html` diff --git a/modules/welectBidAdapter.js b/modules/welectBidAdapter.js deleted file mode 100644 index d88a3f4c3e2..00000000000 --- a/modules/welectBidAdapter.js +++ /dev/null @@ -1,106 +0,0 @@ -import { deepAccess } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; - -const BIDDER_CODE = 'welect'; -const DEFAULT_DOMAIN = 'www.welect.de'; - -export const spec = { - code: BIDDER_CODE, - aliases: ['wlt'], - gvlid: 282, - supportedMediaTypes: ['video'], - - // short code - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function (bid) { - return ( - deepAccess(bid, 'mediaTypes.video.context') === 'instream' && - !!bid.params.placementId - ); - }, - /** - * Make a server request from the list of BidRequests. - * - * @param {validBidRequests[]} - an array of bids - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function (validBidRequests) { - return validBidRequests.map((bidRequest) => { - let rawSizes = - deepAccess(bidRequest, 'mediaTypes.video.playerSize') || - bidRequest.sizes; - let size = rawSizes[0]; - - let domain = bidRequest.params.domain || DEFAULT_DOMAIN; - - let url = `https://${domain}/api/v2/preflight/${bidRequest.params.placementId}`; - - let gdprConsent = null; - - if (bidRequest && bidRequest.gdprConsent) { - gdprConsent = { - gdpr_consent: { - gdprApplies: bidRequest.gdprConsent.gdprApplies, - tcString: bidRequest.gdprConsent.gdprConsent, - }, - }; - } - - const data = { - width: size[0], - height: size[1], - bid_id: bidRequest.bidId, - ...gdprConsent, - }; - - return { - method: 'POST', - url: url, - data: data, - options: { - contentType: 'application/json', - withCredentials: false, - crossOrigin: true, - }, - }; - }); - }, - /** - * Unpack the response from the server into a list of bids. - * - * @param {ServerResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function (serverResponse, bidRequest) { - const responseBody = serverResponse.body; - - if (typeof responseBody !== 'object' || responseBody.available !== true) { - return []; - } - - const bidResponses = []; - const bidResponse = { - requestId: responseBody.bidResponse.requestId, - cpm: responseBody.bidResponse.cpm, - width: responseBody.bidResponse.width, - height: responseBody.bidResponse.height, - creativeId: responseBody.bidResponse.creativeId, - currency: responseBody.bidResponse.currency, - netRevenue: responseBody.bidResponse.netRevenue, - ttl: responseBody.bidResponse.ttl, - ad: responseBody.bidResponse.ad, - vastUrl: responseBody.bidResponse.vastUrl, - meta: { - advertiserDomains: responseBody.bidResponse.meta.advertiserDomains - } - }; - bidResponses.push(bidResponse); - return bidResponses; - }, -}; -registerBidder(spec); diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js index ba94f90f9c9..7890628f94b 100644 --- a/modules/widespaceBidAdapter.js +++ b/modules/widespaceBidAdapter.js @@ -1,8 +1,14 @@ import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {parseQueryStringParameters, parseSizesInput} from '../src/utils.js'; -import {find, includes} from '../src/polyfill.js'; -import {getStorageManager} from '../src/storageManager.js'; +import { + parseQueryStringParameters, + parseSizesInput +} from '../src/utils.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import find from 'core-js-pure/features/array/find.js'; +import { getStorageManager } from '../src/storageManager.js'; + +export const storage = getStorageManager(); const BIDDER_CODE = 'widespace'; const WS_ADAPTER_VERSION = '2.0.1'; @@ -11,7 +17,6 @@ const LS_KEYS = { LC_UID: 'wsLcuid', CUST_DATA: 'wsCustomData' }; -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); let preReqTime = 0; diff --git a/modules/winrBidAdapter.js b/modules/winrBidAdapter.js index 124aba57866..b73758e9717 100644 --- a/modules/winrBidAdapter.js +++ b/modules/winrBidAdapter.js @@ -1,22 +1,12 @@ -import { - convertCamelToUnderscore, - convertTypes, - deepAccess, - getBidRequest, - getParameterByName, - isArray, - isEmpty, - isFn, - isNumber, - isPlainObject, - logError, - transformBidderParamKeywords -} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER} from '../src/mediaTypes.js'; -import {find, includes} from '../src/polyfill.js'; -import {getStorageManager} from '../src/storageManager.js'; +import * as utils from '../src/utils.js'; +import { config } from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER } from '../src/mediaTypes.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import { getStorageManager } from '../src/storageManager.js'; + +export const storage = getStorageManager(); const BIDDER_CODE = 'winr'; const URL = 'https://ib.adnxs.com/ut/v3/prebid'; @@ -27,8 +17,6 @@ const SOURCE = 'pbjs'; const DEFAULT_CURRENCY = 'USD'; const GATE_COOKIE_NAME = 'wnr_gate'; -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); - function buildBid(bidData) { const bid = bidData; const position = { @@ -51,9 +39,9 @@ function wrapAd(bid, position) { - + `, + ad: ``, meta: { advertiserDomains: (matchedBid.advertiser) ? matchedBid.advertiser : 'n/a' } @@ -137,7 +130,7 @@ export const spec = { bidResponse.height = playersize[1] } bidResponse.mediaType = VIDEO - bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/?ts=${timestamp}${extId}${gdprApplies}${gdprConsent}${pvId}${iabContent}` + bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/?ts=${timestamp}${extId}${gdprApplies}${gdprConsent}${pvId}` if (isOutstream(bidRequest)) { const renderer = Renderer.install({ id: bidRequest.bidId, @@ -149,62 +142,10 @@ export const spec = { } } - if (isNative(bidRequest, adType)) { - const url = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/?ts=${timestamp}${extId}${gdprApplies}${gdprConsent}${pvId}` - bidResponse.adUrl = url - bidResponse.mediaType = NATIVE - const nativeImageAssetObj = find(matchedBid.native.assets, e => e.id === 2) - const nativeImageAsset = nativeImageAssetObj ? nativeImageAssetObj.img : {url: '', w: 0, h: 0}; - const nativeTitleAsset = find(matchedBid.native.assets, e => e.id === 1) - const nativeBodyAsset = find(matchedBid.native.assets, e => e.id === 3) - bidResponse.native = { - title: nativeTitleAsset ? nativeTitleAsset.title.text : '', - body: nativeBodyAsset ? nativeBodyAsset.data.value : '', - image: { - url: nativeImageAsset.url, - width: nativeImageAsset.w, - height: nativeImageAsset.h, - }, - clickUrl: matchedBid.native.link.url, - impressionTrackers: matchedBid.native.imptrackers, - }; - } - bidResponses.push(bidResponse) } }) return bidResponses - }, - - /** - * Register the user sync pixels which should be dropped after the auction. - * - * @param {SyncOptions} syncOptions Which user syncs are allowed? - * @param {ServerResponse[]} serverResponses List of server's responses. - * @param {Object} gdprConsent Is the GDPR Consent object wrapping gdprApplies {boolean} and consentString {string} attributes. - * @param {string} uspConsent Is the US Privacy Consent string. - * @return {UserSync[]} The user syncs which should be dropped. - */ - getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) { - const syncs = []; - - if (syncOptions.iframeEnabled) { - let params = []; - params.push(`ts=${timestamp()}`); - params.push(`type=h`) - if (gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean')) { - params.push(`gdpr=${Number(gdprConsent.gdprApplies)}`); - } - if (gdprConsent && (typeof gdprConsent.consentString === 'string')) { - params.push(`gdpr_consent=${gdprConsent.consentString}`); - } - syncs.push({ - type: 'iframe', - url: `${ENDPOINT}/d/6846326/766/2x2?${params.join('&')}` - }); - } - - return syncs; } }; @@ -214,18 +155,8 @@ export const spec = { * @param {String} adtype * @returns {Boolean} */ -function isVideo(format, adtype) { - return deepAccess(format, 'mediaTypes.video') && adtype.toLowerCase() === 'video' -} - -/** - * Is this a native format? - * @param {Object} format - * @param {String} adtype - * @returns {Boolean} - */ -function isNative(format, adtype) { - return deepAccess(format, 'mediaTypes.native') && adtype.toLowerCase() === 'native' +function isVideo (format, adtype) { + return utils.deepAccess(format, 'mediaTypes.video') && adtype.toLowerCase() === 'video' } /** @@ -233,8 +164,8 @@ function isNative(format, adtype) { * @param {Object} format * @returns {Boolean} */ -function isOutstream(format) { - let context = deepAccess(format, 'mediaTypes.video.context') +function isOutstream (format) { + let context = utils.deepAccess(format, 'mediaTypes.video.context') return (context === 'outstream') } @@ -243,9 +174,9 @@ function isOutstream(format) { * @param {Object} format * @returns {Array} */ -function getPlayerSize(format) { - let playerSize = deepAccess(format, 'mediaTypes.video.playerSize') - return (playerSize && isArray(playerSize[0])) ? playerSize[0] : playerSize +function getPlayerSize (format) { + let playerSize = utils.deepAccess(format, 'mediaTypes.video.playerSize') + return (playerSize && utils.isArray(playerSize[0])) ? playerSize[0] : playerSize } /** @@ -253,7 +184,7 @@ function getPlayerSize(format) { * @param {String} size * @returns {Array} */ -function parseSize(size) { +function parseSize (size) { return size.split('x').map(Number) } @@ -262,7 +193,7 @@ function parseSize(size) { * @param {Array} eids * @returns {String} */ -function createUserIdString(eids) { +function createUserIdString (eids) { let str = [] for (let i = 0; i < eids.length; i++) { str.push(eids[i].source + ':' + eids[i].uids[0].id) @@ -275,12 +206,12 @@ function createUserIdString(eids) { * @param {Object} obj * @returns {String} */ -function createQueryString(obj) { +function createQueryString (obj) { let str = [] for (var p in obj) { if (obj.hasOwnProperty(p)) { let val = obj[p] - if (p !== 'schain' && p !== 'iab_content') { + if (p !== 'schain') { str.push(encodeURIComponent(p) + '=' + encodeURIComponent(val)) } else { str.push(p + '=' + val) @@ -295,7 +226,7 @@ function createQueryString(obj) { * @param {Object} obj * @returns {String} */ -function createTargetingString(obj) { +function createTargetingString (obj) { let str = [] for (var p in obj) { if (obj.hasOwnProperty(p)) { @@ -312,7 +243,7 @@ function createTargetingString(obj) { * @param {Object} schain * @returns {String} */ -function createSchainString(schain) { +function createSchainString (schain) { const ver = schain.ver || '' const complete = (schain.complete === 1 || schain.complete === 0) ? schain.complete : '' const keys = ['asi', 'sid', 'hp', 'rid', 'name', 'domain', 'ext'] @@ -322,44 +253,6 @@ function createSchainString(schain) { return `${ver},${complete}${nodesString}` } -/** - * Get content object from bid request - * First get content from bidder params; - * If not provided in bidder params, get from first party data under 'ortb2.site.content' or 'ortb2.app.content' - * @param {Object} bid - * @returns {Object} - */ -function getContentObject(bid) { - if (bid.params.iabContent && isPlainObject(bid.params.iabContent)) { - return bid.params.iabContent - } - - const globalContent = config.getConfig('ortb2.site') ? config.getConfig('ortb2.site.content') - : config.getConfig('ortb2.app.content') - if (globalContent && isPlainObject(globalContent)) { - return globalContent - } - return undefined -} - -/** - * Creates a string for iab_content object - * @param {Object} iabContent - * @returns {String} - */ -function createIabContentString(iabContent) { - const arrKeys = ['keywords', 'cat'] - let str = [] - for (let key in iabContent) { - if (iabContent.hasOwnProperty(key)) { - const value = (arrKeys.indexOf(key) !== -1 && Array.isArray(iabContent[key])) - ? iabContent[key].map(node => encodeURIComponent(node)).join('|') : encodeURIComponent(iabContent[key]) - str.push(''.concat(key, ':', value)) - } - } - return encodeURIComponent(str.join(',')) -} - /** * Encodes URI Component with exlamation mark included. Needed for schain object. * @param {String} str diff --git a/modules/yieldlabBidAdapter.md b/modules/yieldlabBidAdapter.md index 1f52e26f5c7..a7a3f2715dc 100644 --- a/modules/yieldlabBidAdapter.md +++ b/modules/yieldlabBidAdapter.md @@ -11,96 +11,38 @@ Maintainer: solutions@yieldlab.de Module that connects to Yieldlab's demand sources # Test Parameters - -```javascript -const adUnits = [ - { - code: 'banner', - sizes: [ [ 728, 90 ] ], - bids: [{ - bidder: 'yieldlab', - params: { - adslotId: '5220336', - supplyId: '1381604', - targeting: { - key1: 'value1', - key2: 'value2' - }, - extId: 'abc', - iabContent: { - id: 'some_id', - episode: '1', - title: 'some title', - series: 'some series', - season: 's1', - artist: 'John Doe', - genre: 'some genre', - isrc: 'CC-XXX-YY-NNNNN', - url: 'http://foo_url.de', - cat: [ 'IAB1-1', 'IAB1-2', 'IAB2-10' ], - context: '7', - keywords: ['k1', 'k2'], - live: '0' - } - } - }] - }, - { - code: 'video', - sizes: [ [ 640, 480 ] ], - mediaTypes: { - video: { - context: 'instream' // or 'outstream' - } - }, - bids: [{ - bidder: 'yieldlab', - params: { - adslotId: '5220339', - supplyId: '1381604' - } - }] - }, - { - code: 'native', - mediaTypes: { - native: { - // native config - } - }, - bids: [{ - bidder: 'yieldlab', - params: { - adslotId: '5220339', - supplyId: '1381604' - } - }] - } -]; ``` - -# Multi-Format Setup - -A general overview of how to set up multi-format ads can be found in the offical Prebid.js docs. See: [show multi-format ads](https://docs.prebid.org/dev-docs/show-multi-format-ads.html) - -When setting up multi-format ads with Yieldlab make sure to always add at least one eligible Adslot per given media type in the ad unit configuration. - -```javascript -const adUnit = { - code: 'multi-format-adslot', - mediaTypes: { - banner: { - sizes: [ [ 728, 90 ] ] - }, - native: { - // native config - } - }, - bids: [ - // banner Adslot - { bidder: 'yieldlab', params: { adslotId: '1234', supplyId: '42' } }, - // native Adslot - { bidder: 'yieldlab', params: { adslotId: '2345', supplyId: '42' } } - ] -}; + var adUnits = [ + { + code: "banner", + sizes: [[728, 90]], + bids: [{ + bidder: "yieldlab", + params: { + adslotId: "5220336", + supplyId: "1381604", + targeting: { + key1: "value1", + key2: "value2" + }, + extId: "abc" + } + }] + }, { + code: "video", + sizes: [[640, 480]], + mediaTypes: { + video: { + context: "instream" // or "outstream" + } + }, + bids: [{ + bidder: "yieldlab", + params: { + adslotId: "5220339", + supplyId: "1381604" + } + }] + } + ]; ``` diff --git a/modules/yieldliftBidAdapter.js b/modules/yieldliftBidAdapter.js index 61b99d95605..9398e2c7816 100644 --- a/modules/yieldliftBidAdapter.js +++ b/modules/yieldliftBidAdapter.js @@ -1,5 +1,5 @@ -import { deepSetValue, logInfo, deepAccess } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; import {BANNER} from '../src/mediaTypes.js'; const ENDPOINT_URL = 'https://x.yieldlift.com/auction'; @@ -58,18 +58,18 @@ export const spec = { // adding schain object if (validBidRequests[0].schain) { - deepSetValue(openrtbRequest, 'source.ext.schain', validBidRequests[0].schain); + utils.deepSetValue(openrtbRequest, 'source.ext.schain', validBidRequests[0].schain); } // Attaching GDPR Consent Params if (bidderRequest.gdprConsent) { - deepSetValue(openrtbRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(openrtbRequest, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + utils.deepSetValue(openrtbRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(openrtbRequest, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); } // CCPA if (bidderRequest.uspConsent) { - deepSetValue(openrtbRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(openrtbRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); } const payloadString = JSON.stringify(openrtbRequest); @@ -102,12 +102,12 @@ export const spec = { }) }) } else { - logInfo('yieldlift.interpretResponse :: no valid responses to interpret'); + utils.logInfo('yieldlift.interpretResponse :: no valid responses to interpret'); } return bidResponses; }, getUserSyncs: function (syncOptions, serverResponses) { - logInfo('yieldlift.getUserSyncs', 'syncOptions', syncOptions, 'serverResponses', serverResponses); + utils.logInfo('yieldlift.getUserSyncs', 'syncOptions', syncOptions, 'serverResponses', serverResponses); let syncs = []; if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) { @@ -115,7 +115,7 @@ export const spec = { } serverResponses.forEach(resp => { - const userSync = deepAccess(resp, 'body.ext.usersync'); + const userSync = utils.deepAccess(resp, 'body.ext.usersync'); if (userSync) { let syncDetails = []; Object.keys(userSync).forEach(key => { @@ -139,7 +139,7 @@ export const spec = { } } }); - logInfo('yieldlift.getUserSyncs result=%o', syncs); + utils.logInfo('yieldlift.getUserSyncs result=%o', syncs); return syncs; }, diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index bc29f4822c8..654e7236210 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -1,23 +1,9 @@ -import { - deepAccess, - deepSetValue, - getWindowTop, - isArray, - isArrayOfNums, - isBoolean, - isEmpty, - isInteger, - isNumber, - isStr, - logError, - parseQueryStringParameters, - parseUrl -} from '../src/utils.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {Renderer} from '../src/Renderer.js'; -import {find, includes} from '../src/polyfill.js'; -import {createEidsArray} from './userId/eids.js'; +import * as utils from '../src/utils.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { Renderer } from '../src/Renderer.js'; +import includes from 'core-js-pure/features/array/includes'; +import find from 'core-js-pure/features/array/find.js'; const BIDDER_CODE = 'yieldmo'; const CURRENCY = 'USD'; @@ -29,7 +15,7 @@ const OUTSTREAM_VIDEO_PLAYER_URL = 'https://prebid-outstream.yieldmo.com/bundle. const OPENRTB_VIDEO_BIDPARAMS = ['mimes', 'startdelay', 'placement', 'startdelay', 'skipafter', 'protocols', 'api', 'playbackmethod', 'maxduration', 'minduration', 'pos', 'skip', 'skippable']; const OPENRTB_VIDEO_SITEPARAMS = ['name', 'domain', 'cat', 'keywords']; -const LOCAL_WINDOW = getWindowTop(); +const LOCAL_WINDOW = utils.getWindowTop(); const DEFAULT_PLAYBACK_METHOD = 2; const DEFAULT_START_DELAY = 0; const VAST_TIMEOUT = 15000; @@ -60,32 +46,29 @@ export const spec = { buildRequests: function (bidRequests, bidderRequest) { const bannerBidRequests = bidRequests.filter(request => hasBannerMediaType(request)); const videoBidRequests = bidRequests.filter(request => hasVideoMediaType(request)); + let serverRequests = []; - const eids = getEids(bidRequests[0]) || []; if (bannerBidRequests.length > 0) { let serverRequest = { pbav: '$prebid.version$', p: [], page_url: bidderRequest.refererInfo.referer, bust: new Date().getTime().toString(), + pr: (LOCAL_WINDOW.document && LOCAL_WINDOW.document.referrer) || '', + scrd: LOCAL_WINDOW.devicePixelRatio || 0, dnt: getDNT(), description: getPageDescription(), + title: LOCAL_WINDOW.document.title || '', + w: LOCAL_WINDOW.innerWidth, + h: LOCAL_WINDOW.innerHeight, userConsent: JSON.stringify({ // case of undefined, stringify will remove param - gdprApplies: deepAccess(bidderRequest, 'gdprConsent.gdprApplies') || '', - cmp: deepAccess(bidderRequest, 'gdprConsent.consentString') || '' + gdprApplies: utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies') || '', + cmp: utils.deepAccess(bidderRequest, 'gdprConsent.consentString') || '' }), - us_privacy: deepAccess(bidderRequest, 'uspConsent') || '' + us_privacy: utils.deepAccess(bidderRequest, 'uspConsent') || '' }; - if (canAccessTopWindow()) { - serverRequest.pr = (LOCAL_WINDOW.document && LOCAL_WINDOW.document.referrer) || ''; - serverRequest.scrd = LOCAL_WINDOW.devicePixelRatio || 0; - serverRequest.title = LOCAL_WINDOW.document.title || ''; - serverRequest.w = LOCAL_WINDOW.innerWidth; - serverRequest.h = LOCAL_WINDOW.innerHeight; - } - const mtp = window.navigator.maxTouchPoints; if (mtp) { serverRequest.mtp = mtp; @@ -110,17 +93,14 @@ export const spec = { if (request.schain) { serverRequest.schain = JSON.stringify(request.schain); } - if (deepAccess(request, 'params.lr_env')) { + if (utils.deepAccess(request, 'params.lr_env')) { serverRequest.ats_envelope = request.params.lr_env; } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; - if (eids.length) { - serverRequest.eids = JSON.stringify(eids); - }; // check if url exceeded max length - const url = `${BANNER_SERVER_ENDPOINT}?${parseQueryStringParameters(serverRequest)}`; + const url = `${BANNER_SERVER_ENDPOINT}?${utils.parseQueryStringParameters(serverRequest)}`; let extraCharacters = url.length - MAX_BANNER_REQUEST_URL_LENGTH; if (extraCharacters > 0) { for (let i = 0; i < BANNER_REQUEST_PROPERTIES_TO_REDUCE.length; i++) { @@ -141,9 +121,6 @@ export const spec = { if (videoBidRequests.length > 0) { const serverRequest = openRtbRequest(videoBidRequests, bidderRequest); - if (eids.length) { - serverRequest.user = { eids }; - }; serverRequests.push({ method: 'POST', url: VIDEO_SERVER_ENDPOINT, @@ -190,14 +167,14 @@ registerBidder(spec); * @param {BidRequest} bidRequest bid request */ function hasBannerMediaType(bidRequest) { - return !!deepAccess(bidRequest, 'mediaTypes.banner'); + return !!utils.deepAccess(bidRequest, 'mediaTypes.banner'); } /** * @param {BidRequest} bidRequest bid request */ function hasVideoMediaType(bidRequest) { - return !!deepAccess(bidRequest, 'mediaTypes.video'); + return !!utils.deepAccess(bidRequest, 'mediaTypes.video'); } /** @@ -205,7 +182,6 @@ function hasVideoMediaType(bidRequest) { * @param request bid request */ function addPlacement(request) { - const gpid = deepAccess(request, 'ortb2Imp.ext.data.pbadslot'); const placementInfo = { placement_id: request.adUnitCode, callback_id: request.bidId, @@ -220,9 +196,6 @@ function addPlacement(request) { placementInfo.bidFloor = bidfloor; } } - if (gpid) { - placementInfo.gpid = gpid; - } return JSON.stringify(placementInfo); } @@ -232,7 +205,6 @@ function addPlacement(request) { */ function createNewBannerBid(response) { return { - dealId: response.publisherDealId, requestId: response['callback_id'], cpm: response.cpm, width: response.width, @@ -255,10 +227,9 @@ function createNewBannerBid(response) { * @param bidRequest server request */ function createNewVideoBid(response, bidRequest) { - const imp = find((deepAccess(bidRequest, 'data.imp') || []), imp => imp.id === response.impid); + const imp = find((utils.deepAccess(bidRequest, 'data.imp') || []), imp => imp.id === response.impid); let result = { - dealId: response.dealid, requestId: imp.id, cpm: response.price, width: imp.video.w, @@ -335,7 +306,7 @@ function getPageDescription() { * @returns an id if there is one, or undefined */ function getId(request, idType) { - return (typeof deepAccess(request, 'userId') === 'object') ? request.userId[idType] : undefined; + return (typeof utils.deepAccess(request, 'userId') === 'object') ? request.userId[idType] : undefined; } /** @@ -344,13 +315,12 @@ function getId(request, idType) { * @return Object OpenRTB request object */ function openRtbRequest(bidRequests, bidderRequest) { - const schain = bidRequests[0].schain; let openRtbRequest = { id: bidRequests[0].bidderRequestId, at: 1, imp: bidRequests.map(bidRequest => openRtbImpression(bidRequest)), site: openRtbSite(bidRequests[0], bidderRequest), - device: openRtbDevice(bidRequests[0]), + device: openRtbDevice(), badv: bidRequests[0].params.badv || [], bcat: bidRequests[0].params.bcat || [], ext: { @@ -359,10 +329,6 @@ function openRtbRequest(bidRequests, bidderRequest) { ats_envelope: bidRequests[0].params.lr_env, }; - if (schain) { - openRtbRequest.schain = schain; - } - populateOpenRtbGdpr(openRtbRequest, bidderRequest); return openRtbRequest; @@ -373,7 +339,6 @@ function openRtbRequest(bidRequests, bidderRequest) { * @return Object OpenRTB's 'imp' (impression) object */ function openRtbImpression(bidRequest) { - const gpid = deepAccess(bidRequest, 'ortb2Imp.ext.data.pbadslot'); const size = extractPlayerSize(bidRequest); const imp = { id: bidRequest.bidId, @@ -389,12 +354,12 @@ function openRtbImpression(bidRequest) { } }; - const mediaTypesParams = deepAccess(bidRequest, 'mediaTypes.video'); + const mediaTypesParams = utils.deepAccess(bidRequest, 'mediaTypes.video'); Object.keys(mediaTypesParams) .filter(param => includes(OPENRTB_VIDEO_BIDPARAMS, param)) .forEach(param => imp.video[param] = mediaTypesParams[param]); - const videoParams = deepAccess(bidRequest, 'params.video'); + const videoParams = utils.deepAccess(bidRequest, 'params.video'); Object.keys(videoParams) .filter(param => includes(OPENRTB_VIDEO_BIDPARAMS, param)) .forEach(param => imp.video[param] = videoParams[param]); @@ -407,9 +372,6 @@ function openRtbImpression(bidRequest) { imp.video.startdelay = DEFAULT_START_DELAY; imp.video.playbackmethod = [ DEFAULT_PLAYBACK_METHOD ]; } - if (gpid) { - imp.ext.gpid = gpid; - } return imp; } @@ -428,10 +390,10 @@ function getBidFloor(bidRequest, mediaType) { * @return [number, number] || null Player's width and height, or undefined otherwise. */ function extractPlayerSize(bidRequest) { - const sizeArr = deepAccess(bidRequest, 'mediaTypes.video.playerSize'); - if (isArrayOfNums(sizeArr, 2)) { + const sizeArr = utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize'); + if (utils.isArrayOfNums(sizeArr, 2)) { return sizeArr; - } else if (isArray(sizeArr) && isArrayOfNums(sizeArr[0], 2)) { + } else if (utils.isArray(sizeArr) && utils.isArrayOfNums(sizeArr[0], 2)) { return sizeArr[0]; } return null; @@ -445,8 +407,8 @@ function extractPlayerSize(bidRequest) { function openRtbSite(bidRequest, bidderRequest) { let result = {}; - const loc = parseUrl(deepAccess(bidderRequest, 'refererInfo.referer')); - if (!isEmpty(loc)) { + const loc = utils.parseUrl(utils.deepAccess(bidderRequest, 'refererInfo.referer')); + if (!utils.isEmpty(loc)) { result.page = `${loc.protocol}://${loc.hostname}${loc.pathname}`; } @@ -459,7 +421,7 @@ function openRtbSite(bidRequest, bidderRequest) { result.keywords = keywords.content; } - const siteParams = deepAccess(bidRequest, 'params.site'); + const siteParams = utils.deepAccess(bidRequest, 'params.site'); if (siteParams) { Object.keys(siteParams) .filter(param => includes(OPENRTB_VIDEO_SITEPARAMS, param)) @@ -471,12 +433,11 @@ function openRtbSite(bidRequest, bidderRequest) { /** * @return Object OpenRTB's 'device' object */ -function openRtbDevice(bidRequest) { - const deviceObj = { +function openRtbDevice() { + return { ua: navigator.userAgent, language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), }; - return deviceObj; } /** @@ -487,12 +448,12 @@ function openRtbDevice(bidRequest) { function populateOpenRtbGdpr(openRtbRequest, bidderRequest) { const gdpr = bidderRequest.gdprConsent; if (gdpr && 'gdprApplies' in gdpr) { - deepSetValue(openRtbRequest, 'regs.ext.gdpr', gdpr.gdprApplies ? 1 : 0); - deepSetValue(openRtbRequest, 'user.ext.consent', gdpr.consentString); + utils.deepSetValue(openRtbRequest, 'regs.ext.gdpr', gdpr.gdprApplies ? 1 : 0); + utils.deepSetValue(openRtbRequest, 'user.ext.consent', gdpr.consentString); } - const uspConsent = deepAccess(bidderRequest, 'uspConsent'); + const uspConsent = utils.deepAccess(bidderRequest, 'uspConsent'); if (uspConsent) { - deepSetValue(openRtbRequest, 'regs.ext.us_privacy', uspConsent); + utils.deepSetValue(openRtbRequest, 'regs.ext.us_privacy', uspConsent); } } @@ -525,8 +486,8 @@ function validateVideoParams(bid) { if (fieldPath.indexOf('video') === 0) { const valueFieldPath = 'params.' + fieldPath; const mediaFieldPath = 'mediaTypes.' + fieldPath; - const valueParams = deepAccess(bid, valueFieldPath); - const mediaTypesParams = deepAccess(bid, mediaFieldPath); + const valueParams = utils.deepAccess(bid, valueFieldPath); + const mediaTypesParams = utils.deepAccess(bid, mediaFieldPath); const hasValidValueParams = validateCb(valueParams); const hasValidMediaTypesParams = validateCb(mediaTypesParams); @@ -538,7 +499,7 @@ function validateVideoParams(bid) { } return valueParams || mediaTypesParams; } else { - const value = deepAccess(bid, fieldPath); + const value = utils.deepAccess(bid, fieldPath); if (!validateCb(value)) { errorCb(fieldPath, value, errorCbParam); } @@ -547,16 +508,16 @@ function validateVideoParams(bid) { } try { - validate('video.context', val => !isEmpty(val), paramRequired); + validate('video.context', val => !utils.isEmpty(val), paramRequired); - validate('params.placementId', val => !isEmpty(val), paramRequired); + validate('params.placementId', val => !utils.isEmpty(val), paramRequired); - validate('video.playerSize', val => isArrayOfNums(val, 2) || - (isArray(val) && val.every(v => isArrayOfNums(v, 2))), + validate('video.playerSize', val => utils.isArrayOfNums(val, 2) || + (utils.isArray(val) && val.every(v => utils.isArrayOfNums(v, 2))), paramInvalid, 'array of 2 integers, ex: [640,480] or [[640,480]]'); validate('video.mimes', val => isDefined(val), paramRequired); - validate('video.mimes', val => isArray(val) && val.every(v => isStr(v)), paramInvalid, + validate('video.mimes', val => utils.isArray(val) && val.every(v => utils.isStr(v)), paramInvalid, 'array of strings, ex: ["video/mp4"]'); const placement = validate('video.placement', val => isDefined(val), paramRequired); @@ -564,33 +525,33 @@ function validateVideoParams(bid) { if (placement === 1) { validate('video.startdelay', val => isDefined(val), (field, v) => paramRequired(field, v, 'placement == 1')); - validate('video.startdelay', val => isNumber(val), paramInvalid, 'number, ex: 5'); + validate('video.startdelay', val => utils.isNumber(val), paramInvalid, 'number, ex: 5'); } validate('video.protocols', val => isDefined(val), paramRequired); - validate('video.protocols', val => isArrayOfNums(val) && val.every(v => (v >= 1 && v <= 6)), + validate('video.protocols', val => utils.isArrayOfNums(val) && val.every(v => (v >= 1 && v <= 6)), paramInvalid, 'array of numbers, ex: [2,3]'); validate('video.api', val => isDefined(val), paramRequired); - validate('video.api', val => isArrayOfNums(val) && val.every(v => (v >= 1 && v <= 6)), + validate('video.api', val => utils.isArrayOfNums(val) && val.every(v => (v >= 1 && v <= 6)), paramInvalid, 'array of numbers, ex: [2,3]'); - validate('video.playbackmethod', val => !isDefined(val) || isArrayOfNums(val), paramInvalid, + validate('video.playbackmethod', val => !isDefined(val) || utils.isArrayOfNums(val), paramInvalid, 'array of integers, ex: [2,6]'); validate('video.maxduration', val => isDefined(val), paramRequired); - validate('video.maxduration', val => isInteger(val), paramInvalid); - validate('video.minduration', val => !isDefined(val) || isNumber(val), paramInvalid); - validate('video.skippable', val => !isDefined(val) || isBoolean(val), paramInvalid); - validate('video.skipafter', val => !isDefined(val) || isNumber(val), paramInvalid); - validate('video.pos', val => !isDefined(val) || isNumber(val), paramInvalid); - validate('params.badv', val => !isDefined(val) || isArray(val), paramInvalid, + validate('video.maxduration', val => utils.isInteger(val), paramInvalid); + validate('video.minduration', val => !isDefined(val) || utils.isNumber(val), paramInvalid); + validate('video.skippable', val => !isDefined(val) || utils.isBoolean(val), paramInvalid); + validate('video.skipafter', val => !isDefined(val) || utils.isNumber(val), paramInvalid); + validate('video.pos', val => !isDefined(val) || utils.isNumber(val), paramInvalid); + validate('params.badv', val => !isDefined(val) || utils.isArray(val), paramInvalid, 'array of strings, ex: ["ford.com","pepsi.com"]'); - validate('params.bcat', val => !isDefined(val) || isArray(val), paramInvalid, + validate('params.bcat', val => !isDefined(val) || utils.isArray(val), paramInvalid, 'array of strings, ex: ["IAB1-5","IAB1-6"]'); return true; } catch (e) { - logError(e.message); + utils.logError(e.message); return false; } } @@ -616,29 +577,3 @@ function shortcutProperty(extraCharacters, target, propertyName) { return charactersLeft; } - -/** - * Creates and returnes eids arr using createEidsArray from './userId/eids.js' module; - * @param {Object} openRtbRequest OpenRTB's request as a cource of userId. - * @return array of eids objects - */ -function getEids(bidRequest) { - if (deepAccess(bidRequest, 'userId')) { - return createEidsArray(bidRequest.userId) || []; - } -}; - -/** - * Check if top window can be accessed - * - * @return {boolean} true if can access top window otherwise false - */ -function canAccessTopWindow() { - try { - if (getWindowTop().location.href) { - return true; - } - } catch (error) { - return false; - } -} diff --git a/modules/yieldmoSyntheticInventoryModule.js b/modules/yieldmoSyntheticInventoryModule.js deleted file mode 100644 index bca778a7b43..00000000000 --- a/modules/yieldmoSyntheticInventoryModule.js +++ /dev/null @@ -1,46 +0,0 @@ -import { config } from '../src/config.js'; -import { isGptPubadsDefined } from '../src/utils.js'; - -export const MODULE_NAME = 'Yieldmo Synthetic Inventory Module'; - -export function init(config) { - validateConfig(config); - - if (!isGptPubadsDefined()) { - window.googletag = window.googletag || {}; - window.googletag.cmd = window.googletag.cmd || []; - } - - const googletag = window.googletag; - const containerName = 'ym_sim_container_' + config.placementId; - - googletag.cmd.push(() => { - if (window.document.body) { - googletagCmd(config, containerName, googletag); - } else { - window.document.addEventListener('DOMContentLoaded', () => googletagCmd(config, containerName, googletag)); - } - }); -} - -export function validateConfig(config) { - if (!('placementId' in config)) { - throw new Error(`${MODULE_NAME}: placementId required`); - } - if (!('adUnitPath' in config)) { - throw new Error(`${MODULE_NAME}: adUnitPath required`); - } -} - -function googletagCmd(config, containerName, googletag) { - const gamContainer = window.document.createElement('div'); - gamContainer.id = containerName; - window.document.body.appendChild(gamContainer); - googletag.defineSlot(config.adUnitPath, [1, 1], containerName) - .addService(googletag.pubads()) - .setTargeting('ym_sim_p_id', config.placementId); - googletag.enableServices(); - googletag.display(containerName); -} - -config.getConfig('yieldmo_synthetic_inventory', config => init(config.yieldmo_synthetic_inventory)); diff --git a/modules/yieldmoSyntheticInventoryModule.md b/modules/yieldmoSyntheticInventoryModule.md deleted file mode 100644 index dd6f0acf884..00000000000 --- a/modules/yieldmoSyntheticInventoryModule.md +++ /dev/null @@ -1,68 +0,0 @@ -# Yieldmo Synthetic Inventory Module - -## Overview - -This module enables publishers to set up Yieldmo Synthetic Outstream ads on their pages. - -If publishers will enable this module and provide placementId and Google Ad Manager ad unit path, this module will create a placement on the page and inject Yieldmo SDK into this placement. Publisher will then need to get a placement id from their Yieldmo account manager (accounts email) and setup corresponding ad units on the GAM ad server. - -## Integration - -Build the Yieldmo Synthetic Inventory Module into the Prebid.js package with: - -``` -gulp build --modules=yieldmoSyntheticInventoryModule,... -``` - -## Module Configuration - -```js -pbjs.que.push(function() { - pbjs.setConfig({ - yieldmo_synthetic_inventory: { - placementId: '1234567890', - adUnitPath: '/1234567/ad_unit_name_used_in_gam' - } - }); -}); -``` - -### Configuration Parameters - -|Name |Scope |Description | Example| Type -| :------------ | :------------ | :------------ | :------------ | :------------ | -|placementId | required | Yieldmo placement ID | '1234567890' | string -|adUnitPath | required | Google Ad Manager ad unit path | '/6355419/ad_unit_name_used_in_gam' | string - -### How to get ad unit path - -Ad unit path follows the format /network-code/[parent-ad-unit-code/.../]ad-unit-code, where: - -- network-code is a unique identifier for the Ad Manager network the ad unit belongs to -- parent-ad-unit-code are the codes of all parent ad units (only applies to non-top level ad units) -- ad-unit-code is the code for the ad unit to be displayed - -Note that all ad unit codes included in the ad unit path must adhere to the [formatting rules](https://support.google.com/admanager/answer/1628457#ad-unit-codes) specified by Ad Manager. - -Another and probably the easiest way to get an ad unit path is to get it from the google ad manager ad unit document header generated tag: - -```js -googletag.defineSlot('/1234567/ad_unit_name_used_in_gam', [1, 1], 'ad-container-id').addService(googletag.pubads()); -``` - -### How to get Yieldmo placement id - -Please reach out to your Yieldmo account's person or email to support@yieldmo.com - -### Google Ad Manager setup - -Yieldmo Synthetic Inventory Module is designed to be used along with Google Ad Manager. GAM should be set as usual, but there are a few requirements: - -- Ad unit size should be 1x1 -- Creative should NOT be served into a SafeFrame and also should have 1x1 size -- Synthetic Inventory Universal Tag should be used as 3rd party creative code -### Synthetic Inventory Universal Tag - -```js -
-``` \ No newline at end of file diff --git a/modules/yieldoneAnalyticsAdapter.js b/modules/yieldoneAnalyticsAdapter.js index cb13503365e..542c0917708 100644 --- a/modules/yieldoneAnalyticsAdapter.js +++ b/modules/yieldoneAnalyticsAdapter.js @@ -1,10 +1,10 @@ -import { isArray, deepClone } from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; import { targeting } from '../src/targeting.js'; import { auctionManager } from '../src/auctionManager.js'; +import * as utils from '../src/utils.js'; const ANALYTICS_CODE = 'yieldone'; const analyticsType = 'endpoint'; @@ -42,7 +42,7 @@ function makeAdUnitNameMap() { } function addAdUnitNameForArray(ar, map) { - if (isArray(ar)) { + if (utils.isArray(ar)) { ar.forEach((it) => { addAdUnitName(it, map) }); } } @@ -51,14 +51,14 @@ function addAdUnitName(params, map) { if (params.adUnitCode && map[params.adUnitCode]) { params.adUnitName = map[params.adUnitCode]; } - if (isArray(params.adUnits)) { + if (utils.isArray(params.adUnits)) { params.adUnits.forEach((adUnit) => { if (adUnit.code && map[adUnit.code]) { adUnit.name = map[adUnit.code]; } }); } - if (isArray(params.adUnitCodes)) { + if (utils.isArray(params.adUnitCodes)) { params.adUnitNames = params.adUnitCodes.map((code) => map[code]); } ['bids', 'bidderRequests', 'bidsReceived', 'noBids'].forEach((it) => { @@ -71,13 +71,13 @@ const yieldoneAnalytics = Object.assign(adapter({analyticsType}), { track({eventType, args = {}}) { if (eventType === CONSTANTS.EVENTS.BID_REQUESTED) { const reqBidderId = `${args.bidderCode}_${args.auctionId}`; - requestedBidders[reqBidderId] = deepClone(args); + requestedBidders[reqBidderId] = utils.deepClone(args); requestedBidders[reqBidderId].bids = []; args.bids.forEach((bid) => { requestedBids[`${bid.bidId}_${bid.auctionId}`] = bid; }); } - if (eventType === CONSTANTS.EVENTS.BID_TIMEOUT && isArray(args)) { + if (eventType === CONSTANTS.EVENTS.BID_TIMEOUT && utils.isArray(args)) { const eventsStorage = yieldoneAnalytics.eventsStorage; const reqBidders = {}; args.forEach((bid) => { diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js index 334de9eb3fa..73c3d2e8808 100644 --- a/modules/yieldoneBidAdapter.js +++ b/modules/yieldoneBidAdapter.js @@ -1,4 +1,4 @@ -import {deepAccess, isEmpty, isStr, logWarn, parseSizesInput} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { Renderer } from '../src/Renderer.js'; @@ -11,8 +11,6 @@ const VIDEO_PLAYER_URL = 'https://img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/d const CMER_PLAYER_URL = 'https://an.cmertv.com/hb/renderer/cmertv-video-yone-prebid.min.js'; const VIEWABLE_PERCENTAGE_URL = 'https://img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/prebid-adformat-config.js'; -const DEFAULT_VIDEO_SIZE = {w: 640, h: 360}; - export const spec = { code: BIDDER_CODE, aliases: ['y1'], @@ -42,32 +40,24 @@ export const spec = { t: 'i' }; - const mediaType = getMediaType(bidRequest); - switch (mediaType) { - case BANNER: - payload.sz = getBannerSizes(bidRequest); - break; - case VIDEO: - const videoSize = getVideoSize(bidRequest); - payload.w = videoSize.w; - payload.h = videoSize.h; - break; - default: - break; + const videoMediaType = utils.deepAccess(bidRequest, 'mediaTypes.video'); + if ((utils.isEmpty(bidRequest.mediaType) && utils.isEmpty(bidRequest.mediaTypes)) || + (bidRequest.mediaType === BANNER || (bidRequest.mediaTypes && bidRequest.mediaTypes[BANNER]))) { + const sizes = utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes; + payload.sz = utils.parseSizesInput(sizes).join(','); + } else if (bidRequest.mediaType === VIDEO || videoMediaType) { + const sizes = utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize') || bidRequest.sizes; + const size = utils.parseSizesInput(sizes)[0]; + payload.w = size.split('x')[0]; + payload.h = size.split('x')[1]; } // LiveRampID - const idlEnv = deepAccess(bidRequest, 'userId.idl_env'); - if (isStr(idlEnv) && !isEmpty(idlEnv)) { + const idlEnv = utils.deepAccess(bidRequest, 'userId.idl_env'); + if (utils.isStr(idlEnv) && !utils.isEmpty(idlEnv)) { payload.lr_env = idlEnv; } - // IMID - const imuid = deepAccess(bidRequest, 'userId.imuid'); - if (isStr(imuid) && !isEmpty(imuid)) { - payload.imuid = imuid; - } - return { method: 'GET', url: ENDPOINT_URL, @@ -177,106 +167,6 @@ export const spec = { }, } -/** - * NOTE: server side does not yet support multiple formats. - * @param {Object} bidRequest - - * @param {boolean} [enabledOldFormat = true] - default: `true`. - * @return {string|null} - `"banner"` or `"video"` or `null`. - */ -function getMediaType(bidRequest, enabledOldFormat = true) { - let hasBannerType = Boolean(deepAccess(bidRequest, 'mediaTypes.banner')); - let hasVideoType = Boolean(deepAccess(bidRequest, 'mediaTypes.video')); - - if (enabledOldFormat) { - hasBannerType = hasBannerType || bidRequest.mediaType === BANNER || - (isEmpty(bidRequest.mediaTypes) && isEmpty(bidRequest.mediaType)); - hasVideoType = hasVideoType || bidRequest.mediaType === VIDEO; - } - - if (hasBannerType && hasVideoType) { - const playerParams = deepAccess(bidRequest, 'params.playerParams') - if (playerParams) { - return VIDEO; - } else { - return BANNER; - } - } else if (hasBannerType) { - return BANNER; - } else if (hasVideoType) { - return VIDEO; - } - - return null; -} - -/** - * NOTE: - * If `mediaTypes.banner` exists, then `mediaTypes.banner.sizes` must also exist. - * The reason for this is that Prebid.js will perform the verification and - * if `mediaTypes.banner.sizes` is inappropriate, it will delete the entire `mediaTypes.banner`. - * @param {Object} bidRequest - - * @param {Object} bidRequest.banner - - * @param {Array} bidRequest.banner.sizes - - * @param {boolean} [enabledOldFormat = true] - default: `true`. - * @return {string} - strings like `"300x250"` or `"300x250,728x90"`. - */ -function getBannerSizes(bidRequest, enabledOldFormat = true) { - let sizes = deepAccess(bidRequest, 'mediaTypes.banner.sizes'); - - if (enabledOldFormat) { - sizes = sizes || bidRequest.sizes; - } - - return parseSizesInput(sizes).join(','); -} - -/** - * @param {Object} bidRequest - - * @param {boolean} [enabledOldFormat = true] - default: `true`. - * @param {boolean} [enabledFlux = true] - default: `true`. - * @return {{w: number, h: number}} - - */ -function getVideoSize(bidRequest, enabledOldFormat = true, enabledFlux = true) { - /** - * @param {Array | Array>} sizes - - * @return {{w: number, h: number} | null} - - */ - const _getPlayerSize = (sizes) => { - let result = null; - - const size = parseSizesInput(sizes)[0]; - if (isEmpty(size)) { - return result; - } - - const splited = size.split('x'); - const sizeObj = {w: parseInt(splited[0], 10), h: parseInt(splited[1], 10)}; - const _isValidPlayerSize = !(isEmpty(sizeObj)) && (isFinite(sizeObj.w) && isFinite(sizeObj.h)); - if (!_isValidPlayerSize) { - return result; - } - - result = sizeObj; - return result; - } - - let playerSize = _getPlayerSize(deepAccess(bidRequest, 'mediaTypes.video.playerSize')); - - if (enabledOldFormat) { - playerSize = playerSize || _getPlayerSize(bidRequest.sizes); - } - - if (enabledFlux) { - // NOTE: `video.playerSize` in Flux is always [1,1]. - if (playerSize && (playerSize.w === 1 && playerSize.h === 1)) { - // NOTE: `params.playerSize` is a specific object to support `FLUX`. - playerSize = _getPlayerSize(deepAccess(bidRequest, 'params.playerSize')); - } - } - - return playerSize || DEFAULT_VIDEO_SIZE; -} - function newRenderer(response) { const renderer = Renderer.install({ id: response.uid, @@ -287,7 +177,7 @@ function newRenderer(response) { try { renderer.setRender(outstreamRender); } catch (err) { - logWarn('Prebid Error calling setRender on newRenderer', err); + utils.logWarn('Prebid Error calling setRender on newRenderer', err); } return renderer; @@ -309,7 +199,7 @@ function newCmerRenderer(response) { try { renderer.setRender(cmerRender); } catch (err) { - logWarn('Prebid Error calling setRender on newRenderer', err); + utils.logWarn('Prebid Error calling setRender on newRenderer', err); } return renderer; diff --git a/modules/yuktamediaAnalyticsAdapter.js b/modules/yuktamediaAnalyticsAdapter.js index 6872820dd48..2ef2d251ace 100644 --- a/modules/yuktamediaAnalyticsAdapter.js +++ b/modules/yuktamediaAnalyticsAdapter.js @@ -1,11 +1,11 @@ -import {buildUrl, generateUUID, getWindowLocation, logError, logInfo, parseSizesInput, parseUrl} from '../src/utils.js'; -import {ajax} from '../src/ajax.js'; +import { ajax } from '../src/ajax.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; -import {getStorageManager} from '../src/storageManager.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import {includes as strIncludes} from '../src/polyfill.js'; +import * as utils from '../src/utils.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { getRefererInfo } from '../src/refererDetection.js'; +import strIncludes from 'core-js-pure/features/string/includes.js'; const storage = getStorageManager(); const yuktamediaAnalyticsVersion = 'v3.1.0'; @@ -17,7 +17,7 @@ const events = { }; const localStoragePrefix = 'yuktamediaAnalytics_'; const utmTags = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']; -const location = getWindowLocation(); +const location = utils.getWindowLocation(); const referer = getRefererInfo().referer; const _pageInfo = { userAgent: window.navigator.userAgent, @@ -25,13 +25,13 @@ const _pageInfo = { language: window.navigator.language, screenWidth: window.screen.width, screenHeight: window.screen.height, - pageViewId: generateUUID(), + pageViewId: utils.generateUUID(), host: location.host, path: location.pathname, search: location.search, hash: location.hash, referer: referer, - refererDomain: parseUrl(referer).host, + refererDomain: utils.parseUrl(referer).host, yuktamediaAnalyticsVersion: yuktamediaAnalyticsVersion, prebidVersion: $$PREBID_GLOBAL$$.version }; @@ -53,7 +53,7 @@ function isNavigatorSendBeaconSupported() { function updateSessionId() { if (isSessionIdTimeoutExpired()) { - let newSessionId = generateUUID(); + let newSessionId = utils.generateUUID(); storage.setDataInLocalStorage(localStoragePrefix.concat('session_id'), newSessionId); } initOptions.sessionId = getSessionId(); @@ -80,7 +80,7 @@ function isUtmTimeoutExpired() { function send(data, status) { data.initOptions = Object.assign(_pageInfo, initOptions); - const yuktamediaAnalyticsRequestUrl = buildUrl({ + const yuktamediaAnalyticsRequestUrl = utils.buildUrl({ protocol: 'https', hostname: 'analytics-prebid.yuktamedia.com', pathname: '/api/bids' @@ -97,13 +97,13 @@ var yuktamediaAnalyticsAdapter = Object.assign(adapter({ analyticsType: 'endpoin if (typeof args !== 'undefined') { switch (eventType) { case CONSTANTS.EVENTS.AUCTION_INIT: - logInfo(localStoragePrefix + 'AUCTION_INIT:', JSON.stringify(args)); + utils.logInfo(localStoragePrefix + 'AUCTION_INIT:', JSON.stringify(args)); if (typeof args.auctionId !== 'undefined' && args.auctionId.length) { events.auctions[args.auctionId] = { bids: {} }; } break; case CONSTANTS.EVENTS.BID_REQUESTED: - logInfo(localStoragePrefix + 'BID_REQUESTED:', JSON.stringify(args)); + utils.logInfo(localStoragePrefix + 'BID_REQUESTED:', JSON.stringify(args)); if (typeof args.auctionId !== 'undefined' && args.auctionId.length) { if (typeof events.auctions[args.auctionId] === 'undefined') { events.auctions[args.auctionId] = { bids: {} }; @@ -113,7 +113,7 @@ var yuktamediaAnalyticsAdapter = Object.assign(adapter({ analyticsType: 'endpoin events.auctions[args.auctionId]['bids'][bidRequest.bidId] = { bidder: bidRequest.bidder, adUnit: bidRequest.adUnitCode, - sizes: parseSizesInput(bidRequest.sizes).toString(), + sizes: utils.parseSizesInput(bidRequest.sizes).toString(), isBid: false, won: false, timeout: false, @@ -132,7 +132,7 @@ var yuktamediaAnalyticsAdapter = Object.assign(adapter({ analyticsType: 'endpoin } break; case CONSTANTS.EVENTS.BID_RESPONSE: - logInfo(localStoragePrefix + 'BID_RESPONSE:', JSON.stringify(args)); + utils.logInfo(localStoragePrefix + 'BID_RESPONSE:', JSON.stringify(args)); if (typeof args.auctionId !== 'undefined' && args.auctionId.length) { if (typeof events.auctions[args.auctionId] === 'undefined') { events.auctions[args.auctionId] = { bids: {} }; @@ -162,7 +162,7 @@ var yuktamediaAnalyticsAdapter = Object.assign(adapter({ analyticsType: 'endpoin } break; case CONSTANTS.EVENTS.NO_BID: - logInfo(localStoragePrefix + 'NO_BID:', JSON.stringify(args)); + utils.logInfo(localStoragePrefix + 'NO_BID:', JSON.stringify(args)); if (typeof args.auctionId !== 'undefined' && args.auctionId.length) { if (typeof events.auctions[args.auctionId] === 'undefined') { events.auctions[args.auctionId] = { bids: {} }; @@ -173,7 +173,7 @@ var yuktamediaAnalyticsAdapter = Object.assign(adapter({ analyticsType: 'endpoin } break; case CONSTANTS.EVENTS.BID_WON: - logInfo(localStoragePrefix + 'BID_WON:', JSON.stringify(args)); + utils.logInfo(localStoragePrefix + 'BID_WON:', JSON.stringify(args)); if (typeof initOptions.enableSession !== 'undefined' && initOptions.enableSession) { updateSessionId(); } @@ -189,7 +189,7 @@ var yuktamediaAnalyticsAdapter = Object.assign(adapter({ analyticsType: 'endpoin } break; case CONSTANTS.EVENTS.BID_TIMEOUT: - logInfo(localStoragePrefix + 'BID_TIMEOUT:', JSON.stringify(args)); + utils.logInfo(localStoragePrefix + 'BID_TIMEOUT:', JSON.stringify(args)); if (args.length) { args.forEach(timeout => { if (typeof timeout !== 'undefined' && typeof timeout.auctionId !== 'undefined' && timeout.auctionId.length) { @@ -205,7 +205,7 @@ var yuktamediaAnalyticsAdapter = Object.assign(adapter({ analyticsType: 'endpoin } break; case CONSTANTS.EVENTS.AUCTION_END: - logInfo(localStoragePrefix + 'AUCTION_END:', JSON.stringify(args)); + utils.logInfo(localStoragePrefix + 'AUCTION_END:', JSON.stringify(args)); if (typeof initOptions.enableSession !== 'undefined' && initOptions.enableSession) { updateSessionId(); } @@ -249,7 +249,7 @@ yuktamediaAnalyticsAdapter.originEnableAnalytics = yuktamediaAnalyticsAdapter.en yuktamediaAnalyticsAdapter.enableAnalytics = function (config) { if (config && config.options) { if (typeof config.options.pubId === 'undefined' || typeof config.options.pubKey === 'undefined') { - logError('Need pubId and pubKey to log auction results. Please contact a YuktaMedia representative if you do not know your pubId and pubKey.'); + utils.logError('Need pubId and pubKey to log auction results. Please contact a YuktaMedia representative if you do not know your pubId and pubKey.'); return; } } diff --git a/modules/zeotapIdPlusIdSystem.js b/modules/zeotapIdPlusIdSystem.js index 3437928df4b..8f26cc827d6 100644 --- a/modules/zeotapIdPlusIdSystem.js +++ b/modules/zeotapIdPlusIdSystem.js @@ -4,7 +4,7 @@ * @module modules/zeotapIdPlusIdSystem * @requires module:modules/userId */ -import { isStr, isPlainObject } from '../src/utils.js'; +import * as utils from '../src/utils.js' import {submodule} from '../src/hook.js'; import { getStorageManager } from '../src/storageManager.js'; @@ -21,7 +21,7 @@ function readFromLocalStorage() { } export function getStorage() { - return getStorageManager({gvlid: ZEOTAP_VENDOR_ID, moduleName: ZEOTAP_MODULE_NAME}); + return getStorageManager(ZEOTAP_VENDOR_ID, ZEOTAP_MODULE_NAME); } export const storage = getStorage(); @@ -45,7 +45,7 @@ export const zeotapIdPlusSubmodule = { * @return { Object | string | undefined } */ decode(value) { - const id = value ? isStr(value) ? value : isPlainObject(value) ? value.id : undefined : undefined; + const id = value ? utils.isStr(value) ? value : utils.isPlainObject(value) ? value.id : undefined : undefined; return id ? { 'IDP': JSON.parse(atob(id)) } : undefined; diff --git a/modules/zetaBidAdapter.js b/modules/zetaBidAdapter.js index 27650888677..c6ce7e857ba 100644 --- a/modules/zetaBidAdapter.js +++ b/modules/zetaBidAdapter.js @@ -1,4 +1,4 @@ -import { logWarn } from '../src/utils.js'; +import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import {BANNER} from '../src/mediaTypes.js'; const BIDDER_CODE = 'zeta_global'; @@ -24,30 +24,30 @@ export const spec = { if (!(bid && bid.bidId && bid.params)) { - logWarn('Invalid bid request - missing required bid data'); + utils.logWarn('Invalid bid request - missing required bid data'); return false; } if (!(bid.params.user && bid.params.user.buyeruid)) { - logWarn('Invalid bid request - missing required user data'); + utils.logWarn('Invalid bid request - missing required user data'); return false; } if (!(bid.params.device && bid.params.device.ip)) { - logWarn('Invalid bid request - missing required device data'); + utils.logWarn('Invalid bid request - missing required device data'); return false; } if (!(bid.params.device.geo && bid.params.device.geo.country)) { - logWarn('Invalid bid request - missing required geo data'); + utils.logWarn('Invalid bid request - missing required geo data'); return false; } if (!bid.params.definerId) { - logWarn('Invalid bid request - missing required definer data'); + utils.logWarn('Invalid bid request - missing required definer data'); return false; } diff --git a/modules/zetaSspBidAdapter.md b/modules/zetaSspBidAdapter.md index 00d8663586c..d2950bce6b9 100644 --- a/modules/zetaSspBidAdapter.md +++ b/modules/zetaSspBidAdapter.md @@ -10,7 +10,7 @@ Maintainer: miakovlev@zetaglobal.com Module that connects to Zeta's SSP -# Banner Ad Unit: For Publishers +# Test Parameters ``` var adUnits = [ { @@ -40,35 +40,3 @@ Module that connects to Zeta's SSP } ]; ``` - -# Video Ad Unit: For Publishers -``` - var adUnits = [ - { - mediaTypes: { - video: { - playerSize: [640, 480], - context: 'outstream' - } - }, - bids: [ - { - bidder: 'zeta_global_ssp', - bidId: 12345, - params: { - placement: 12345, - user: { - uid: 12345, - buyeruid: 12345 - }, - tags: { - someTag: 123, - sid: 'publisherId' - }, - test: 1 - } - } - ] - } - ]; -``` diff --git a/modules/zeta_global_sspAnalyticsAdapter.js b/modules/zeta_global_sspAnalyticsAdapter.js deleted file mode 100644 index 906e6e19cc2..00000000000 --- a/modules/zeta_global_sspAnalyticsAdapter.js +++ /dev/null @@ -1,97 +0,0 @@ -import { logInfo, logError } from '../src/utils.js'; -import { ajax } from '../src/ajax.js'; -import adapterManager from '../src/adapterManager.js'; -import CONSTANTS from '../src/constants.json'; - -import adapter from '../src/AnalyticsAdapter.js'; - -const ZETA_GVL_ID = 833; -const ADAPTER_CODE = 'zeta_global_ssp'; -const BASE_URL = 'https://ssp.disqus.com/prebid/event'; -const LOG_PREFIX = 'ZetaGlobalSsp-Analytics: '; - -/// /////////// VARIABLES //////////////////////////////////// - -let publisherId; // int - -/// /////////// HELPER FUNCTIONS ///////////////////////////// - -function sendEvent(eventType, event) { - ajax( - BASE_URL + '/' + eventType, - null, - JSON.stringify(event) - ); -} - -/// /////////// ADAPTER EVENT HANDLER FUNCTIONS ////////////// - -function adRenderSucceededHandler(args) { - let eventType = CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED - logInfo(LOG_PREFIX + 'handle ' + eventType + ' event'); - - sendEvent(eventType, args); -} - -function auctionEndHandler(args) { - let eventType = CONSTANTS.EVENTS.AUCTION_END; - logInfo(LOG_PREFIX + 'handle ' + eventType + ' event'); - - sendEvent(eventType, args); -} - -/// /////////// ADAPTER DEFINITION /////////////////////////// - -let baseAdapter = adapter({ analyticsType: 'endpoint' }); -let zetaAdapter = Object.assign({}, baseAdapter, { - - enableAnalytics(config = {}) { - let error = false; - - if (typeof config.options === 'object') { - if (config.options.sid) { - publisherId = Number(config.options.sid); - } - } else { - logError(LOG_PREFIX + 'Config not found'); - error = true; - } - - if (!publisherId) { - logError(LOG_PREFIX + 'Missing sid (publisher id)'); - error = true; - } - - if (error) { - logError(LOG_PREFIX + 'Analytics is disabled due to error(s)'); - } else { - baseAdapter.enableAnalytics.call(this, config); - } - }, - - disableAnalytics() { - publisherId = undefined; - baseAdapter.disableAnalytics.apply(this, arguments); - }, - - track({ eventType, args }) { - switch (eventType) { - case CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED: - adRenderSucceededHandler(args); - break; - case CONSTANTS.EVENTS.AUCTION_END: - auctionEndHandler(args); - break; - } - } -}); - -/// /////////// ADAPTER REGISTRATION ///////////////////////// - -adapterManager.registerAnalyticsAdapter({ - adapter: zetaAdapter, - code: ADAPTER_CODE, - gvlid: ZETA_GVL_ID -}); - -export default zetaAdapter; diff --git a/modules/zeta_global_sspAnalyticsAdapter.md b/modules/zeta_global_sspAnalyticsAdapter.md deleted file mode 100644 index d586d0069b1..00000000000 --- a/modules/zeta_global_sspAnalyticsAdapter.md +++ /dev/null @@ -1,24 +0,0 @@ -# Zeta Global SSP Analytics Adapter - -## Overview - -Module Name: Zeta Global SSP Analytics Adapter\ -Module Type: Analytics Adapter\ -Maintainer: abermanov@zetaglobal.com - -## Description - -Analytics Adapter which sends auctionEnd and adRenderSucceeded events to Zeta Global SSP analytics endpoints - -## How to configure -``` -pbjs.enableAnalytics({ - provider: 'zeta_global_ssp', - options: { - sid: 111, - tags: { - ... - } - } -}); -``` diff --git a/modules/zeta_global_sspBidAdapter.js b/modules/zeta_global_sspBidAdapter.js index 87fdbe1396f..4d5966e03e9 100644 --- a/modules/zeta_global_sspBidAdapter.js +++ b/modules/zeta_global_sspBidAdapter.js @@ -1,6 +1,6 @@ -import {deepAccess, deepSetValue, isArray, isBoolean, isNumber, isStr, logWarn} from '../src/utils.js'; +import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import {BANNER} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; const BIDDER_CODE = 'zeta_global_ssp'; @@ -11,36 +11,9 @@ const DEFAULT_CUR = 'USD'; const TTL = 200; const NET_REV = true; -const VIDEO_REGEX = new RegExp(/VAST\s+version/); - -const DATA_TYPES = { - 'NUMBER': 'number', - 'STRING': 'string', - 'BOOLEAN': 'boolean', - 'ARRAY': 'array', - 'OBJECT': 'object' -}; -const VIDEO_CUSTOM_PARAMS = { - 'mimes': DATA_TYPES.ARRAY, - 'minduration': DATA_TYPES.NUMBER, - 'maxduration': DATA_TYPES.NUMBER, - 'startdelay': DATA_TYPES.NUMBER, - 'playbackmethod': DATA_TYPES.ARRAY, - 'api': DATA_TYPES.ARRAY, - 'protocols': DATA_TYPES.ARRAY, - 'w': DATA_TYPES.NUMBER, - 'h': DATA_TYPES.NUMBER, - 'battr': DATA_TYPES.ARRAY, - 'linearity': DATA_TYPES.NUMBER, - 'placement': DATA_TYPES.NUMBER, - 'minbitrate': DATA_TYPES.NUMBER, - 'maxbitrate': DATA_TYPES.NUMBER, - 'skip': DATA_TYPES.NUMBER -} - export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO], + supportedMediaTypes: [BANNER], /** * Determines whether or not the given bid request is valid. @@ -53,7 +26,7 @@ export const spec = { if (!(bid && bid.bidId && bid.params)) { - logWarn('Invalid bid request - missing required bid data'); + utils.logWarn('Invalid bid request - missing required bid data'); return false; } return true; @@ -72,23 +45,9 @@ export const spec = { const params = request.params; const impData = { id: request.bidId, - secure: secure + secure: secure, + banner: buildBanner(request) }; - if (request.mediaTypes) { - for (const mediaType in request.mediaTypes) { - switch (mediaType) { - case BANNER: - impData.banner = buildBanner(request); - break; - case VIDEO: - impData.video = buildVideo(request); - break; - } - } - } - if (!impData.banner && !impData.video) { - impData.banner = buildBanner(request); - } const fpd = config.getLegacyFpd(config.getConfig('ortb2')) || {}; let payload = { id: bidderRequest.auctionId, @@ -108,7 +67,8 @@ export const spec = { payload.site.domain = config.getConfig('publisherDomain') || getDomainFromURL(payload.site.page); payload.device.ua = navigator.userAgent; - payload.device.language = navigator.language; + payload.device.devicetype = isMobile() ? 1 : isConnectedTV() ? 3 : 2; + payload.site.mobile = payload.device.devicetype === 1 ? 1 : 0; if (params.test) { payload.test = params.test; @@ -116,13 +76,13 @@ export const spec = { // Attaching GDPR Consent Params if (bidderRequest && bidderRequest.gdprConsent) { - deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(payload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + utils.deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + utils.deepSetValue(payload, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); } // CCPA if (bidderRequest && bidderRequest.uspConsent) { - deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); + utils.deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); } provideEids(request, payload); @@ -162,7 +122,6 @@ export const spec = { advertiserDomains: zetaBid.adomain }; } - provideMediaType(zetaBid, bid); bidResponses.push(bid); }) }) @@ -219,52 +178,9 @@ function buildBanner(request) { }; } -function buildVideo(request) { - let video = {}; - const videoParams = deepAccess(request, 'mediaTypes.video', {}); - for (const key in VIDEO_CUSTOM_PARAMS) { - if (videoParams.hasOwnProperty(key)) { - video[key] = checkParamDataType(key, videoParams[key], VIDEO_CUSTOM_PARAMS[key]); - } - } - if (videoParams.playerSize) { - if (isArray(videoParams.playerSize[0])) { - video.w = parseInt(videoParams.playerSize[0][0], 10); - video.h = parseInt(videoParams.playerSize[0][1], 10); - } else if (isNumber(videoParams.playerSize[0])) { - video.w = parseInt(videoParams.playerSize[0], 10); - video.h = parseInt(videoParams.playerSize[1], 10); - } - } - return video; -} - -function checkParamDataType(key, value, datatype) { - let functionToExecute; - switch (datatype) { - case DATA_TYPES.BOOLEAN: - functionToExecute = isBoolean; - break; - case DATA_TYPES.NUMBER: - functionToExecute = isNumber; - break; - case DATA_TYPES.STRING: - functionToExecute = isStr; - break; - case DATA_TYPES.ARRAY: - functionToExecute = isArray; - break; - } - if (functionToExecute(value)) { - return value; - } - logWarn('Ignoring param key: ' + key + ', expects ' + datatype + ', found ' + typeof value); - return undefined; -} - function provideEids(request, payload) { if (Array.isArray(request.userIdAsEids) && request.userIdAsEids.length > 0) { - deepSetValue(payload, 'user.ext.eids', request.userIdAsEids); + utils.deepSetValue(payload, 'user.ext.eids', request.userIdAsEids); } } @@ -278,22 +194,12 @@ function getDomainFromURL(url) { return hostname; } -function provideMediaType(zetaBid, bid) { - if (zetaBid.ext && zetaBid.ext.bidtype) { - if (zetaBid.ext.bidtype === VIDEO) { - bid.mediaType = VIDEO; - bid.vastXml = bid.ad; - } else { - bid.mediaType = BANNER; - } - } else { - if (VIDEO_REGEX.test(bid.ad)) { - bid.mediaType = VIDEO; - bid.vastXml = bid.ad; - } else { - bid.mediaType = BANNER; - } - } +function isMobile() { + return /(ios|ipod|ipad|iphone|android)/i.test(navigator.userAgent); +} + +function isConnectedTV() { + return /(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i.test(navigator.userAgent); } registerBidder(spec); diff --git a/package-lock.json b/package-lock.json index c5797787eb0..50296a6ae96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,25687 +1,2187 @@ { "name": "prebid.js", - "version": "6.24.0-pre", - "lockfileVersion": 2, + "version": "5.3.0-pre", + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "prebid.js", - "version": "6.20.0-pre", - "license": "Apache-2.0", - "dependencies": { - "babel-plugin-transform-object-assign": "^6.22.0", - "core-js": "^3.13.0", - "core-js-pure": "^3.13.0", - "criteo-direct-rsa-validate": "^1.1.0", - "crypto-js": "^3.3.0", - "dlv": "1.1.3", - "dset": "2.0.1", - "express": "^4.15.4", - "fun-hooks": "^0.9.9", - "just-clone": "^1.0.2", - "live-connect-js": "2.3.1" - }, - "devDependencies": { - "@babel/core": "^7.16.7", - "@babel/eslint-parser": "^7.16.5", - "@babel/preset-env": "^7.16.8", - "@jsdevtools/coverage-istanbul-loader": "^3.0.3", - "@wdio/browserstack-service": "^7.16.0", - "@wdio/cli": "^7.5.2", - "@wdio/concise-reporter": "^7.5.2", - "@wdio/local-runner": "^7.5.2", - "@wdio/mocha-framework": "^7.5.2", - "@wdio/spec-reporter": "^7.19.0", - "@wdio/sync": "^7.5.2", - "ajv": "6.12.3", - "assert": "^2.0.0", - "babel-loader": "^8.0.5", - "babel-register": "^6.26.0", - "body-parser": "^1.19.0", - "chai": "^4.2.0", - "coveralls": "^3.1.0", - "deep-equal": "^2.0.3", - "documentation": "^13.2.5", - "es5-shim": "^4.5.14", - "eslint": "^7.27.0", - "eslint-config-standard": "^10.2.1", - "eslint-plugin-import": "^2.20.2", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prebid": "file:./plugins/eslint", - "eslint-plugin-promise": "^5.1.0", - "eslint-plugin-standard": "^3.0.1", - "execa": "^1.0.0", - "faker": "^5.5.3", - "fs.extra": "^1.3.2", - "gulp": "^4.0.0", - "gulp-clean": "^0.3.2", - "gulp-concat": "^2.6.0", - "gulp-connect": "^5.7.0", - "gulp-eslint": "^4.0.0", - "gulp-footer": "^2.0.2", - "gulp-header": "^2.0.9", - "gulp-if": "^3.0.0", - "gulp-js-escape": "^1.0.1", - "gulp-replace": "^1.0.0", - "gulp-shell": "^0.8.0", - "gulp-sourcemaps": "^3.0.0", - "gulp-terser": "^2.0.1", - "gulp-util": "^3.0.0", - "is-docker": "^2.2.1", - "istanbul": "^0.4.5", - "karma": "^6.3.2", - "karma-babel-preprocessor": "^8.0.1", - "karma-browserstack-launcher": "1.4.0", - "karma-chai": "^0.1.0", - "karma-chrome-launcher": "^3.1.0", - "karma-coverage": "^2.0.1", - "karma-coverage-istanbul-reporter": "^3.0.3", - "karma-es5-shim": "^0.0.4", - "karma-firefox-launcher": "^2.1.0", - "karma-ie-launcher": "^1.0.0", - "karma-mocha": "^2.0.1", - "karma-mocha-reporter": "^2.2.5", - "karma-opera-launcher": "^1.0.0", - "karma-safari-launcher": "^1.0.0", - "karma-script-launcher": "^1.0.0", - "karma-sinon": "^1.0.5", - "karma-sourcemap-loader": "^0.3.7", - "karma-spec-reporter": "^0.0.32", - "karma-webpack": "^5.0.0", - "lodash": "^4.17.21", - "mocha": "^5.0.0", - "morgan": "^1.10.0", - "opn": "^5.4.0", - "resolve-from": "^5.0.0", - "sinon": "^4.1.3", - "through2": "^4.0.2", - "url": "^0.11.0", - "url-parse": "^1.0.5", - "webdriverio": "^7.6.1", - "webpack": "^5.70.0", - "webpack-bundle-analyzer": "^4.5.0", - "webpack-stream": "^7.0.0", - "yargs": "^1.3.1" - }, - "engines": { - "node": ">=8.9.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.0" - }, - "engines": { - "node": ">=6.0.0" + "requires": { + "@babel/highlight": "7.14.5" } }, - "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.16.7" + "@babel/compat-data": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", + "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", + "dev": true + }, + "@babel/core": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz", + "integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.14.5", + "@babel/generator": "7.14.5", + "@babel/helper-compilation-targets": "7.14.5", + "@babel/helper-module-transforms": "7.14.5", + "@babel/helpers": "7.14.6", + "@babel/parser": "7.14.7", + "@babel/template": "7.14.5", + "@babel/traverse": "7.14.7", + "@babel/types": "7.14.5", + "convert-source-map": "1.8.0", + "debug": "4.3.1", + "gensync": "1.0.0-beta.2", + "json5": "2.2.0", + "semver": "6.3.0", + "source-map": "0.5.7" }, - "engines": { - "node": ">=6.9.0" + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } } }, - "node_modules/@babel/compat-data": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", - "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", + "@babel/generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz", + "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", "dev": true, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/types": "7.14.5", + "jsesc": "2.5.2", + "source-map": "0.5.7" } }, - "node_modules/@babel/core": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", - "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", + "@babel/helper-annotate-as-pure": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", + "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.3", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "requires": { + "@babel/types": "7.14.5" } }, - "node_modules/@babel/eslint-parser": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.17.0.tgz", - "integrity": "sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA==", + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", + "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", "dev": true, - "dependencies": { - "eslint-scope": "^5.1.1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.11.0", - "eslint": "^7.5.0 || ^8.0.0" + "requires": { + "@babel/helper-explode-assignable-expression": "7.14.5", + "@babel/types": "7.14.5" } }, - "node_modules/@babel/generator": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", - "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", + "@babel/helper-compilation-targets": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", + "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", "dev": true, - "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/compat-data": "7.14.7", + "@babel/helper-validator-option": "7.14.5", + "browserslist": "4.16.6", + "semver": "6.3.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", - "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "@babel/helper-create-class-features-plugin": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz", + "integrity": "sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-annotate-as-pure": "7.14.5", + "@babel/helper-function-name": "7.14.5", + "@babel/helper-member-expression-to-functions": "7.14.7", + "@babel/helper-optimise-call-expression": "7.14.5", + "@babel/helper-replace-supers": "7.14.5", + "@babel/helper-split-export-declaration": "7.14.5" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", - "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "@babel/helper-create-regexp-features-plugin": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", + "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", "dev": true, - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-annotate-as-pure": "7.14.5", + "regexpu-core": "4.7.1" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", - "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", + "@babel/helper-define-polyfill-provider": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz", + "integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==", "dev": true, - "dependencies": { - "@babel/compat-data": "^7.16.4", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-compilation-targets": "7.14.5", + "@babel/helper-module-imports": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5", + "@babel/traverse": "7.14.7", + "debug": "4.3.1", + "lodash.debounce": "4.0.8", + "resolve": "1.20.0", + "semver": "6.3.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz", - "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==", + "@babel/helper-explode-assignable-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", + "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "requires": { + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", - "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", + "@babel/helper-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", + "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "regexpu-core": "^5.0.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "requires": { + "@babel/helper-get-function-arity": "7.14.5", + "@babel/template": "7.14.5", + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", - "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "@babel/helper-get-function-arity": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", + "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" + "requires": { + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "@babel/helper-hoist-variables": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", + "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", - "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "@babel/helper-member-expression-to-functions": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", + "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "@babel/helper-module-imports": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", + "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", "dev": true, - "dependencies": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", + "@babel/helper-module-transforms": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz", + "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-module-imports": "7.14.5", + "@babel/helper-replace-supers": "7.14.5", + "@babel/helper-simple-access": "7.14.5", + "@babel/helper-split-export-declaration": "7.14.5", + "@babel/helper-validator-identifier": "7.14.5", + "@babel/template": "7.14.5", + "@babel/traverse": "7.14.7", + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "@babel/helper-optimise-call-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", + "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz", - "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==", + "@babel/helper-plugin-utils": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", + "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-annotate-as-pure": "7.14.5", + "@babel/helper-wrap-function": "7.14.5", + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "@babel/helper-replace-supers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", + "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-member-expression-to-functions": "7.14.7", + "@babel/helper-optimise-call-expression": "7.14.5", + "@babel/traverse": "7.14.7", + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz", - "integrity": "sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA==", + "@babel/helper-simple-access": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz", + "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==", "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", - "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", + "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", + "@babel/helper-split-export-declaration": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", + "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", "dev": true, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", - "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", + "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-wrap-function": "^7.16.8", - "@babel/types": "^7.16.8" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-function-name": "7.14.5", + "@babel/template": "7.14.5", + "@babel/traverse": "7.14.7", + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", - "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", + "@babel/helpers": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz", + "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==", "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/template": "7.14.5", + "@babel/traverse": "7.14.7", + "@babel/types": "7.14.5" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", - "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-validator-identifier": "7.14.5", + "chalk": "2.4.2", + "js-tokens": "4.0.0" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", - "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "@babel/parser": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", + "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", + "dev": true + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz", + "integrity": "sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.0" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "7.14.5", + "@babel/plugin-proposal-optional-chaining": "7.14.5" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", + "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/helper-remap-async-to-generator": "7.14.5", + "@babel/plugin-syntax-async-generators": "7.8.4" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "@babel/plugin-proposal-class-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", + "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", "dev": true, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-create-class-features-plugin": "7.14.6", + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "@babel/plugin-proposal-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz", + "integrity": "sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg==", "dev": true, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-create-class-features-plugin": "7.14.6", + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-syntax-class-static-block": "7.14.5" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", - "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "@babel/plugin-proposal-dynamic-import": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", + "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.8", - "@babel/types": "^7.16.8" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-syntax-dynamic-import": "7.8.3" } }, - "node_modules/@babel/helpers": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", - "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", + "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", "dev": true, - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.0", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-syntax-export-namespace-from": "7.8.3" } }, - "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "@babel/plugin-proposal-json-strings": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", + "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-syntax-json-strings": "7.8.3" } }, - "node_modules/@babel/parser": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", - "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", + "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-syntax-logical-assignment-operators": "7.10.4" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", - "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", + "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "7.8.3" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", - "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", + "@babel/plugin-proposal-numeric-separator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", + "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-syntax-numeric-separator": "7.10.4" } }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", - "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz", + "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-remap-async-to-generator": "^7.16.8", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/compat-data": "7.14.7", + "@babel/helper-compilation-targets": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@babel/plugin-transform-parameters": "7.14.5" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", - "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", + "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-syntax-optional-catch-binding": "7.8.3" } }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz", - "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==", + "@babel/plugin-proposal-optional-chaining": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", + "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.17.6", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "7.14.5", + "@babel/plugin-syntax-optional-chaining": "7.8.3" } }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", - "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", + "@babel/plugin-proposal-private-methods": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", + "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-create-class-features-plugin": "7.14.6", + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", - "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-annotate-as-pure": "7.14.5", + "@babel/helper-create-class-features-plugin": "7.14.6", + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-syntax-private-property-in-object": "7.14.5" } }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", - "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", + "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-create-regexp-features-plugin": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", - "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", - "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", - "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", - "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.17.0", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", - "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", - "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.16.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", - "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.10", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", - "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", - "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { + "@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { + "@babel/plugin-syntax-class-static-block": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { + "@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { + "@babel/plugin-syntax-export-namespace-from": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-json-strings": { + "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { + "@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { + "@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { + "@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { + "@babel/plugin-syntax-private-property-in-object": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { + "@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", - "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", + "@babel/plugin-transform-arrow-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", + "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", - "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", + "@babel/plugin-transform-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", + "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-remap-async-to-generator": "^7.16.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-module-imports": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5", + "@babel/helper-remap-async-to-generator": "7.14.5" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", - "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", + "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", - "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", + "@babel/plugin-transform-block-scoping": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz", + "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", - "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", + "@babel/plugin-transform-classes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz", + "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-annotate-as-pure": "7.14.5", + "@babel/helper-function-name": "7.14.5", + "@babel/helper-optimise-call-expression": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5", + "@babel/helper-replace-supers": "7.14.5", + "@babel/helper-split-export-declaration": "7.14.5", + "globals": "11.12.0" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", - "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", + "@babel/plugin-transform-computed-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", + "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz", - "integrity": "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==", + "@babel/plugin-transform-destructuring": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", + "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", - "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "@babel/plugin-transform-dotall-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", + "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-create-regexp-features-plugin": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", - "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", + "@babel/plugin-transform-duplicate-keys": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", + "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", - "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", + "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", "dev": true, - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", - "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", + "@babel/plugin-transform-for-of": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", + "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", - "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", + "@babel/plugin-transform-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", + "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-function-name": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", - "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", + "@babel/plugin-transform-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", + "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", - "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "@babel/plugin-transform-member-expression-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", + "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", - "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", + "@babel/plugin-transform-modules-amd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", + "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-module-transforms": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5", + "babel-plugin-dynamic-import-node": "2.3.3" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz", - "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==", + "@babel/plugin-transform-modules-commonjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz", + "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==", "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-simple-access": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-module-transforms": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5", + "@babel/helper-simple-access": "7.14.5", + "babel-plugin-dynamic-import-node": "2.3.3" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz", - "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==", + "@babel/plugin-transform-modules-systemjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", + "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", "dev": true, - "dependencies": { - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-hoist-variables": "7.14.5", + "@babel/helper-module-transforms": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5", + "@babel/helper-validator-identifier": "7.14.5", + "babel-plugin-dynamic-import-node": "2.3.3" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", - "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", + "@babel/plugin-transform-modules-umd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", + "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-module-transforms": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", - "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz", + "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==", "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "requires": { + "@babel/helper-create-regexp-features-plugin": "7.14.5" } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", - "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", + "@babel/plugin-transform-new-target": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", + "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", - "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "@babel/plugin-transform-object-super": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", + "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/helper-replace-supers": "7.14.5" } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", - "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", + "@babel/plugin-transform-parameters": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", + "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", - "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "@babel/plugin-transform-property-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", + "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", - "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", + "@babel/plugin-transform-regenerator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", + "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", "dev": true, - "dependencies": { - "regenerator-transform": "^0.14.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "regenerator-transform": "0.14.5" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", - "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", + "@babel/plugin-transform-reserved-words": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", + "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", - "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "@babel/plugin-transform-shorthand-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", + "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", - "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", + "@babel/plugin-transform-spread": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", + "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "7.14.5" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", - "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "@babel/plugin-transform-sticky-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", + "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", - "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", + "@babel/plugin-transform-template-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", + "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", - "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", + "@babel/plugin-transform-typeof-symbol": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", + "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", - "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "@babel/plugin-transform-unicode-escapes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", + "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", - "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "@babel/plugin-transform-unicode-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", + "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-create-regexp-features-plugin": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5" } }, - "node_modules/@babel/preset-env": { - "version": "7.16.11", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", - "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.16.8", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", - "@babel/plugin-proposal-async-generator-functions": "^7.16.8", - "@babel/plugin-proposal-class-properties": "^7.16.7", - "@babel/plugin-proposal-class-static-block": "^7.16.7", - "@babel/plugin-proposal-dynamic-import": "^7.16.7", - "@babel/plugin-proposal-export-namespace-from": "^7.16.7", - "@babel/plugin-proposal-json-strings": "^7.16.7", - "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", - "@babel/plugin-proposal-numeric-separator": "^7.16.7", - "@babel/plugin-proposal-object-rest-spread": "^7.16.7", - "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", - "@babel/plugin-proposal-optional-chaining": "^7.16.7", - "@babel/plugin-proposal-private-methods": "^7.16.11", - "@babel/plugin-proposal-private-property-in-object": "^7.16.7", - "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.16.7", - "@babel/plugin-transform-async-to-generator": "^7.16.8", - "@babel/plugin-transform-block-scoped-functions": "^7.16.7", - "@babel/plugin-transform-block-scoping": "^7.16.7", - "@babel/plugin-transform-classes": "^7.16.7", - "@babel/plugin-transform-computed-properties": "^7.16.7", - "@babel/plugin-transform-destructuring": "^7.16.7", - "@babel/plugin-transform-dotall-regex": "^7.16.7", - "@babel/plugin-transform-duplicate-keys": "^7.16.7", - "@babel/plugin-transform-exponentiation-operator": "^7.16.7", - "@babel/plugin-transform-for-of": "^7.16.7", - "@babel/plugin-transform-function-name": "^7.16.7", - "@babel/plugin-transform-literals": "^7.16.7", - "@babel/plugin-transform-member-expression-literals": "^7.16.7", - "@babel/plugin-transform-modules-amd": "^7.16.7", - "@babel/plugin-transform-modules-commonjs": "^7.16.8", - "@babel/plugin-transform-modules-systemjs": "^7.16.7", - "@babel/plugin-transform-modules-umd": "^7.16.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", - "@babel/plugin-transform-new-target": "^7.16.7", - "@babel/plugin-transform-object-super": "^7.16.7", - "@babel/plugin-transform-parameters": "^7.16.7", - "@babel/plugin-transform-property-literals": "^7.16.7", - "@babel/plugin-transform-regenerator": "^7.16.7", - "@babel/plugin-transform-reserved-words": "^7.16.7", - "@babel/plugin-transform-shorthand-properties": "^7.16.7", - "@babel/plugin-transform-spread": "^7.16.7", - "@babel/plugin-transform-sticky-regex": "^7.16.7", - "@babel/plugin-transform-template-literals": "^7.16.7", - "@babel/plugin-transform-typeof-symbol": "^7.16.7", - "@babel/plugin-transform-unicode-escapes": "^7.16.7", - "@babel/plugin-transform-unicode-regex": "^7.16.7", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.16.8", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", - "core-js-compat": "^3.20.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/preset-env": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.7.tgz", + "integrity": "sha512-itOGqCKLsSUl0Y+1nSfhbuuOlTs0MJk2Iv7iSH+XT/mR8U1zRLO7NjWlYXB47yhK4J/7j+HYty/EhFZDYKa/VA==", + "dev": true, + "requires": { + "@babel/compat-data": "7.14.7", + "@babel/helper-compilation-targets": "7.14.5", + "@babel/helper-plugin-utils": "7.14.5", + "@babel/helper-validator-option": "7.14.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "7.14.5", + "@babel/plugin-proposal-async-generator-functions": "7.14.7", + "@babel/plugin-proposal-class-properties": "7.14.5", + "@babel/plugin-proposal-class-static-block": "7.14.5", + "@babel/plugin-proposal-dynamic-import": "7.14.5", + "@babel/plugin-proposal-export-namespace-from": "7.14.5", + "@babel/plugin-proposal-json-strings": "7.14.5", + "@babel/plugin-proposal-logical-assignment-operators": "7.14.5", + "@babel/plugin-proposal-nullish-coalescing-operator": "7.14.5", + "@babel/plugin-proposal-numeric-separator": "7.14.5", + "@babel/plugin-proposal-object-rest-spread": "7.14.7", + "@babel/plugin-proposal-optional-catch-binding": "7.14.5", + "@babel/plugin-proposal-optional-chaining": "7.14.5", + "@babel/plugin-proposal-private-methods": "7.14.5", + "@babel/plugin-proposal-private-property-in-object": "7.14.5", + "@babel/plugin-proposal-unicode-property-regex": "7.14.5", + "@babel/plugin-syntax-async-generators": "7.8.4", + "@babel/plugin-syntax-class-properties": "7.12.13", + "@babel/plugin-syntax-class-static-block": "7.14.5", + "@babel/plugin-syntax-dynamic-import": "7.8.3", + "@babel/plugin-syntax-export-namespace-from": "7.8.3", + "@babel/plugin-syntax-json-strings": "7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "7.8.3", + "@babel/plugin-syntax-numeric-separator": "7.10.4", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "7.8.3", + "@babel/plugin-syntax-optional-chaining": "7.8.3", + "@babel/plugin-syntax-private-property-in-object": "7.14.5", + "@babel/plugin-syntax-top-level-await": "7.14.5", + "@babel/plugin-transform-arrow-functions": "7.14.5", + "@babel/plugin-transform-async-to-generator": "7.14.5", + "@babel/plugin-transform-block-scoped-functions": "7.14.5", + "@babel/plugin-transform-block-scoping": "7.14.5", + "@babel/plugin-transform-classes": "7.14.5", + "@babel/plugin-transform-computed-properties": "7.14.5", + "@babel/plugin-transform-destructuring": "7.14.7", + "@babel/plugin-transform-dotall-regex": "7.14.5", + "@babel/plugin-transform-duplicate-keys": "7.14.5", + "@babel/plugin-transform-exponentiation-operator": "7.14.5", + "@babel/plugin-transform-for-of": "7.14.5", + "@babel/plugin-transform-function-name": "7.14.5", + "@babel/plugin-transform-literals": "7.14.5", + "@babel/plugin-transform-member-expression-literals": "7.14.5", + "@babel/plugin-transform-modules-amd": "7.14.5", + "@babel/plugin-transform-modules-commonjs": "7.14.5", + "@babel/plugin-transform-modules-systemjs": "7.14.5", + "@babel/plugin-transform-modules-umd": "7.14.5", + "@babel/plugin-transform-named-capturing-groups-regex": "7.14.7", + "@babel/plugin-transform-new-target": "7.14.5", + "@babel/plugin-transform-object-super": "7.14.5", + "@babel/plugin-transform-parameters": "7.14.5", + "@babel/plugin-transform-property-literals": "7.14.5", + "@babel/plugin-transform-regenerator": "7.14.5", + "@babel/plugin-transform-reserved-words": "7.14.5", + "@babel/plugin-transform-shorthand-properties": "7.14.5", + "@babel/plugin-transform-spread": "7.14.6", + "@babel/plugin-transform-sticky-regex": "7.14.5", + "@babel/plugin-transform-template-literals": "7.14.5", + "@babel/plugin-transform-typeof-symbol": "7.14.5", + "@babel/plugin-transform-unicode-escapes": "7.14.5", + "@babel/plugin-transform-unicode-regex": "7.14.5", + "@babel/preset-modules": "0.1.4", + "@babel/types": "7.14.5", + "babel-plugin-polyfill-corejs2": "0.2.2", + "babel-plugin-polyfill-corejs3": "0.2.3", + "babel-plugin-polyfill-regenerator": "0.2.2", + "core-js-compat": "3.15.1", + "semver": "6.3.0" } }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "requires": { + "@babel/helper-plugin-utils": "7.14.5", + "@babel/plugin-proposal-unicode-property-regex": "7.14.5", + "@babel/plugin-transform-dotall-regex": "7.14.5", + "@babel/types": "7.14.5", + "esutils": "2.0.3" } }, - "node_modules/@babel/runtime": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz", - "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==", + "@babel/runtime": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", + "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" + "requires": { + "regenerator-runtime": "0.13.7" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime/node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + } } }, - "node_modules/@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "@babel/runtime-corejs3": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz", + "integrity": "sha512-Wvzcw4mBYbTagyBVZpAJWI06auSIj033T/yNE0Zn1xcup83MieCddZA7ls3kme17L4NOGBrQ09Q+nKB41RLWBA==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", - "debug": "^4.1.0", - "globals": "^11.1.0" + "requires": { + "core-js-pure": "3.15.1", + "regenerator-runtime": "0.13.7" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "engines": { - "node": ">=0.1.90" + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + } } }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "requires": { + "@babel/code-frame": "7.14.5", + "@babel/parser": "7.14.7", + "@babel/types": "7.14.5" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "@babel/traverse": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz", + "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==", "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "requires": { + "@babel/code-frame": "7.14.5", + "@babel/generator": "7.14.5", + "@babel/helper-function-name": "7.14.5", + "@babel/helper-hoist-variables": "7.14.5", + "@babel/helper-split-export-declaration": "7.14.5", + "@babel/parser": "7.14.7", + "@babel/types": "7.14.5", + "debug": "4.3.1", + "globals": "11.12.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", - "dev": true, "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } } }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "@babel/types": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", + "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "requires": { + "@babel/helper-validator-identifier": "7.14.5", + "to-fast-properties": "2.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "@eslint/eslintrc": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", + "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", "dev": true, - "engines": { - "node": ">=10" + "requires": { + "ajv": "6.12.6", + "debug": "4.3.1", + "espree": "7.3.1", + "globals": "13.9.0", + "ignore": "4.0.6", + "import-fresh": "3.3.0", + "js-yaml": "3.14.1", + "minimatch": "3.0.4", + "strip-json-comments": "3.1.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "3.1.3", + "fast-json-stable-stringify": "2.1.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.4.1" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", + "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", + "dev": true, + "requires": { + "type-fest": "0.20.2" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.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 + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } } }, - "node_modules/@gulp-sourcemaps/identity-map": { + "@gulp-sourcemaps/identity-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-2.0.1.tgz", "integrity": "sha512-Tb+nSISZku+eQ4X1lAkevcQa+jknn/OVUgZ3XCxEKIsLsqYuPoJwJOPQeaOk75X3WPftb29GWY1eqE7GLsXb1Q==", "dev": true, - "dependencies": { - "acorn": "^6.4.1", - "normalize-path": "^3.0.0", - "postcss": "^7.0.16", - "source-map": "^0.6.0", - "through2": "^3.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/@gulp-sourcemaps/identity-map/node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/@gulp-sourcemaps/identity-map/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/@gulp-sourcemaps/identity-map/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" + "requires": { + "acorn": "6.4.2", + "normalize-path": "3.0.0", + "postcss": "7.0.36", + "source-map": "0.6.1", + "through2": "3.0.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/@gulp-sourcemaps/identity-map/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@gulp-sourcemaps/identity-map/node_modules/through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "postcss": { + "version": "7.0.36", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", + "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "source-map": "0.6.1", + "supports-color": "6.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 + }, + "supports-color": { + "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" + } + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "2.0.4", + "readable-stream": "3.6.0" + } + } } }, - "node_modules/@gulp-sourcemaps/map-sources": { + "@gulp-sourcemaps/map-sources": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", "dev": true, - "dependencies": { - "normalize-path": "^2.0.1", - "through2": "^2.0.3" + "requires": { + "normalize-path": "2.1.1", + "through2": "2.0.5" }, - "engines": { - "node": ">= 0.10" + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "2.3.7", + "xtend": "4.0.2" + } + } } }, - "node_modules/@gulp-sourcemaps/map-sources/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/types": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", + "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" + "requires": { + "@types/istanbul-lib-coverage": "2.0.3", + "@types/istanbul-reports": "3.0.1", + "@types/node": "15.12.4", + "@types/yargs": "16.0.3", + "chalk": "4.1.1" }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@gulp-sourcemaps/map-sources/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/types/node_modules/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 - }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } + } } }, - "node_modules/@jsdevtools/coverage-istanbul-loader": { + "@jsdevtools/coverage-istanbul-loader": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz", "integrity": "sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA==", "dev": true, - "dependencies": { - "convert-source-map": "^1.7.0", - "istanbul-lib-instrument": "^4.0.3", - "loader-utils": "^2.0.0", - "merge-source-map": "^1.1.0", - "schema-utils": "^2.7.0" + "requires": { + "convert-source-map": "1.8.0", + "istanbul-lib-instrument": "4.0.3", + "loader-utils": "2.0.0", + "merge-source-map": "1.1.0", + "schema-utils": "2.7.1" } }, - "node_modules/@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", + "@sindresorhus/is": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", + "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", "dev": true }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@sinonjs/commons": { + "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, - "dependencies": { + "requires": { "type-detect": "4.0.8" } }, - "node_modules/@sinonjs/formatio": { + "@sinonjs/formatio": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", "dev": true, - "dependencies": { + "requires": { "samsam": "1.3.0" } }, - "node_modules/@sinonjs/samsam": { + "@sinonjs/samsam": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" + "requires": { + "@sinonjs/commons": "1.8.3", + "array-from": "2.1.1", + "lodash": "4.17.21" } }, - "node_modules/@sinonjs/text-encoding": { + "@sinonjs/text-encoding": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "node_modules/@socket.io/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "@szmarczak/http-timer": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", + "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", "dev": true, - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" + "requires": { + "defer-to-connect": "2.0.1" } }, - "node_modules/@types/aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-P+dkdFu0n08PDIvw+9nT9ByQnd+Udc8DaWPb9HKfaPwCvWvQpC5XaMRx2xLWECm9x1VKNps6vEAlirjA6+uNrQ==", + "@types/aria-query": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.1.tgz", + "integrity": "sha512-S6oPal772qJZHoRZLFc/XoZW2gFvwXusYUmXPXkgxJLuEk2vOt7jc4Yo6z/vtI0EBkbPBVrJJ0B+prLIKiWqHg==", "dev": true }, - "node_modules/@types/cacheable-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", - "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "@types/cacheable-request": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", + "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", "dev": true, - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "*", - "@types/node": "*", - "@types/responselike": "*" + "requires": { + "@types/http-cache-semantics": "4.0.0", + "@types/keyv": "3.1.1", + "@types/node": "15.12.4", + "@types/responselike": "1.0.0" } }, - "node_modules/@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", - "dev": true - }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "@types/component-emitter": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", + "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==", "dev": true }, - "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", + "@types/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==", "dev": true }, - "node_modules/@types/diff": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.0.2.tgz", - "integrity": "sha512-uw8eYMIReOwstQ0QKF0sICefSy8cNO/v7gOTiIy9SbwuHyEecJUm7qlgueOO5S1udZ5I/irVydHVwMchgzbKTg==", + "@types/cors": { + "version": "2.8.10", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz", + "integrity": "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==", "dev": true }, - "node_modules/@types/easy-table": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/easy-table/-/easy-table-0.0.33.tgz", - "integrity": "sha512-/vvqcJPmZUfQwCgemL0/34G7bIQnCuvgls379ygRlcC1FqNqk3n+VZ15dAO51yl6JNDoWd8vsk+kT8zfZ1VZSw==", + "@types/easy-table": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/easy-table/-/easy-table-0.0.32.tgz", + "integrity": "sha512-zKh0f/ixYFnr3Ldf5ZJTi1ZpnRqAynTTtVyGvWDf/TT12asE8ac98t3/WGWfFdRPp/qsccxg82C/Kl3NPNhqEw==", "dev": true }, - "node_modules/@types/ejs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.0.tgz", - "integrity": "sha512-DCg+Ka+uDQ31lJ/UtEXVlaeV3d6t81gifaVWKJy4MYVVgvJttyX/viREy+If7fz+tK/gVxTGMtyrFPnm4gjrVA==", + "@types/ejs": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.0.6.tgz", + "integrity": "sha512-fj1hi+ZSW0xPLrJJD+YNwIh9GZbyaIepG26E/gXvp8nCa2pYokxUYO1sK9qjGxp2g8ryZYuon7wmjpwE2cyASQ==", "dev": true }, - "node_modules/@types/eslint": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", - "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "@types/estree": { + "version": "0.0.48", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz", + "integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==", "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true + "optional": true }, - "node_modules/@types/expect": { + "@types/expect": { "version": "1.20.4", "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", "dev": true }, - "node_modules/@types/fibers": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/fibers/-/fibers-3.1.1.tgz", - "integrity": "sha512-yHoUi46uika0snoTpNcVqUSvgbRndaIps4TUCotrXjtc0DHDoPQckmyXEZ2bX3e4mpJmyEW3hRhCwQa/ISCPaA==", + "@types/fibers": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/fibers/-/fibers-3.1.0.tgz", + "integrity": "sha512-1o3I9xtk2PZFxwaLCC6gTaBfBZ5rvw/DSZZPK89fwuwO6LNrzSbC6rEs1xI0bQ3fCRWmO+uNJQQeD2J56oTMDg==", "dev": true }, - "node_modules/@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "@types/fs-extra": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.11.tgz", + "integrity": "sha512-mZsifGG4QeQ7hlkhO56u7zt/ycBgGxSVsFI/6lGTU34VtwkiqrrSDgw0+ygs8kFGWcXnFQWMrzF2h7TtDFNixA==", "dev": true, - "dependencies": { - "@types/node": "*" + "requires": { + "@types/node": "15.12.4" } }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "@types/http-cache-semantics": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", + "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==", "dev": true }, - "node_modules/@types/inquirer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.0.tgz", - "integrity": "sha512-BNoMetRf3gmkpAlV5we+kxyZTle7YibdOntIZbU5pyIfMdcwy784KfeZDAcuyMznkh5OLa17RVXZOGA5LTlkgQ==", + "@types/inquirer": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-7.3.2.tgz", + "integrity": "sha512-EkeX/hU0SWinA2c7Qu/+6+7KbepFPYJcjankUgtA/VSY6BlVHybL0Cgyey9PDbXwhNXnNGBLU3t+MORp23RgAw==", "dev": true, - "dependencies": { - "@types/through": "*", - "rxjs": "^7.2.0" + "requires": { + "@types/through": "0.0.30", + "rxjs": "6.6.7" } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "@types/istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", "dev": true }, - "node_modules/@types/istanbul-lib-report": { + "@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" + "requires": { + "@types/istanbul-lib-coverage": "2.0.3" } }, - "node_modules/@types/istanbul-reports": { + "@types/istanbul-reports": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" + "requires": { + "@types/istanbul-lib-report": "3.0.0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "@types/json-schema": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", "dev": true }, - "node_modules/@types/json5": { + "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, - "node_modules/@types/keyv": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", - "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", + "@types/keyv": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", + "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", "dev": true, - "dependencies": { - "@types/node": "*" + "requires": { + "@types/node": "15.12.4" } }, - "node_modules/@types/lodash": { - "version": "4.14.179", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.179.tgz", - "integrity": "sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w==", + "@types/lodash": { + "version": "4.14.170", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz", + "integrity": "sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==", "dev": true }, - "node_modules/@types/lodash.flattendeep": { + "@types/lodash.flattendeep": { "version": "4.4.6", "resolved": "https://registry.npmjs.org/@types/lodash.flattendeep/-/lodash.flattendeep-4.4.6.tgz", "integrity": "sha512-uLm2MaRVlqJSGsMK0RZpP5T3KqReq+9WbYDHCUhBhp98v56hMG/Yht52bsoTSui9xz2mUvQ9NfG3LrNGDL92Ng==", "dev": true, - "dependencies": { - "@types/lodash": "*" + "requires": { + "@types/lodash": "4.14.170" } }, - "node_modules/@types/lodash.pickby": { + "@types/lodash.pickby": { "version": "4.6.6", "resolved": "https://registry.npmjs.org/@types/lodash.pickby/-/lodash.pickby-4.6.6.tgz", "integrity": "sha512-NFa13XxlMd9eFi0UFZFWIztpMpXhozbijrx3Yb1viYZphT7jyopIFVoIRF4eYMjruWNEG1rnyrRmg/8ej9T8Iw==", "dev": true, - "dependencies": { - "@types/lodash": "*" + "requires": { + "@types/lodash": "4.14.170" } }, - "node_modules/@types/lodash.union": { + "@types/lodash.union": { "version": "4.6.6", "resolved": "https://registry.npmjs.org/@types/lodash.union/-/lodash.union-4.6.6.tgz", "integrity": "sha512-Wu0ZEVNcyCz8eAn6TlUbYWZoGbH9E+iOHxAZbwUoCEXdUiy6qpcz5o44mMXViM4vlPLLCPlkAubEP1gokoSZaw==", "dev": true, - "dependencies": { - "@types/lodash": "*" + "requires": { + "@types/lodash": "4.14.170" } }, - "node_modules/@types/mdast": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", - "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "@types/mdast": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz", + "integrity": "sha512-SXPBMnFVQg1s00dlMCc/jCdvPqdE4mXaMMCeRlxLDmTAEoegHT53xKtkDnzDTOcmMHUfcjyf36/YYZ6SxRdnsw==", "dev": true, - "dependencies": { - "@types/unist": "*" + "requires": { + "@types/unist": "2.0.3" } }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", - "integrity": "sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg==", + "@types/minimist": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz", + "integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==", "dev": true }, - "node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "@types/mocha": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", + "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==", "dev": true }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "@types/node": { + "version": "15.12.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz", + "integrity": "sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==", "dev": true }, - "node_modules/@types/object-inspect": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@types/object-inspect/-/object-inspect-1.8.1.tgz", - "integrity": "sha512-0JTdf3CGV0oWzE6Wa40Ayv2e2GhpP3pEJMcrlM74vBSJPuuNkVwfDnl0SZxyFCXETcB4oKA/MpTVfuYSMOelBg==", + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, - "node_modules/@types/puppeteer": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-5.4.5.tgz", - "integrity": "sha512-lxCjpDEY+DZ66+W3x5Af4oHnEmUXt0HuaRzkBGE2UZiZEp/V1d3StpLPlmNVu/ea091bdNmVPl44lu8Wy/0ZCA==", + "@types/puppeteer": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-5.4.3.tgz", + "integrity": "sha512-3nE8YgR9DIsgttLW+eJf6mnXxq8Ge+27m5SU3knWmrlfl6+KOG0Bf9f7Ua7K+C4BnaTMAh3/UpySqdAYvrsvjg==", "dev": true, - "dependencies": { - "@types/node": "*" + "requires": { + "@types/node": "15.12.4" } }, - "node_modules/@types/recursive-readdir": { + "@types/recursive-readdir": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@types/recursive-readdir/-/recursive-readdir-2.2.0.tgz", "integrity": "sha512-HGk753KRu2N4mWduovY4BLjYq4jTOL29gV2OfGdGxHcPSWGFkC5RRIdk+VTs5XmYd7MVAD+JwKrcb5+5Y7FOCg==", "dev": true, - "dependencies": { - "@types/node": "*" + "requires": { + "@types/node": "15.12.4" } }, - "node_modules/@types/responselike": { + "@types/responselike": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", "dev": true, - "dependencies": { - "@types/node": "*" + "requires": { + "@types/node": "15.12.4" } }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "@types/stack-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", + "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", "dev": true }, - "node_modules/@types/stream-buffers": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/stream-buffers/-/stream-buffers-3.0.4.tgz", - "integrity": "sha512-qU/K1tb2yUdhXkLIATzsIPwbtX6BpZk0l3dPW6xqWyhfzzM1ECaQ/8faEnu3CNraLiQ9LHyQQPBGp7N9Fbs25w==", + "@types/stream-buffers": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/stream-buffers/-/stream-buffers-3.0.3.tgz", + "integrity": "sha512-NeFeX7YfFZDYsCfbuaOmFQ0OjSmHreKBpp7MQ4alWQBHeh2USLsj7qyMyn9t82kjqIX516CR/5SRHnARduRtbQ==", "dev": true, - "dependencies": { - "@types/node": "*" + "requires": { + "@types/node": "15.12.4" } }, - "node_modules/@types/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==", - "dev": true - }, - "node_modules/@types/through": { + "@types/through": { "version": "0.0.30", "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", "dev": true, - "dependencies": { - "@types/node": "*" + "requires": { + "@types/node": "15.12.4" } }, - "node_modules/@types/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-dDZH/tXzwjutnuk4UacGgFRwV+JSLaXL1ikvidfJprkb7L9Nx1njcRHHmi3Dsvt7pgqqTEeucQuOrWHPFgzVHA==", - "dev": true - }, - "node_modules/@types/ua-parser-js": { - "version": "0.7.36", - "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", - "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==", - "dev": true - }, - "node_modules/@types/unist": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", - "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", + "@types/unist": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", "dev": true }, - "node_modules/@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", + "@types/vinyl": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.4.tgz", + "integrity": "sha512-2o6a2ixaVI2EbwBPg1QYLGQoHK56p/8X/sGfKbFC8N6sY9lfjsMf/GprtkQkSya0D4uRiutRZ2BWj7k3JvLsAQ==", "dev": true, - "dependencies": { - "@types/expect": "^1.20.4", - "@types/node": "*" + "requires": { + "@types/expect": "1.20.4", + "@types/node": "15.12.4" } }, - "node_modules/@types/which": { + "@types/which": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/which/-/which-1.3.2.tgz", "integrity": "sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA==", "dev": true }, - "node_modules/@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "@types/yargs": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", + "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", "dev": true, - "dependencies": { - "@types/yargs-parser": "*" + "requires": { + "@types/yargs-parser": "20.2.0" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "@types/yargs-parser": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", + "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", "dev": true }, - "node_modules/@types/yauzl": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", - "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", + "@types/yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", "dev": true, "optional": true, - "dependencies": { - "@types/node": "*" + "requires": { + "@types/node": "15.12.4" } }, - "node_modules/@ungap/promise-all-settled": { + "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, - "node_modules/@vue/compiler-core": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.31.tgz", - "integrity": "sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==", - "dev": true, - "optional": true, - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.31", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" - } - }, - "node_modules/@vue/compiler-core/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.31.tgz", - "integrity": "sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==", + "@vue/compiler-core": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.2.tgz", + "integrity": "sha512-nHmq7vLjq/XM2IMbZUcKWoH5sPXa2uR/nIKZtjbK5F3TcbnYE/zKsrSUR9WZJ03unlwotNBX1OyxVt9HbWD7/Q==", "dev": true, - "optional": true, + "requires": { + "@babel/parser": "7.14.7", + "@babel/types": "7.14.5", + "@vue/shared": "3.1.2", + "estree-walker": "2.0.2", + "source-map": "0.6.1" + }, "dependencies": { - "@vue/compiler-core": "3.2.31", - "@vue/shared": "3.2.31" + "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 + } } }, - "node_modules/@vue/compiler-sfc": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.31.tgz", - "integrity": "sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==", - "dev": true, - "optional": true, - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.31", - "@vue/compiler-dom": "3.2.31", - "@vue/compiler-ssr": "3.2.31", - "@vue/reactivity-transform": "3.2.31", - "@vue/shared": "3.2.31", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" - } - }, - "node_modules/@vue/compiler-sfc/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "@vue/compiler-dom": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.1.2.tgz", + "integrity": "sha512-k2+SWcWH0jL6WQAX7Or2ONqu5MbtTgTO0dJrvebQYzgqaKMXNI90RNeWeCxS4BnNFMDONpHBeFgbwbnDWIkmRg==", "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" + "requires": { + "@vue/compiler-core": "3.1.2", + "@vue/shared": "3.1.2" } }, - "node_modules/@vue/compiler-ssr": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.31.tgz", - "integrity": "sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==", + "@vue/compiler-sfc": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.1.2.tgz", + "integrity": "sha512-SeG/2+DvwejQ7oAiSx8BrDh5qOdqCYHGClPiTvVIHTfSIHiS2JjMbCANdDCjHkTOh/O7WZzo2JhdKm98bRBxTw==", "dev": true, "optional": true, + "requires": { + "@babel/parser": "7.14.7", + "@babel/types": "7.14.5", + "@types/estree": "0.0.48", + "@vue/compiler-core": "3.1.2", + "@vue/compiler-dom": "3.1.2", + "@vue/compiler-ssr": "3.1.2", + "@vue/shared": "3.1.2", + "consolidate": "0.16.0", + "estree-walker": "2.0.2", + "hash-sum": "2.0.0", + "lru-cache": "5.1.1", + "magic-string": "0.25.7", + "merge-source-map": "1.1.0", + "postcss": "8.3.5", + "postcss-modules": "4.1.3", + "postcss-selector-parser": "6.0.6", + "source-map": "0.6.1" + }, "dependencies": { - "@vue/compiler-dom": "3.2.31", - "@vue/shared": "3.2.31" + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "optional": true, + "requires": { + "yallist": "3.1.1" + } + }, + "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 + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "optional": true + } } }, - "node_modules/@vue/reactivity-transform": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.31.tgz", - "integrity": "sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==", + "@vue/compiler-ssr": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.1.2.tgz", + "integrity": "sha512-BwXo9LFk5OSWdMyZQ4bX1ELHX0Z/9F+ld/OaVnpUPzAZCHslBYLvyKUVDwv2C/lpLjRffpC2DOUEdl1+RP1aGg==", "dev": true, "optional": true, - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.31", - "@vue/shared": "3.2.31", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" - } - }, - "node_modules/@vue/shared": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.31.tgz", - "integrity": "sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==", - "dev": true, - "optional": true - }, - "node_modules/@wdio/browserstack-service": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/browserstack-service/-/browserstack-service-7.16.16.tgz", - "integrity": "sha512-q4wUh/j0MR2SwhTkmIFif2DaXgH5yzdgOer6G/fac2n81zLCSpQHWO5aQ9T0An9CAd4L2A+t3dmChpBJPkHWSw==", - "dev": true, - "dependencies": { - "@types/node": "^17.0.4", - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "browserstack-local": "^1.4.5", - "got": "^11.0.2", - "webdriverio": "7.16.16" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@wdio/cli": "^7.0.0" + "requires": { + "@vue/compiler-dom": "3.1.2", + "@vue/shared": "3.1.2" } }, - "node_modules/@wdio/cli": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-7.16.16.tgz", - "integrity": "sha512-Wz/e5zm1UNHB9RAIsJIM7ioDzVllUwTvhVWOrI7HR/53GmO/cIvAVjpnlglizJNgK8WlbnM/cKNVIXxqxrnFmw==", - "dev": true, - "dependencies": { - "@types/ejs": "^3.0.5", - "@types/fs-extra": "^9.0.4", - "@types/inquirer": "^8.1.2", - "@types/lodash.flattendeep": "^4.4.6", - "@types/lodash.pickby": "^4.6.6", - "@types/lodash.union": "^4.6.6", - "@types/node": "^17.0.4", - "@types/recursive-readdir": "^2.2.0", - "@wdio/config": "7.16.16", - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "async-exit-hook": "^2.0.1", - "chalk": "^4.0.0", - "chokidar": "^3.0.0", - "cli-spinners": "^2.1.0", - "ejs": "^3.0.1", - "fs-extra": "^10.0.0", - "inquirer": "8.1.5", - "lodash.flattendeep": "^4.4.0", - "lodash.pickby": "^4.6.0", - "lodash.union": "^4.6.0", - "mkdirp": "^1.0.4", - "recursive-readdir": "^2.2.2", - "webdriverio": "7.16.16", - "yargs": "^17.0.0", - "yarn-install": "^1.0.0" - }, - "bin": { - "wdio": "bin/wdio.js" - }, - "engines": { - "node": ">=12.0.0" - } + "@vue/shared": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.2.tgz", + "integrity": "sha512-EmH/poaDWBPJaPILXNI/1fvUbArJQmmTyVCwvvyDYDFnkPoTclAbHRAtyIvqfez7jybTDn077HTNILpxlsoWhg==", + "dev": true }, - "node_modules/@wdio/cli/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "@wdio/browserstack-service": { + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/@wdio/browserstack-service/-/browserstack-service-6.12.1.tgz", + "integrity": "sha512-B4zYlaE8q1Jxb6ctcuUPlKL3inwloETwks+cB9fFtVMDf/HH2Cau3Pi0CoIs8435EI+J4/1LxLHQV2uhzbBSlQ==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "requires": { + "@wdio/logger": "6.10.10", + "browserstack-local": "1.4.8", + "got": "11.8.2" } }, - "node_modules/@wdio/cli/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "@wdio/cli": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-7.7.4.tgz", + "integrity": "sha512-npgpaIpPoSpyef1Pv0ZKyB5FJAZnDJiVphgda0RysXd6J0S3mlwzXrcIoapl28mmeWI6NIvvv65u0sominhsyQ==", + "dev": true, + "requires": { + "@types/ejs": "3.0.6", + "@types/fs-extra": "9.0.11", + "@types/inquirer": "7.3.2", + "@types/lodash.flattendeep": "4.4.6", + "@types/lodash.pickby": "4.6.6", + "@types/lodash.union": "4.6.6", + "@types/recursive-readdir": "2.2.0", + "@wdio/config": "7.7.3", + "@wdio/logger": "7.7.0", + "@wdio/types": "7.7.3", + "@wdio/utils": "7.7.3", + "async-exit-hook": "2.0.1", + "chalk": "4.1.1", + "chokidar": "3.5.2", + "cli-spinners": "2.6.0", + "ejs": "3.1.6", + "fs-extra": "10.0.0", + "inquirer": "8.1.1", + "lodash.flattendeep": "4.4.0", + "lodash.pickby": "4.6.0", + "lodash.union": "4.6.0", + "mkdirp": "1.0.4", + "recursive-readdir": "2.2.2", + "webdriverio": "7.7.4", + "yargs": "17.0.1", + "yarn-install": "1.0.0" + }, + "dependencies": { + "@wdio/logger": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.7.0.tgz", + "integrity": "sha512-XX/OkC8NlvsBdhKsb9j7ZbuQtF/Vuo0xf38PXdqYtVezOrYbDuba0hPG++g/IGNuAF34ZbSi+49cvz4u5w92kQ==", + "dev": true, + "requires": { + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } + }, + "yargs": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.0.1.tgz", + "integrity": "sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==", + "dev": true, + "requires": { + "cliui": "7.0.4", + "escalade": "3.1.1", + "get-caller-file": "2.0.5", + "require-directory": "2.1.1", + "string-width": "4.2.2", + "y18n": "5.0.8", + "yargs-parser": "20.2.9" + } + } } }, - "node_modules/@wdio/cli/node_modules/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==", + "@wdio/concise-reporter": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/@wdio/concise-reporter/-/concise-reporter-7.7.3.tgz", + "integrity": "sha512-2Ix20n48N+lvvU4NzqMP7z+daG748RRsmDqdstCoBrJgXV6frvu38HVHV90U5uKt5Vmp6/QQl05A4OliaNoO9w==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" + "requires": { + "@wdio/reporter": "7.7.3", + "@wdio/types": "7.7.3", + "chalk": "4.1.1", + "pretty-ms": "7.0.1" }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@wdio/cli/node_modules/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 - }, - "node_modules/@wdio/cli/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } + } } }, - "node_modules/@wdio/cli/node_modules/yargs": { - "version": "17.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", - "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", + "@wdio/config": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-7.7.3.tgz", + "integrity": "sha512-I8gkb5BjXLe6/9NK7OCA9Mc+A6xeGUqbYTRd4PNKdObE6HomKOxw4plVZCYF0DlD2FCo4OGrvYGmalojFsCMdA==", "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "requires": { + "@wdio/logger": "7.7.0", + "@wdio/types": "7.7.3", + "deepmerge": "4.2.2", + "glob": "7.1.7" }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@wdio/concise-reporter": { - "version": "7.16.14", - "resolved": "https://registry.npmjs.org/@wdio/concise-reporter/-/concise-reporter-7.16.14.tgz", - "integrity": "sha512-CR+9+skJ3mXPIdRo0AnIJTJHOArrWdKlXTnyZ/DD6M9VrNk5aiTWQyphT/IeHV5+fxjHlMNIf/KgIhj1ewschQ==", - "dev": true, "dependencies": { - "@wdio/reporter": "7.16.14", - "@wdio/types": "7.16.14", - "chalk": "^4.0.0", - "pretty-ms": "^7.0.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@wdio/cli": "^7.0.0" + "@wdio/logger": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.7.0.tgz", + "integrity": "sha512-XX/OkC8NlvsBdhKsb9j7ZbuQtF/Vuo0xf38PXdqYtVezOrYbDuba0hPG++g/IGNuAF34ZbSi+49cvz4u5w92kQ==", + "dev": true, + "requires": { + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } + } } }, - "node_modules/@wdio/concise-reporter/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "@wdio/local-runner": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-7.7.4.tgz", + "integrity": "sha512-ubBr9+pDZuOg6i/EJdW8E71dXrE1A63+wsZH6lpdm1fFWqfRvjl+DTCdE2rtLhr44vNSmiHxIIQnCjvZXwjiFg==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "requires": { + "@types/stream-buffers": "3.0.3", + "@wdio/logger": "7.7.0", + "@wdio/repl": "7.7.3", + "@wdio/runner": "7.7.4", + "@wdio/types": "7.7.3", + "async-exit-hook": "2.0.1", + "split2": "3.2.2", + "stream-buffers": "3.0.2" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@wdio/concise-reporter/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@wdio/concise-reporter/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@wdio/concise-reporter/node_modules/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 - }, - "node_modules/@wdio/concise-reporter/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@wdio/config": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-7.16.16.tgz", - "integrity": "sha512-K/ObPuo6Da2liz++OKOIfbdpFwI7UWiFcBylfJkCYbweuXCoW1aUqlKI6rmKPwCH9Uqr/RHWu6p8eo0zWe6xVA==", - "dev": true, - "dependencies": { - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "deepmerge": "^4.0.0", - "glob": "^7.1.2" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@wdio/local-runner": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-7.16.16.tgz", - "integrity": "sha512-AJaOyM842PWgMffrrXyHJjouVseLHoiL5U1sw2VVproi3ORWHbltl1AMnreU/lrGu9L0CVKHYT1pxu5UbSOCxQ==", - "dev": true, - "dependencies": { - "@types/stream-buffers": "^3.0.3", - "@wdio/logger": "7.16.0", - "@wdio/repl": "7.16.14", - "@wdio/runner": "7.16.16", - "@wdio/types": "7.16.14", - "async-exit-hook": "^2.0.1", - "split2": "^4.0.0", - "stream-buffers": "^3.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@wdio/cli": "^7.0.0" - } - }, - "node_modules/@wdio/logger": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.16.0.tgz", - "integrity": "sha512-/6lOGb2Iow5eSsy7RJOl1kCwsP4eMlG+/QKro5zUJsuyNJSQXf2ejhpkzyKWLgQbHu83WX6cM1014AZuLkzoQg==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "loglevel": "^1.6.0", - "loglevel-plugin-prefix": "^0.8.4", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@wdio/logger/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@wdio/logger/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@wdio/logger/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@wdio/logger/node_modules/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 - }, - "node_modules/@wdio/logger/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@wdio/mocha-framework": { - "version": "7.16.15", - "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-7.16.15.tgz", - "integrity": "sha512-XRya85/RYPZk4MZ7Cvl3oudTdrOo+RyO8b5Ff+dH8hD3GBCACaWgW9AjbsyhvbSTdUlF0gNLPdqOCsxV5XyM3w==", - "dev": true, - "dependencies": { - "@types/mocha": "^9.0.0", - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "expect-webdriverio": "^3.0.0", - "mocha": "^9.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/@wdio/mocha-framework/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/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 - }, - "node_modules/@wdio/mocha-framework/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/mocha": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.1.tgz", - "integrity": "sha512-T7uscqjJVS46Pq1XDXyo9Uvey9gd3huT/DD9cYBb4K2Xc/vbKRPUWK067bxDQRK0yIz6Jxk73IrnimvASzBNAQ==", - "dev": true, - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.2.0", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/@wdio/mocha-framework/node_modules/nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@wdio/mocha-framework/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@wdio/protocols": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-7.16.7.tgz", - "integrity": "sha512-Wv40pNQcLiPzQ3o98Mv4A8T1EBQ6k4khglz/e2r16CTm+F3DDYh8eLMAsU5cgnmuwwDKX1EyOiFwieykBn5MCg==", - "dev": true, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@wdio/repl": { - "version": "7.16.14", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-7.16.14.tgz", - "integrity": "sha512-Ezih0Y+lsGkKv3H3U56hdWgZiQGA3VaAYguSLd9+g1xbQq+zMKqSmfqECD9bAy+OgCCiVTRstES6lHZxJVPhAg==", - "dev": true, - "dependencies": { - "@wdio/utils": "7.16.14" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@wdio/reporter": { - "version": "7.16.14", - "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-7.16.14.tgz", - "integrity": "sha512-e/I2oGfqjx9+zI4NT/garqxm7Afnos1EcrGSNu75WmP3PNJt4i+9DKkROu4PM6XWcpUB4v2UF7Mv/NrL3TU9aA==", - "dev": true, - "dependencies": { - "@types/diff": "^5.0.0", - "@types/node": "^17.0.4", - "@types/object-inspect": "^1.8.0", - "@types/supports-color": "^8.1.0", - "@types/tmp": "^0.2.0", - "@wdio/types": "7.16.14", - "diff": "^5.0.0", - "fs-extra": "^10.0.0", - "object-inspect": "^1.10.3", - "supports-color": "8.1.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@wdio/runner": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-7.16.16.tgz", - "integrity": "sha512-Tt2ja6GukGPq1m98WP26yOWUGwzK1y7gPTLy6rKlamz3mOBC7koL0T9+iqcFREquUe4CMy2jWp1lqvPlwMbu7g==", - "dev": true, - "dependencies": { - "@wdio/config": "7.16.16", - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "deepmerge": "^4.0.0", - "gaze": "^1.1.2", - "webdriver": "7.16.16", - "webdriverio": "7.16.16" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@wdio/spec-reporter": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-7.19.1.tgz", - "integrity": "sha512-qnZkn3VcyBPtcorUtpyCFE8v5ubyWmR7mFETXNzyriHyvjvk+NeFCWaFcIehpXYXiAmNpAwyfnZoIY6tkKQixQ==", - "dev": true, - "dependencies": { - "@types/easy-table": "^0.0.33", - "@wdio/reporter": "7.19.1", - "@wdio/types": "7.19.1", - "chalk": "^4.0.0", - "easy-table": "^1.1.1", - "pretty-ms": "^7.0.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@wdio/cli": "^7.0.0" - } - }, - "node_modules/@wdio/spec-reporter/node_modules/@wdio/reporter": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-7.19.1.tgz", - "integrity": "sha512-sWmBBV4dPCZkGk9Qq0m35T/vHGen0N10nH4osQcVP3IZJqpo2eLIH4w+X6EUbjZ2GdgOA2bLMMzb1bl9JqnGPg==", - "dev": true, - "dependencies": { - "@types/diff": "^5.0.0", - "@types/node": "^17.0.4", - "@types/object-inspect": "^1.8.0", - "@types/supports-color": "^8.1.0", - "@types/tmp": "^0.2.0", - "@wdio/types": "7.19.1", - "diff": "^5.0.0", - "fs-extra": "^10.0.0", - "object-inspect": "^1.10.3", - "supports-color": "8.1.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@wdio/spec-reporter/node_modules/@wdio/reporter/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/@wdio/spec-reporter/node_modules/@wdio/types": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.19.1.tgz", - "integrity": "sha512-mOodKlmvYxpj8P5BhjggEGpXuiRSlsyn2ClG8QqJ3lfXgOtOVEzFNfv/Ai7TkHr+lHDQNXLjllCjSqoCHhwlqg==", - "dev": true, - "dependencies": { - "@types/node": "^17.0.4", - "got": "^11.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "^4.6.2" - } - }, - "node_modules/@wdio/spec-reporter/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@wdio/spec-reporter/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@wdio/spec-reporter/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@wdio/spec-reporter/node_modules/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 - }, - "node_modules/@wdio/spec-reporter/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@wdio/sync": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/sync/-/sync-7.16.16.tgz", - "integrity": "sha512-MbVFAteaAOxHLKkMiMzOnh1hzINAK2U41GDIfy1yaPumcw1pNuJIhWrBYxprNMlqt8srk++wqQWgj5XpFjCL6g==", - "dev": true, - "dependencies": { - "@types/fibers": "^3.1.0", - "@types/puppeteer": "^5.4.0", - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "fibers": "^5.0.0", - "webdriverio": "7.16.16" - }, - "engines": { - "node": ">=12.0.0 <16" - } - }, - "node_modules/@wdio/types": { - "version": "7.16.14", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.16.14.tgz", - "integrity": "sha512-AyNI9iBSos9xWBmiFAF3sBs6AJXO/55VppU/eeF4HRdbZMtMarnvMuahM+jlUrA3vJSmDW+ufelG0MT//6vrnw==", - "dev": true, - "dependencies": { - "@types/node": "^17.0.4", - "got": "^11.8.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@wdio/utils": { - "version": "7.16.14", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-7.16.14.tgz", - "integrity": "sha512-wwin8nVpIlhmXJkq6GJw9aDDzgLOJKgXTcEua0T2sdXjoW78u5Ly/GZrFXTjMGhacFvoZfitTrjyfyy4CxMVvw==", - "dev": true, - "dependencies": { - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "p-iteration": "^1.1.8" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dev": true, - "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/add-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", - "dev": true - }, - "node_modules/agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", - "dev": true, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", - "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.4.2" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "dependencies": { - "ansi-wrap": "0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "dependencies": { - "buffer-equal": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/archiver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz", - "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", - "dev": true, - "dependencies": { - "archiver-utils": "^2.1.0", - "async": "^3.2.0", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.0.0", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "dev": true, - "dependencies": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/archiver/node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true - }, - "node_modules/archiver/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/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 - }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", - "dev": true - }, - "node_modules/array-includes": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", - "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "dependencies": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-initial/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "dependencies": { - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "dependencies": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", - "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", - "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", - "dev": true, - "dependencies": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "node_modules/async-exit-hook": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", - "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "dependencies": { - "async-done": "^1.2.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "node_modules/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, - "dependencies": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "node_modules/babel-code-frame/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "node_modules/babel-code-frame/node_modules/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, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/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, - "dependencies": { - "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" - } - }, - "node_modules/babel-core/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/babel-core/node_modules/json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/babel-core/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/babel-core/node_modules/slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "dependencies": { - "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" - } - }, - "node_modules/babel-generator/node_modules/detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "dependencies": { - "repeating": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-generator/node_modules/jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "node_modules/babel-loader": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz", - "integrity": "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==", - "dev": true, - "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^1.4.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "engines": { - "node": ">= 8.9" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" - } - }, - "node_modules/babel-loader/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/babel-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "dependencies": { - "object.assign": "^4.1.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", - "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.1", - "semver": "^6.1.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", - "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", - "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-transform-object-assign": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz", - "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "dependencies": { - "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" - } - }, - "node_modules/babel-register/node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, - "hasInstallScript": true - }, - "node_modules/babel-register/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/babel-register/node_modules/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==", - "dev": true, - "dependencies": { - "source-map": "^0.5.6" - } - }, - "node_modules/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=", - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "node_modules/babel-runtime/node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", - "hasInstallScript": true - }, - "node_modules/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, - "dependencies": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "node_modules/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, - "dependencies": { - "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" - } - }, - "node_modules/babel-traverse/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/babel-traverse/node_modules/globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-traverse/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/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, - "dependencies": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "node_modules/babel-types/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babelify": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz", - "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true, - "bin": { - "babylon": "bin/babylon.js" - } - }, - "node_modules/bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "dependencies": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/bail": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "dev": true, - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/binaryextensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", - "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", - "dev": true, - "engines": { - "node": ">=0.8" - }, - "funding": { - "url": "https://bevry.me/fund" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "node_modules/body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true, - "dependencies": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" - } - }, - "node_modules/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/body/node_modules/bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", - "dev": true - }, - "node_modules/body/node_modules/raw-body": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", - "dev": true, - "dependencies": { - "bytes": "1", - "string_decoder": "0.10" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/body/node_modules/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 - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-resolve": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", - "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", - "dev": true, - "dependencies": { - "resolve": "1.1.7" - } - }, - "node_modules/browser-resolve/node_modules/resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.0.tgz", - "integrity": "sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001313", - "electron-to-chromium": "^1.4.76", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/browserstack": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.3.tgz", - "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==", - "dev": true, - "dependencies": { - "https-proxy-agent": "^2.2.1" - } - }, - "node_modules/browserstack-local": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.9.tgz", - "integrity": "sha512-V+q8HQwRQFr9nd32xR66ZZ3VDWa3Kct4IMMudhKgcuD7cWrvvFARZOibx71II+Rf7P5nMQpWWxl9z/3p927nbg==", - "dev": true, - "dependencies": { - "https-proxy-agent": "^4.0.0", - "is-running": "^2.1.0", - "ps-tree": "=1.2.0", - "temp-fs": "^0.9.9" - } - }, - "node_modules/browserstack/node_modules/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, - "dependencies": { - "es6-promisify": "^5.0.0" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/browserstack/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/browserstack/node_modules/https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "dependencies": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/browserstacktunnel-wrapper": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.4.tgz", - "integrity": "sha512-GCV599FUUxNOCFl3WgPnfc5dcqq9XTmMXoxWpqkvmk0R9TOIoqmjENNU6LY6DtgIL6WfBVbg/jmWtnM5K6UYSg==", - "dev": true, - "dependencies": { - "https-proxy-agent": "^2.2.1", - "unzipper": "^0.9.3" - }, - "engines": { - "node": ">= 0.10.20" - } - }, - "node_modules/browserstacktunnel-wrapper/node_modules/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, - "dependencies": { - "es6-promisify": "^5.0.0" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/browserstacktunnel-wrapper/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/browserstacktunnel-wrapper/node_modules/https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "dependencies": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", - "dev": true - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cac": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/cac/-/cac-3.0.4.tgz", - "integrity": "sha1-bSTO7Dcu/lybeYgIvH9JtHJCpO8=", - "dev": true, - "dependencies": { - "camelcase-keys": "^3.0.0", - "chalk": "^1.1.3", - "indent-string": "^3.0.0", - "minimist": "^1.2.0", - "read-pkg-up": "^1.0.1", - "suffix": "^0.1.0", - "text-table": "^0.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cac/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/camelcase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-3.0.0.tgz", - "integrity": "sha1-/AxsNgNj9zd+N5O5oWvM8QcMHKQ=", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/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, - "engines": { - "node": ">=4" - } - }, - "node_modules/cac/node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/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, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cac/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cached-path-relative": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz", - "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==", - "dev": true - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "dependencies": { - "callsites": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caller-path/node_modules/callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001320", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", - "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "node_modules/ccount": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", - "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/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, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/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, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-html4": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz", - "integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/chrome-launcher": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.0.tgz", - "integrity": "sha512-ZQqX5kb9H0+jy1OqLnWampfocrtSZaGl7Ny3F9GRha85o4odbL8x55paUzh51UC7cEmZ5obp3H2Mm70uC2PpRA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0" - }, - "bin": { - "print-chrome-path": "bin/print-chrome-path.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/chrome-launcher/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "deprecated": "CircularJSON is in maintenance only, flatted is its successor.", - "dev": true - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/class-utils/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/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, - "dependencies": { - "mimic-response": "^1.0.0" - } - }, - "node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "dependencies": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/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, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "node_modules/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 - }, - "node_modules/compress-commons": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", - "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", - "dev": true, - "dependencies": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/compress-commons/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/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 - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-with-sourcemaps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/concat-with-sourcemaps/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/connect-livereload": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.6.1.tgz", - "integrity": "sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/continuable-cache": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", - "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", - "dev": true - }, - "node_modules/conventional-changelog": { - "version": "3.1.24", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", - "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", - "dev": true, - "dependencies": { - "conventional-changelog-angular": "^5.0.12", - "conventional-changelog-atom": "^2.0.8", - "conventional-changelog-codemirror": "^2.0.8", - "conventional-changelog-conventionalcommits": "^4.5.0", - "conventional-changelog-core": "^4.2.1", - "conventional-changelog-ember": "^2.0.9", - "conventional-changelog-eslint": "^3.0.9", - "conventional-changelog-express": "^2.0.6", - "conventional-changelog-jquery": "^3.0.11", - "conventional-changelog-jshint": "^2.0.9", - "conventional-changelog-preset-loader": "^2.3.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-atom": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", - "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-codemirror": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", - "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-config-spec": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", - "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", - "dev": true - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz", - "integrity": "sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", - "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", - "dev": true, - "dependencies": { - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-parser": "^3.2.0", - "dateformat": "^3.0.0", - "get-pkg-repo": "^4.0.0", - "git-raw-commits": "^2.0.8", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^4.1.1", - "lodash": "^4.17.15", - "normalize-package-data": "^3.0.0", - "q": "^1.5.1", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0", - "through2": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-core/node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/conventional-changelog-core/node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-core/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-core/node_modules/read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/conventional-changelog-core/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-ember": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", - "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-eslint": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", - "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-express": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", - "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-jquery": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", - "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-jshint": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", - "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-preset-loader": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", - "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-writer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", - "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", - "dev": true, - "dependencies": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-changelog-writer": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-writer/node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/conventional-changelog-writer/node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/conventional-commits-filter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", - "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", - "dev": true, - "dependencies": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-commits-parser": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", - "dev": true, - "dependencies": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-commits-parser/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/conventional-commits-parser/node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/conventional-recommended-bump": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", - "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", - "dev": true, - "dependencies": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^2.3.4", - "conventional-commits-filter": "^2.0.7", - "conventional-commits-parser": "^3.2.0", - "git-raw-commits": "^2.0.8", - "git-semver-tags": "^4.1.1", - "meow": "^8.0.0", - "q": "^1.5.1" - }, - "bin": { - "conventional-recommended-bump": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-recommended-bump/node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "engines": [ - "node >= 6.0" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/conventional-recommended-bump/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "dependencies": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - } - }, - "node_modules/core-js": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", - "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz", - "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==", - "dev": true, - "dependencies": { - "browserslist": "^4.19.1", - "semver": "7.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/core-js-pure": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz", - "integrity": "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/coveralls": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", - "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", - "dev": true, - "dependencies": { - "js-yaml": "^3.13.1", - "lcov-parse": "^1.0.0", - "log-driver": "^1.2.7", - "minimist": "^1.2.5", - "request": "^2.88.2" - }, - "bin": { - "coveralls": "bin/coveralls.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/crc-32": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", - "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", - "dev": true, - "dependencies": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.3.1" - }, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/crc32-stream": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", - "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", - "dev": true, - "dependencies": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/crc32-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/criteo-direct-rsa-validate": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/criteo-direct-rsa-validate/-/criteo-direct-rsa-validate-1.1.0.tgz", - "integrity": "sha512-7gQ3zX+d+hS/vOxzLrZ4aRAceB7qNJ0VzaGNpcWjDCmtOpASB50USJDupTik/H2nHgiSAA3VNZ3SFuONs8LR9Q==" - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dev": true, - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-js": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz", - "integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==" - }, - "node_modules/css": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", - "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "source-map": "^0.6.1", - "source-map-resolve": "^0.6.0" - } - }, - "node_modules/css-shorthand-properties": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/css-shorthand-properties/-/css-shorthand-properties-1.1.1.tgz", - "integrity": "sha512-Md+Juc7M3uOdbAFwOYlTrccIZ7oCFuzrhKYQjdeUEW/sE1hv17Jp/Bws+ReOPpGVBTYCBoYo+G17V5Qo8QQ75A==", - "dev": true - }, - "node_modules/css-value": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", - "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", - "dev": true - }, - "node_modules/css/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "dependencies": { - "array-find-index": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", - "dev": true - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/date-format": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.4.tgz", - "integrity": "sha512-/jyf4rhB17ge328HJuJjAcmRtCsGd+NDeAtahRBTaK6vSPR6MO5HlrAit3Nn7dVjaa6sowW0WXt8yQtLyZQFRg==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", - "dev": true, - "optional": true - }, - "node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug-fabulous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", - "dev": true, - "dependencies": { - "debug": "3.X", - "memoizee": "0.4.X", - "object-assign": "4.X" - } - }, - "node_modules/debug-fabulous/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-equal": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.5.tgz", - "integrity": "sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "es-get-iterator": "^1.1.1", - "get-intrinsic": "^1.0.1", - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.2", - "is-regex": "^1.1.1", - "isarray": "^2.0.5", - "object-is": "^1.1.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.3", - "which-boxed-primitive": "^1.0.1", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "dependencies": { - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - } - }, - "node_modules/defaults/node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/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, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detective": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "dev": true, - "dependencies": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - }, - "bin": { - "detective": "bin/detective.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/devtools": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/devtools/-/devtools-7.16.16.tgz", - "integrity": "sha512-M0kzkuSgfEhpqIis3gdtWsNjn/HQ+vRAmEzDnbYx/7FfjFxhSv1d+rOOT20pvd60soItMYpsOova1igACEGkGQ==", - "dev": true, - "dependencies": { - "@types/node": "^17.0.4", - "@types/ua-parser-js": "^0.7.33", - "@wdio/config": "7.16.16", - "@wdio/logger": "7.16.0", - "@wdio/protocols": "7.16.7", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "chrome-launcher": "^0.15.0", - "edge-paths": "^2.1.0", - "puppeteer-core": "^13.1.3", - "query-selector-shadow-dom": "^1.0.0", - "ua-parser-js": "^1.0.1", - "uuid": "^8.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/devtools-protocol": { - "version": "0.0.973690", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.973690.tgz", - "integrity": "sha512-myh3hSFp0YWa2GED11PmbLhV4dv9RdO7YUz27XJrbQLnP5bMbZL6dfOOILTHO57yH0kX5GfuOZBsg/4NamfPvQ==", - "dev": true - }, - "node_modules/devtools/node_modules/ua-parser-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.2.tgz", - "integrity": "sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - } - ], - "engines": { - "node": "*" - } - }, - "node_modules/devtools/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", - "dev": true - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/doctrine-temporary-fork": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.1.0.tgz", - "integrity": "sha512-nliqOv5NkE4zMON4UA6AMJE6As35afs8aYXATpU4pTUdIKiARZwrJVEP1boA3Rx1ZXHVkwxkhcq4VkqvsuRLsA==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/documentation": { - "version": "13.2.5", - "resolved": "https://registry.npmjs.org/documentation/-/documentation-13.2.5.tgz", - "integrity": "sha512-d1TrfrHXYZR63xrOzkYwwe297vkSwBoEhyyMBOi20T+7Ohe1aX1dW4nqXncQmdmE5MxluSaxxa3BW1dCvbF5AQ==", - "dev": true, - "dependencies": { - "@babel/core": "7.12.3", - "@babel/generator": "7.12.1", - "@babel/parser": "7.12.3", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "ansi-html": "^0.0.7", - "babelify": "^10.0.0", - "chalk": "^2.3.0", - "chokidar": "^3.4.0", - "concat-stream": "^1.6.0", - "diff": "^4.0.1", - "doctrine-temporary-fork": "2.1.0", - "get-port": "^5.0.0", - "git-url-parse": "^11.1.2", - "github-slugger": "1.2.0", - "glob": "^7.1.2", - "globals-docs": "^2.4.0", - "highlight.js": "^10.7.2", - "ini": "^1.3.5", - "js-yaml": "^3.10.0", - "lodash": "^4.17.10", - "mdast-util-find-and-replace": "^1.1.1", - "mdast-util-inject": "^1.1.0", - "micromatch": "^3.1.5", - "mime": "^2.2.0", - "module-deps-sortable": "^5.0.3", - "parse-filepath": "^1.0.2", - "pify": "^5.0.0", - "read-pkg-up": "^4.0.0", - "remark": "^13.0.0", - "remark-gfm": "^1.0.0", - "remark-html": "^13.0.1", - "remark-reference-links": "^5.0.0", - "remark-toc": "^7.2.0", - "resolve": "^1.8.1", - "stream-array": "^1.1.2", - "strip-json-comments": "^2.0.1", - "tiny-lr": "^1.1.0", - "unist-builder": "^2.0.3", - "unist-util-visit": "^2.0.3", - "vfile": "^4.0.0", - "vfile-reporter": "^6.0.0", - "vfile-sort": "^2.1.0", - "vinyl": "^2.1.0", - "vinyl-fs": "^3.0.2", - "yargs": "^15.3.1" - }, - "bin": { - "documentation": "bin/documentation.js" - }, - "engines": { - "node": ">=10" - }, - "optionalDependencies": { - "@vue/compiler-sfc": "^3.0.11", - "vue-template-compiler": "^2.6.12" - } - }, - "node_modules/documentation/node_modules/@babel/core": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz", - "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.1", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.1", - "@babel/parser": "^7.12.3", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/documentation/node_modules/@babel/generator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", - "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.12.1", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "node_modules/documentation/node_modules/@babel/parser": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz", - "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/documentation/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/documentation/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/documentation/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/documentation/node_modules/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 - }, - "node_modules/documentation/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/documentation/node_modules/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, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/documentation/node_modules/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, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/documentation/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/documentation/node_modules/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, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/documentation/node_modules/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, - "engines": { - "node": ">=6" - } - }, - "node_modules/documentation/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/documentation/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/documentation/node_modules/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, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/documentation/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/documentation/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "dependencies": { - "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": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/documentation/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "dependencies": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotgitignore": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", - "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/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, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/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, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/dotgitignore/node_modules/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, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/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, - "engines": { - "node": ">=6" - } - }, - "node_modules/dset": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/dset/-/dset-2.0.1.tgz", - "integrity": "sha512-nI29OZMRYq36hOcifB6HTjajNAAiBKSXsyWZrq+VniusseuP2OpNlTiYgsaNRSGvpyq5Wjbc2gQLyBdTyWqhnQ==", - "deprecated": "Please use dset@2.1.0 or later for an important security patch", - "engines": { - "node": ">=4" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" - } - }, - "node_modules/duplexify/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "node_modules/each-props/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/easy-table": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", - "integrity": "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "optionalDependencies": { - "wcwidth": "^1.0.1" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/edge-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/edge-paths/-/edge-paths-2.2.1.tgz", - "integrity": "sha512-AI5fC7dfDmCdKo3m5y7PkYE8m6bMqR6pvVpgtrZkkhcJXFLelUgkjrhk3kXXx8Kbw2cRaTT4LkOR7hqf39KJdw==", - "dev": true, - "dependencies": { - "@types/which": "^1.3.2", - "which": "^2.0.2" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "node_modules/ejs": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", - "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", - "dev": true, - "dependencies": { - "jake": "^10.6.1" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.78", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.78.tgz", - "integrity": "sha512-o61+D/Lx7j/E0LIin/efOqeHpXhwi1TaQco9vUcRmr91m25SfZY6L5hWJDv/r+6kNjboFKgBw1LbfM0lbhuK6Q==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", - "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", - "dev": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "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, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", - "dev": true, - "dependencies": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/engine.io-parser": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", - "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", - "dev": true, - "dependencies": { - "@socket.io/base64-arraybuffer": "~1.0.2" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", - "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", - "dev": true - }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", - "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", - "dev": true, - "dependencies": { - "string-template": "~0.2.1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", - "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.0", - "has-symbols": "^1.0.1", - "is-arguments": "^1.1.0", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.5", - "isarray": "^2.0.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "node_modules/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, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es5-ext": { - "version": "0.10.57", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.57.tgz", - "integrity": "sha512-L7cCNoPwTkAp7IBHxrKLsh7NKiVFkcdxlP9vbVw9QUvb7gF0Mz9bEBN0WY9xqdTjGF907EMT/iG013vnbqwu1Q==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es5-shim": { - "version": "4.6.5", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.6.5.tgz", - "integrity": "sha512-vfQ4UAai8szn0sAubCy97xnZ4sJVDD1gt/Grn736hg8D7540wemIb1YPrYZSTqlM2H69EQX1or4HU/tSwRTI3w==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=", - "dev": true - }, - "node_modules/es6-promise": { - "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 - }, - "node_modules/es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "dependencies": { - "es6-promise": "^4.0.3" - } - }, - "node_modules/es6-symbol": { - "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, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "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, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "dependencies": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=0.12.0" - }, - "optionalDependencies": { - "source-map": "~0.2.0" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-standard": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", - "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", - "dev": true, - "peerDependencies": { - "eslint": ">=3.19.0", - "eslint-plugin-import": ">=2.2.0", - "eslint-plugin-node": ">=4.2.2", - "eslint-plugin-promise": ">=3.5.0", - "eslint-plugin-standard": ">=3.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "resolve": "^1.20.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", - "dev": true, - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.25.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", - "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.2", - "has": "^1.0.3", - "is-core-module": "^2.8.0", - "is-glob": "^4.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.5", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.12.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", - "dev": true, - "dependencies": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-plugin-node/node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint-plugin-prebid": { - "resolved": "plugins/eslint", - "link": true - }, - "node_modules/eslint-plugin-promise": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz", - "integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==", - "dev": true, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.0.0" - } - }, - "node_modules/eslint-plugin-standard": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", - "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", - "dev": true, - "peerDependencies": { - "eslint": ">=3.19.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/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 - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "optional": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "node_modules/event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "node_modules/event-stream/node_modules/map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/execa/node_modules/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, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/execa/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/execa/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/execa/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/exit-on-epipe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", - "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/expect-webdriverio": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/expect-webdriverio/-/expect-webdriverio-3.1.4.tgz", - "integrity": "sha512-65FTS3bmxcIp0cq6fLb/72TrCQXBCpwPLC7SwMWdpPlLq461mXcK1BPKJJjnIC587aXSKD+3E4hvnlCtwDmXfg==", - "dev": true, - "dependencies": { - "expect": "^27.0.2", - "jest-matcher-utils": "^27.0.2" - } - }, - "node_modules/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/express/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", - "dev": true, - "dependencies": { - "type": "^2.5.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/faker": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", - "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==", - "dev": true - }, - "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/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, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/fibers": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/fibers/-/fibers-5.0.1.tgz", - "integrity": "sha512-VMC7Frt87Oo0AOJ6EcPFbi+tZmkQ4tD85aatwyWL6I9cYMJmm2e+pXUJsfGZ36U7MffXtjou2XIiWJMtHriErw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "detect-libc": "^1.0.3" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/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, - "optional": true - }, - "node_modules/filelist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", - "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", - "dev": true, - "dependencies": { - "minimatch": "^3.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fined/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "node_modules/foreachasync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", - "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=", - "dev": true - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/fork-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", - "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", - "dev": true - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "node_modules/fs-access": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", - "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true, - "dependencies": { - "null-check": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "node_modules/fs-extra": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", - "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fs-mkdirp-stream/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/fs.extra": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", - "integrity": "sha1-3QI/kwE77iRTHxszUUw3sg/ZM0k=", - "dev": true, - "dependencies": { - "fs-extra": "~0.6.1", - "mkdirp": "~0.3.5", - "walk": "^2.3.9" - }, - "engines": { - "node": "*" - } - }, - "node_modules/fs.extra/node_modules/fs-extra": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", - "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", - "dev": true, - "dependencies": { - "jsonfile": "~1.0.1", - "mkdirp": "0.3.x", - "ncp": "~0.4.2", - "rimraf": "~2.2.0" - } - }, - "node_modules/fs.extra/node_modules/jsonfile": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", - "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", - "dev": true - }, - "node_modules/fs.extra/node_modules/mkdirp": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", - "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dev": true - }, - "node_modules/fs.extra/node_modules/rimraf": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/fstream/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/fstream/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/fun-hooks": { - "version": "0.9.10", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.10.tgz", - "integrity": "sha512-7xBjdT+oMYOPWgwFxNiNzF4ubeUvim4zs1DnQqSSGyxu8UD7AW/6Z0iFsVRwuVSIZKUks2en2VHHotmNfj3ipw==", - "dependencies": { - "typescript-tuple": "^2.2.1" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "dependencies": { - "globule": "^1.0.0" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/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, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", - "dev": true, - "dependencies": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" - }, - "bin": { - "get-pkg-repo": "src/cli.js" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-pkg-repo/node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/get-pkg-repo/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/get-pkg-repo/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/get-pkg-repo/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", - "dev": true, - "dependencies": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "git-raw-commits": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/git-raw-commits/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/git-raw-commits/node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", - "dev": true, - "dependencies": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/git-remote-origin-url/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/git-semver-tags": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", - "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", - "dev": true, - "dependencies": { - "meow": "^8.0.0", - "semver": "^6.0.0" - }, - "bin": { - "git-semver-tags": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/git-up": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.5.tgz", - "integrity": "sha512-YUvVDg/vX3d0syBsk/CKUTib0srcQME0JyHkL5BaYdwLsiCslPWmDSi8PUMo9pXYjrryMcmsCoCgsTpSCJEQaA==", - "dev": true, - "dependencies": { - "is-ssh": "^1.3.0", - "parse-url": "^6.0.0" - } - }, - "node_modules/git-url-parse": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.6.0.tgz", - "integrity": "sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g==", - "dev": true, - "dependencies": { - "git-up": "^4.0.0" - } - }, - "node_modules/gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", - "dev": true, - "dependencies": { - "ini": "^1.3.2" - } - }, - "node_modules/github-slugger": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", - "integrity": "sha512-wIaa75k1vZhyPm9yWrD08A5Xnx/V+RmzGrpjQuLemGKSb77Qukiaei58Bogrl/LZSADDfPzKJX8jhLs4CRTl7Q==", - "dev": true, - "dependencies": { - "emoji-regex": ">=6.0.0 <=6.1.1" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-stream/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-stream/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-watcher/node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/glob-watcher/node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/glob-watcher/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/glob-watcher/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-watcher/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/glob-watcher/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/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, - "engines": { - "node": ">=4" - } - }, - "node_modules/globals-docs": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.1.tgz", - "integrity": "sha512-qpPnUKkWnz8NESjrCvnlGklsgiQzlq+rcCxoG5uNQ+dNA7cFMCmn231slLAwS2N/PlkzZ3COL8CcS10jXmLHqg==", - "dev": true - }, - "node_modules/globule": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.3.tgz", - "integrity": "sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg==", - "dev": true, - "dependencies": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/globule/node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/globule/node_modules/minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "dependencies": { - "sparkles": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/got": { - "version": "11.8.3", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", - "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "dependencies": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-clean": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/gulp-clean/-/gulp-clean-0.3.2.tgz", - "integrity": "sha1-o0fUc6zqQBgvk1WHpFGUFnGSgQI=", - "dev": true, - "dependencies": { - "gulp-util": "^2.2.14", - "rimraf": "^2.2.8", - "through2": "^0.4.2" - }, - "engines": { - "node": ">=0.9" - } - }, - "node_modules/gulp-clean/node_modules/ansi-regex": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/ansi-styles": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "dependencies": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/chalk": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true, - "dependencies": { - "ansi-styles": "^1.1.0", - "escape-string-regexp": "^1.0.0", - "has-ansi": "^0.1.0", - "strip-ansi": "^0.3.0", - "supports-color": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "node_modules/gulp-clean/node_modules/dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "dependencies": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - }, - "bin": { - "dateformat": "bin/cli.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/gulp-clean/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/gulp-util": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", - "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", - "deprecated": "gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5", - "dev": true, - "dependencies": { - "chalk": "^0.5.0", - "dateformat": "^1.0.7-1.2.3", - "lodash._reinterpolate": "^2.4.1", - "lodash.template": "^2.4.1", - "minimist": "^0.2.0", - "multipipe": "^0.1.0", - "through2": "^0.5.0", - "vinyl": "^0.2.1" - }, - "engines": { - "node": ">= 0.9" - } - }, - "node_modules/gulp-clean/node_modules/gulp-util/node_modules/through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" - } - }, - "node_modules/gulp-clean/node_modules/gulp-util/node_modules/xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/gulp-clean/node_modules/has-ansi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true, - "dependencies": { - "ansi-regex": "^0.2.0" - }, - "bin": { - "has-ansi": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "dependencies": { - "repeating": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/gulp-clean/node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/lodash._reinterpolate": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", - "dev": true - }, - "node_modules/gulp-clean/node_modules/lodash.defaults": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", - "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true, - "dependencies": { - "lodash._objecttypes": "~2.4.1", - "lodash.keys": "~2.4.1" - } - }, - "node_modules/gulp-clean/node_modules/lodash.template": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", - "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true, - "dependencies": { - "lodash._escapestringchar": "~2.4.1", - "lodash._reinterpolate": "~2.4.1", - "lodash.defaults": "~2.4.1", - "lodash.escape": "~2.4.1", - "lodash.keys": "~2.4.1", - "lodash.templatesettings": "~2.4.1", - "lodash.values": "~2.4.1" - } - }, - "node_modules/gulp-clean/node_modules/lodash.templatesettings": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true, - "dependencies": { - "lodash._reinterpolate": "~2.4.1", - "lodash.escape": "~2.4.1" - } - }, - "node_modules/gulp-clean/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "dependencies": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/meow/node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/gulp-clean/node_modules/minimist": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.1.tgz", - "integrity": "sha512-GY8fANSrTMfBVfInqJAY41QkOM+upUTytK1jZ0c8+3HdHrJxBJ3rF5i9moClXTE8uUSnUo8cAsCoxDXvSY4DHg==", - "dev": true - }, - "node_modules/gulp-clean/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "node_modules/gulp-clean/node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/gulp-clean/node_modules/redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "dependencies": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/gulp-clean/node_modules/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 - }, - "node_modules/gulp-clean/node_modules/strip-ansi": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true, - "dependencies": { - "ansi-regex": "^0.2.1" - }, - "bin": { - "strip-ansi": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "dependencies": { - "get-stdin": "^4.0.1" - }, - "bin": { - "strip-indent": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", - "dev": true, - "bin": { - "supports-color": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/through2": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", - "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.17", - "xtend": "~2.1.1" - } - }, - "node_modules/gulp-clean/node_modules/trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-clean/node_modules/vinyl": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", - "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "dependencies": { - "clone-stats": "~0.0.1" - }, - "engines": { - "node": ">= 0.9" - } - }, - "node_modules/gulp-clean/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "dependencies": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli/node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/gulp-cli/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "node_modules/gulp-cli/node_modules/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, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/gulp-cli/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/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, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "node_modules/gulp-cli/node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/gulp-cli/node_modules/yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - } - }, - "node_modules/gulp-cli/node_modules/yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "node_modules/gulp-concat": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", - "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "dependencies": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-concat/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/gulp-connect": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", - "dev": true, - "dependencies": { - "ansi-colors": "^2.0.5", - "connect": "^3.6.6", - "connect-livereload": "^0.6.0", - "fancy-log": "^1.3.2", - "map-stream": "^0.0.7", - "send": "^0.16.2", - "serve-index": "^1.9.1", - "serve-static": "^1.13.2", - "tiny-lr": "^1.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-connect/node_modules/ansi-colors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/gulp-connect/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/gulp-connect/node_modules/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, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/gulp-connect/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/gulp-connect/node_modules/mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true, - "bin": { - "mime": "cli.js" - } - }, - "node_modules/gulp-connect/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/gulp-connect/node_modules/send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/gulp-connect/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/gulp-connect/node_modules/statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/gulp-eslint": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", - "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", - "dev": true, - "dependencies": { - "eslint": "^4.0.0", - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.0" - } - }, - "node_modules/gulp-eslint/node_modules/acorn": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", - "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/gulp-eslint/node_modules/acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "dependencies": { - "acorn": "^3.0.4" - } - }, - "node_modules/gulp-eslint/node_modules/acorn-jsx/node_modules/acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/gulp-eslint/node_modules/ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "dependencies": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "node_modules/gulp-eslint/node_modules/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, - "peerDependencies": { - "ajv": "^5.0.0" - } - }, - "node_modules/gulp-eslint/node_modules/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, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "node_modules/gulp-eslint/node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true - }, - "node_modules/gulp-eslint/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "node_modules/gulp-eslint/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/gulp-eslint/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-eslint/node_modules/eslint": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", - "dev": true, - "dependencies": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", - "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^1.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", - "dev": true, - "dependencies": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/gulp-eslint/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "dependencies": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-eslint/node_modules/external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "dependencies": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/gulp-eslint/node_modules/fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "node_modules/gulp-eslint/node_modules/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "dependencies": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-eslint/node_modules/flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", - "dev": true, - "dependencies": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-eslint/node_modules/ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "node_modules/gulp-eslint/node_modules/inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - } - }, - "node_modules/gulp-eslint/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "node_modules/gulp-eslint/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/gulp-eslint/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/gulp-eslint/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/gulp-eslint/node_modules/mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "node_modules/gulp-eslint/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/gulp-eslint/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/gulp-eslint/node_modules/regexpp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/gulp-eslint/node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/gulp-eslint/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/gulp-eslint/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-eslint/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-eslint/node_modules/slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true, - "dependencies": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - } - }, - "node_modules/gulp-eslint/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/gulp-eslint/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/gulp-eslint/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "node_modules/gulp-footer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-2.1.0.tgz", - "integrity": "sha512-CK3nRBP3PG59XN2L1rDLkBHA7goYsW+tJuVQccLP9jq3mpBT2kuRq0ImgNjrUkDbF948aCVQH4J7uIEqiZ2MHA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.21", - "map-stream": "^0.0.7" - } - }, - "node_modules/gulp-header": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-2.0.9.tgz", - "integrity": "sha512-LMGiBx+qH8giwrOuuZXSGvswcIUh0OiioNkUpLhNyvaC6/Ga8X6cfAeme2L5PqsbXMhL8o8b/OmVqIQdxprhcQ==", - "dev": true, - "dependencies": { - "concat-with-sourcemaps": "^1.1.0", - "lodash.template": "^4.5.0", - "map-stream": "0.0.7", - "through2": "^2.0.0" - } - }, - "node_modules/gulp-header/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/gulp-if": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-3.0.0.tgz", - "integrity": "sha512-fCUEngzNiEZEK2YuPm+sdMpO6ukb8+/qzbGfJBXyNOXz85bCG7yBI+pPSl+N90d7gnLvMsarthsAImx0qy7BAw==", - "dev": true, - "dependencies": { - "gulp-match": "^1.1.0", - "ternary-stream": "^3.0.0", - "through2": "^3.0.1" - } - }, - "node_modules/gulp-if/node_modules/through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, - "node_modules/gulp-js-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gulp-js-escape/-/gulp-js-escape-1.0.1.tgz", - "integrity": "sha1-HNRF+9AJ4Np2lZoDp/SbNWav+Gg=", - "dev": true, - "dependencies": { - "through2": "^0.6.3" - } - }, - "node_modules/gulp-js-escape/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/gulp-js-escape/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/gulp-js-escape/node_modules/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 - }, - "node_modules/gulp-js-escape/node_modules/through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "dependencies": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "node_modules/gulp-match": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", - "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", - "dev": true, - "dependencies": { - "minimatch": "^3.0.3" - } - }, - "node_modules/gulp-replace": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.1.3.tgz", - "integrity": "sha512-HcPHpWY4XdF8zxYkDODHnG2+7a3nD/Y8Mfu3aBgMiCFDW3X2GiOKXllsAmILcxe3KZT2BXoN18WrpEFm48KfLQ==", - "dev": true, - "dependencies": { - "@types/node": "^14.14.41", - "@types/vinyl": "^2.0.4", - "istextorbinary": "^3.0.0", - "replacestream": "^4.0.3", - "yargs-parser": ">=5.0.0-security.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gulp-replace/node_modules/@types/node": { - "version": "14.18.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", - "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", - "dev": true - }, - "node_modules/gulp-shell": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.8.0.tgz", - "integrity": "sha512-wHNCgmqbWkk1c6Gc2dOL5SprcoeujQdeepICwfQRo91DIylTE7a794VEE+leq3cE2YDoiS5ulvRfKVIEMazcTQ==", - "dev": true, - "dependencies": { - "chalk": "^3.0.0", - "fancy-log": "^1.3.3", - "lodash.template": "^4.5.0", - "plugin-error": "^1.0.1", - "through2": "^3.0.1", - "tslib": "^1.10.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/gulp-shell/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/gulp-shell/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gulp-shell/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/gulp-shell/node_modules/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 - }, - "node_modules/gulp-shell/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gulp-shell/node_modules/through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, - "node_modules/gulp-sourcemaps": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-3.0.0.tgz", - "integrity": "sha512-RqvUckJkuYqy4VaIH60RMal4ZtG0IbQ6PXMNkNsshEGJ9cldUPRb/YCgboYae+CLAs1HQNb4ADTKCx65HInquQ==", - "dev": true, - "dependencies": { - "@gulp-sourcemaps/identity-map": "^2.0.1", - "@gulp-sourcemaps/map-sources": "^1.0.0", - "acorn": "^6.4.1", - "convert-source-map": "^1.0.0", - "css": "^3.0.0", - "debug-fabulous": "^1.0.0", - "detect-newline": "^2.0.0", - "graceful-fs": "^4.0.0", - "source-map": "^0.6.0", - "strip-bom-string": "^1.0.0", - "through2": "^2.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gulp-sourcemaps/node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/gulp-sourcemaps/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-sourcemaps/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/gulp-terser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-terser/-/gulp-terser-2.1.0.tgz", - "integrity": "sha512-lQ3+JUdHDVISAlUIUSZ/G9Dz/rBQHxOiYDQ70IVWFQeh4b33TC1MCIU+K18w07PS3rq/CVc34aQO4SUbdaNMPQ==", - "dev": true, - "dependencies": { - "plugin-error": "^1.0.1", - "terser": "^5.9.0", - "through2": "^4.0.2", - "vinyl-sourcemaps-apply": "^0.2.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "deprecated": "gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5", - "dev": true, - "dependencies": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/gulp-util/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-util/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-util/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-util/node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/gulp-util/node_modules/clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "node_modules/gulp-util/node_modules/lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "dependencies": { - "lodash._root": "^3.0.0" - } - }, - "node_modules/gulp-util/node_modules/lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "dependencies": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "node_modules/gulp-util/node_modules/lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "dependencies": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } - }, - "node_modules/gulp-util/node_modules/lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" - } - }, - "node_modules/gulp-util/node_modules/object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-util/node_modules/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, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-util/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/gulp-util/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/gulp-util/node_modules/vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "dependencies": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - }, - "engines": { - "node": ">= 0.9" - } - }, - "node_modules/gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "dependencies": { - "glogg": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/har-validator/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "dependencies": { - "sparkles": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hast-util-is-element": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz", - "integrity": "sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-sanitize": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-3.0.2.tgz", - "integrity": "sha512-+2I0x2ZCAyiZOO/sb4yNLFmdwPBnyJ4PBkVTUMKMqBwYNA+lXSgOmoRXlJFazoyid9QPogRRKgKhVEodv181sA==", - "dev": true, - "dependencies": { - "xtend": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-html": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-7.1.3.tgz", - "integrity": "sha512-yk2+1p3EJTEE9ZEUkgHsUSVhIpCsL/bvT8E5GzmWc+N1Po5gBw+0F8bo7dpxXR0nu0bQVxVZGX2lBGF21CmeDw==", - "dev": true, - "dependencies": { - "ccount": "^1.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-is-element": "^1.0.0", - "hast-util-whitespace": "^1.0.0", - "html-void-elements": "^1.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0", - "stringify-entities": "^3.0.1", - "unist-util-is": "^4.0.0", - "xtend": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz", - "integrity": "sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/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, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/html-void-elements": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", - "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", - "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", - "dev": true, - "dependencies": { - "agent-base": "5", - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/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, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/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, - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/inquirer": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.5.tgz", - "integrity": "sha512-G6/9xUqmt/r+UvufSyrPpt84NYwhKZ9jLsgMbQzlx804XErNupor8WQdBnBRrXmBfTPpuwf1sV+ss2ovjgdXIg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.2.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/inquirer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/inquirer/node_modules/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 - }, - "node_modules/inquirer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "dev": true, - "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/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, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extendable/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "node_modules/is-running": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-running/-/is-running-2.1.0.tgz", - "integrity": "sha1-MKc/9cw4VOT8JUkICen1q/jeCeA=", - "dev": true - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-ssh": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.3.tgz", - "integrity": "sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ==", - "dev": true, - "dependencies": { - "protocols": "^1.1.0" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", - "dev": true, - "dependencies": { - "text-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", - "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "node_modules/is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isbinaryfile": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", - "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", - "dev": true, - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.", - "dev": true, - "dependencies": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "istanbul": "lib/cli.js" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", - "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul/node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/istanbul/node_modules/has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/istanbul/node_modules/resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "node_modules/istanbul/node_modules/supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "dependencies": { - "has-flag": "^1.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/istanbul/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/istextorbinary": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-3.3.0.tgz", - "integrity": "sha512-Tvq1W6NAcZeJ8op+Hq7tdZ434rqnMx4CCZ7H0ff83uEloDvVbqAwaMTZcafKGJT0VHkYzuXUiCY4hlXQg6WfoQ==", - "dev": true, - "dependencies": { - "binaryextensions": "^2.2.0", - "textextensions": "^3.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://bevry.me/fund" - } - }, - "node_modules/jake": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", - "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", - "dev": true, - "dependencies": { - "async": "0.9.x", - "chalk": "^2.4.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jake/node_modules/async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "node_modules/jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-diff/node_modules/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 - }, - "node_modules/jest-diff/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "dev": true, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/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 - }, - "node_modules/jest-matcher-utils/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-message-util/node_modules/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 - }, - "node_modules/jest-message-util/node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/jest-message-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/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 - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/js-yaml/node_modules/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, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "node_modules/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 - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true, - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/just-clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/just-clone/-/just-clone-1.0.2.tgz", - "integrity": "sha1-v7P672WqEqMWBYcSlFwyb9jwFDQ=" - }, - "node_modules/just-debounce": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", - "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", - "dev": true - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "node_modules/karma": { - "version": "6.3.17", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.17.tgz", - "integrity": "sha512-2TfjHwrRExC8yHoWlPBULyaLwAFmXmxQrcuFImt/JsAsSZu1uOWTZ1ZsWjqQtWpHLiatJOHL5jFjXSJIgCd01g==", - "dev": true, - "dependencies": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.2.0", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" - }, - "bin": { - "karma": "bin/karma" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/karma-babel-preprocessor": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-8.0.2.tgz", - "integrity": "sha512-6ZUnHwaK2EyhgxbgeSJW6n6WZUYSEdekHIV/qDUnPgMkVzQBHEvd07d2mTL5AQjV8uTUgH6XslhaPrp+fHWH2A==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "@babel/core": "7" - } - }, - "node_modules/karma-browserstack-launcher": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.4.0.tgz", - "integrity": "sha512-bUQK84U+euDfOUfEjcF4IareySMOBNRLrrl9q6cttIe8f011Ir6olLITTYMOJDcGY58wiFIdhPHSPd9Pi6+NfQ==", - "dev": true, - "dependencies": { - "browserstack": "~1.5.1", - "browserstacktunnel-wrapper": "~2.0.2", - "q": "~1.5.0" - }, - "peerDependencies": { - "karma": ">=0.9" - } - }, - "node_modules/karma-chai": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", - "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", - "dev": true, - "peerDependencies": { - "chai": "*", - "karma": ">=0.10.9" - } - }, - "node_modules/karma-chrome-launcher": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", - "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", - "dev": true, - "dependencies": { - "which": "^1.2.1" - } - }, - "node_modules/karma-chrome-launcher/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/karma-coverage": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.0.tgz", - "integrity": "sha512-gPVdoZBNDZ08UCzdMHHhEImKrw1+PAOQOIiffv1YsvxFhBjqvo/SVXNk4tqn1SYqX0BJZT6S/59zgxiBe+9OuA==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.0.5", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/karma-coverage-istanbul-reporter": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-3.0.3.tgz", - "integrity": "sha512-wE4VFhG/QZv2Y4CdAYWDbMmcAHeS926ZIji4z+FkB2aF/EposRb6DP6G5ncT/wXhqUfAb/d7kZrNKPonbvsATw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^3.0.6", - "istanbul-reports": "^3.0.2", - "minimatch": "^3.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/mattlewis92" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/istanbul-lib-source-maps/node_modules/istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/karma-coverage/node_modules/istanbul-lib-instrument": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", - "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/karma-es5-shim": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/karma-es5-shim/-/karma-es5-shim-0.0.4.tgz", - "integrity": "sha1-zdADM8znfC5M4D46yT8vjs0fuVI=", - "dev": true, - "dependencies": { - "es5-shim": "^4.0.5" - } - }, - "node_modules/karma-firefox-launcher": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.2.tgz", - "integrity": "sha512-VV9xDQU1QIboTrjtGVD4NCfzIH7n01ZXqy/qpBhnOeGVOkG5JYPEm8kuSd7psHE6WouZaQ9Ool92g8LFweSNMA==", - "dev": true, - "dependencies": { - "is-wsl": "^2.2.0", - "which": "^2.0.1" - } - }, - "node_modules/karma-ie-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", - "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", - "dev": true, - "dependencies": { - "lodash": "^4.6.1" - }, - "peerDependencies": { - "karma": ">=0.9" - } - }, - "node_modules/karma-mocha": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-2.0.1.tgz", - "integrity": "sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.3" - } - }, - "node_modules/karma-mocha-reporter": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", - "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", - "dev": true, - "dependencies": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "strip-ansi": "^4.0.0" - }, - "peerDependencies": { - "karma": ">=0.13" - } - }, - "node_modules/karma-mocha-reporter/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/karma-mocha-reporter/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/karma-opera-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/karma-opera-launcher/-/karma-opera-launcher-1.0.0.tgz", - "integrity": "sha1-+lFihTGh0L6EstjcDX7iCfyP+Ro=", - "dev": true, - "peerDependencies": { - "karma": ">=0.9" - } - }, - "node_modules/karma-safari-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/karma-safari-launcher/-/karma-safari-launcher-1.0.0.tgz", - "integrity": "sha1-lpgqLMR9BmquccVTursoMZEVos4=", - "dev": true, - "peerDependencies": { - "karma": ">=0.9" - } - }, - "node_modules/karma-script-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/karma-script-launcher/-/karma-script-launcher-1.0.0.tgz", - "integrity": "sha1-zQF8TeXvCeWp2nkydhdhCN1LVC0=", - "dev": true, - "peerDependencies": { - "karma": ">=0.9" - } - }, - "node_modules/karma-sinon": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/karma-sinon/-/karma-sinon-1.0.5.tgz", - "integrity": "sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo=", - "dev": true, - "engines": { - "node": ">= 0.10.0" - }, - "peerDependencies": { - "karma": ">=0.10", - "sinon": "*" - } - }, - "node_modules/karma-sourcemap-loader": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.8.tgz", - "integrity": "sha512-zorxyAakYZuBcHRJE+vbrK2o2JXLFWK8VVjiT/6P+ltLBUGUvqTEkUiQ119MGdOrK7mrmxXHZF1/pfT6GgIZ6g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2" - } - }, - "node_modules/karma-spec-reporter": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.32.tgz", - "integrity": "sha1-LpxyB+pyZ3EmAln4K+y1QyCeRAo=", - "dev": true, - "dependencies": { - "colors": "^1.1.2" - }, - "peerDependencies": { - "karma": ">=0.9" - } - }, - "node_modules/karma-webpack": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-5.0.0.tgz", - "integrity": "sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "webpack-merge": "^4.1.5" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/karma/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/karma/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/karma/node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/karma/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/karma/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/keyv": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.1.tgz", - "integrity": "sha512-tGv1yP6snQVDSM4X6yxrv2zzq/EvpW+oYiUz6aueW1u9CtS8RzUQYxxmFwgZlO2jSgCxQbchhxaqXXp2hnKGpQ==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/konan": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/konan/-/konan-2.1.1.tgz", - "integrity": "sha512-7ZhYV84UzJ0PR/RJnnsMZcAbn+kLasJhVNWsu8ZyVEJYRpGA5XESQ9d/7zOa08U0Ou4cmB++hMNY/3OSV9KIbg==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.10.5", - "@babel/traverse": "^7.10.5" - } - }, - "node_modules/ky": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/ky/-/ky-0.29.0.tgz", - "integrity": "sha512-01TBSOqlHmLfcQhHseugGHLxPtU03OyZWaLDWt5MfzCkijG6xWFvAQPhKVn0cR2MMjYvBP9keQ8A3+rQEhLO5g==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/ky?sponsor=1" - } - }, - "node_modules/last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "dependencies": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lcov-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", - "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", - "dev": true, - "bin": { - "lcov-parse": "bin/cli.js" - } - }, - "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/liftoff/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lighthouse-logger": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.3.0.tgz", - "integrity": "sha512-BbqAKApLb9ywUli+0a+PcV04SyJ/N1q/8qgCNe6U97KbPCS1BTksEuHFLYdvc8DltuhfxIUBqDZsC0bBGtl3lA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "marky": "^1.2.2" - } - }, - "node_modules/lighthouse-logger/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/lighthouse-logger/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "node_modules/live-connect-js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-2.3.1.tgz", - "integrity": "sha512-4IT8NEOOTNmoYpw5CTxdugSF2w9xqfOujrEqx6zLPdTT3xq/lLdxxvRTREDi+qYHDsCDovdiNO3uOSoemdTCdA==", - "dependencies": { - "tiny-hashes": "1.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/livereload-js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", - "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", - "dev": true - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "node_modules/lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "node_modules/lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "node_modules/lodash._escapehtmlchar": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", - "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", - "dev": true, - "dependencies": { - "lodash._htmlescapes": "~2.4.1" - } - }, - "node_modules/lodash._escapestringchar": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", - "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", - "dev": true - }, - "node_modules/lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "node_modules/lodash._htmlescapes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", - "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", - "dev": true - }, - "node_modules/lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "node_modules/lodash._isnative": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", - "dev": true - }, - "node_modules/lodash._objecttypes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", - "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", - "dev": true - }, - "node_modules/lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "node_modules/lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "node_modules/lodash._reunescapedhtml": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", - "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true, - "dependencies": { - "lodash._htmlescapes": "~2.4.1", - "lodash.keys": "~2.4.1" - } - }, - "node_modules/lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "node_modules/lodash._shimkeys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true, - "dependencies": { - "lodash._objecttypes": "~2.4.1" - } - }, - "node_modules/lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", - "dev": true - }, - "node_modules/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 - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true - }, - "node_modules/lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", - "dev": true - }, - "node_modules/lodash.escape": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", - "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "dependencies": { - "lodash._escapehtmlchar": "~2.4.1", - "lodash._reunescapedhtml": "~2.4.1", - "lodash.keys": "~2.4.1" - } - }, - "node_modules/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 - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "node_modules/lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "node_modules/lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", - "dev": true - }, - "node_modules/lodash.isobject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=", - "dev": true - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "node_modules/lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "dependencies": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" - } - }, - "node_modules/lodash.keys/node_modules/lodash.isobject": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", - "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true, - "dependencies": { - "lodash._objecttypes": "~2.4.1" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.pickby": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", - "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=", - "dev": true - }, - "node_modules/lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "node_modules/lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", - "dev": true - }, - "node_modules/lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "dev": true, - "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "node_modules/lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "dev": true, - "dependencies": { - "lodash._reinterpolate": "^3.0.0" - } - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "node_modules/lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", - "dev": true - }, - "node_modules/lodash.values": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", - "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", - "dev": true, - "dependencies": { - "lodash.keys": "~2.4.1" - } - }, - "node_modules/lodash.zip": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", - "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=", - "dev": true - }, - "node_modules/log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "dev": true, - "engines": { - "node": ">=0.8.6" - } - }, - "node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log4js": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.2.tgz", - "integrity": "sha512-k80cggS2sZQLBwllpT1p06GtfvzMmSdUCkW96f0Hj83rKGJDAu2vZjt9B9ag2vx8Zz1IXzxoLgqvRJCdMKybGg==", - "dev": true, - "dependencies": { - "date-format": "^4.0.4", - "debug": "^4.3.3", - "flatted": "^3.2.5", - "rfdc": "^1.3.0", - "streamroller": "^3.0.4" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/loglevel": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", - "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - }, - "funding": { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/loglevel" - } - }, - "node_modules/loglevel-plugin-prefix": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz", - "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", - "dev": true - }, - "node_modules/lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", - "dev": true - }, - "node_modules/longest-streak": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", - "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "dependencies": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "dependencies": { - "es5-ext": "~0.10.2" - } - }, - "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "optional": true, - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/make-iterator/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", - "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", - "dev": true, - "dependencies": { - "repeat-string": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/marky": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.4.tgz", - "integrity": "sha512-zd2/GiSn6U3/jeFVZ0J9CA1LzQ8RfIVvXkb/U0swFHF/zT+dVohTAWjmo2DcIuofmIIIROlwTbd+shSeXmxr0w==", - "dev": true - }, - "node_modules/matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "dependencies": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/matchdep/node_modules/findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/matchdep/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mdast-util-definitions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", - "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", - "dev": true, - "dependencies": { - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz", - "integrity": "sha512-9cKl33Y21lyckGzpSmEQnIDjEfeeWelN5s1kUW1LwdB0Fkuq2u+4GdqcGEygYxJE8GVqCl0741bYXHgamfWAZA==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^4.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz", - "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-string": "^2.0.0", - "micromark": "~2.11.0", - "parse-entities": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-from-markdown/node_modules/mdast-util-to-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", - "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-0.1.2.tgz", - "integrity": "sha512-NNkhDx/qYcuOWB7xHUGWZYVXvjPFFd6afg6/e2g+SV4r9q5XUcCbV4Wfa3DLYIiD+xAEZc6K4MGaE/m0KDcPwQ==", - "dev": true, - "dependencies": { - "mdast-util-gfm-autolink-literal": "^0.1.0", - "mdast-util-gfm-strikethrough": "^0.2.0", - "mdast-util-gfm-table": "^0.1.0", - "mdast-util-gfm-task-list-item": "^0.1.0", - "mdast-util-to-markdown": "^0.6.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.3.tgz", - "integrity": "sha512-GjmLjWrXg1wqMIO9+ZsRik/s7PLwTaeCHVB7vRxUwLntZc8mzmTsLVr6HW1yLokcnhfURsn5zmSVdi3/xWWu1A==", - "dev": true, - "dependencies": { - "ccount": "^1.0.0", - "mdast-util-find-and-replace": "^1.1.0", - "micromark": "^2.11.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.3.tgz", - "integrity": "sha512-5OQLXpt6qdbttcDG/UxYY7Yjj3e8P7X16LzvpX8pIQPYJ/C2Z1qFGMmcw+1PZMUM3Z8wt8NRfYTvCni93mgsgA==", - "dev": true, - "dependencies": { - "mdast-util-to-markdown": "^0.6.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.6.tgz", - "integrity": "sha512-j4yDxQ66AJSBwGkbpFEp9uG/LS1tZV3P33fN1gkyRB2LoRL+RR3f76m0HPHaby6F4Z5xr9Fv1URmATlRRUIpRQ==", - "dev": true, - "dependencies": { - "markdown-table": "^2.0.0", - "mdast-util-to-markdown": "~0.6.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz", - "integrity": "sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A==", - "dev": true, - "dependencies": { - "mdast-util-to-markdown": "~0.6.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-inject": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", - "integrity": "sha1-2wa4tYW+lZotzS+H9HK6m3VvNnU=", - "dev": true, - "dependencies": { - "mdast-util-to-string": "^1.0.0" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz", - "integrity": "sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "mdast-util-definitions": "^4.0.0", - "mdurl": "^1.0.0", - "unist-builder": "^2.0.0", - "unist-util-generated": "^1.0.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz", - "integrity": "sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "longest-streak": "^2.0.0", - "mdast-util-to-string": "^2.0.0", - "parse-entities": "^2.0.0", - "repeat-string": "^1.0.0", - "zwitch": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/mdast-util-to-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", - "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", - "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-toc": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-5.1.0.tgz", - "integrity": "sha512-csimbRIVkiqc+PpFeKDGQ/Ck2N4f9FYH3zzBMMJzcxoKL8m+cM0n94xXm0I9eaxHnKdY9n145SGTdyJC7i273g==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.3", - "@types/unist": "^2.0.3", - "extend": "^3.0.2", - "github-slugger": "^1.2.1", - "mdast-util-to-string": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-toc/node_modules/github-slugger": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", - "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==", - "dev": true - }, - "node_modules/mdast-util-toc/node_modules/mdast-util-to-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", - "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, - "node_modules/memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/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, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/meow/node_modules/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, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/meow/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/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, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/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, - "engines": { - "node": ">=6" - } - }, - "node_modules/meow/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/read-pkg-up/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/meow/node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "node_modules/merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/merge-source-map/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromark": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz", - "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "debug": "^4.0.0", - "parse-entities": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-0.3.3.tgz", - "integrity": "sha512-oVN4zv5/tAIA+l3GbMi7lWeYpJ14oQyJ3uEim20ktYFAcfX1x3LNlFGGlmrZHt7u9YlKExmyJdDGaTt6cMSR/A==", - "dev": true, - "dependencies": { - "micromark": "~2.11.0", - "micromark-extension-gfm-autolink-literal": "~0.5.0", - "micromark-extension-gfm-strikethrough": "~0.6.5", - "micromark-extension-gfm-table": "~0.4.0", - "micromark-extension-gfm-tagfilter": "~0.3.0", - "micromark-extension-gfm-task-list-item": "~0.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz", - "integrity": "sha512-ePiDGH0/lhcngCe8FtH4ARFoxKTUelMp4L7Gg2pujYD5CSMb9PbblnyL+AAMud/SNMyusbS2XDSiPIRcQoNFAw==", - "dev": true, - "dependencies": { - "micromark": "~2.11.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.5.tgz", - "integrity": "sha512-PpOKlgokpQRwUesRwWEp+fHjGGkZEejj83k9gU5iXCbDG+XBA92BqnRKYJdfqfkrRcZRgGuPuXb7DaK/DmxOhw==", - "dev": true, - "dependencies": { - "micromark": "~2.11.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.3.tgz", - "integrity": "sha512-hVGvESPq0fk6ALWtomcwmgLvH8ZSVpcPjzi0AjPclB9FsVRgMtGZkUcpE0zgjOCFAznKepF4z3hX8z6e3HODdA==", - "dev": true, - "dependencies": { - "micromark": "~2.11.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz", - "integrity": "sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz", - "integrity": "sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ==", - "dev": true, - "dependencies": { - "micromark": "~2.11.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dependencies": { - "mime-db": "1.51.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/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, - "engines": { - "node": ">=6" - } - }, - "node_modules/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, - "engines": { - "node": ">=4" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minimist-options/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, - "node_modules/mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "dependencies": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/mocha/node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "node_modules/mocha/node_modules/mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dev": true, - "dependencies": { - "minimist": "0.0.8" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/module-deps-sortable": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-5.0.3.tgz", - "integrity": "sha512-eiyIZj/A0dj1o4ywXWqicazUL3l0HP3TydUR6xF0X3xh3LGBMLqW8a9aFe6MuNH4mxNMk53QKBHM6LOPR8kSgw==", - "dev": true, - "dependencies": { - "browser-resolve": "^1.7.0", - "cached-path-relative": "^1.0.0", - "concat-stream": "~1.5.0", - "defined": "^1.0.0", - "detective": "^5.2.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "JSONStream": "^1.0.3", - "konan": "^2.1.1", - "readable-stream": "^2.0.2", - "resolve": "^1.1.3", - "standard-version": "^9.0.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - }, - "bin": { - "module-deps": "bin/cmd.js" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/module-deps-sortable/node_modules/concat-stream": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "inherits": "~2.0.1", - "readable-stream": "~2.0.0", - "typedarray": "~0.0.5" - } - }, - "node_modules/module-deps-sortable/node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/module-deps-sortable/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/module-deps-sortable/node_modules/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 - }, - "node_modules/module-deps-sortable/node_modules/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 - }, - "node_modules/module-deps-sortable/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", - "dev": true, - "dependencies": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/morgan/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/morgan/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/morgan/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/mrmime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", - "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/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 - }, - "node_modules/multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "dependencies": { - "duplexer2": "0.0.2" - } - }, - "node_modules/multipipe/node_modules/duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "dependencies": { - "readable-stream": "~1.1.9" - } - }, - "node_modules/multipipe/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/multipipe/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/multipipe/node_modules/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 - }, - "node_modules/mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "dev": true, - "optional": true - }, - "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "dev": true, - "optional": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/ncp": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", - "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", - "dev": true, - "bin": { - "ncp": "bin/ncp" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/nise": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", - "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", - "dev": true, - "dependencies": { - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^5.0.1", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/formatio": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } - }, - "node_modules/nise/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/nise/node_modules/lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/nise/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", - "dev": true - }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/null-check": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", - "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/object-copy/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/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, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true, - "dependencies": { - "is-wsl": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/opn/node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/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 - }, - "node_modules/ora/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-iteration": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/p-iteration/-/p-iteration-1.1.8.tgz", - "integrity": "sha512-IMFBSDIYcPNnW7uWYGrBqmvTiq7W0uB0fJn6shQZs7dlF3OvrHOre+JT9ikSZ7gZS3vWqclVgoQSvToJrns7uQ==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/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, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", - "dev": true, - "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/parse-ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", - "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-path": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.3.tgz", - "integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==", - "dev": true, - "dependencies": { - "is-ssh": "^1.3.0", - "protocols": "^1.4.0", - "qs": "^6.9.4", - "query-string": "^6.13.8" - } - }, - "node_modules/parse-url": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz", - "integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==", - "dev": true, - "dependencies": { - "is-ssh": "^1.3.0", - "normalize-url": "^6.1.0", - "parse-path": "^4.0.0", - "protocols": "^1.4.0" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-type/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "dependencies": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/plugin-error/node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss": { - "version": "8.4.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.8.tgz", - "integrity": "sha512-2tXEqGxrjvAO6U+CJzDL2Fk2kPHTv1jQsYkSoMeOis2SsYaXRO2COxTdQp99cYvif9JTXaAk9lYGc3VhJt7JPQ==", - "dev": true, - "optional": true, - "dependencies": { - "nanoid": "^3.3.1", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pretty-ms": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", - "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", - "dev": true, - "dependencies": { - "parse-ms": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/printj": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", - "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==", - "dev": true, - "bin": { - "printj": "bin/printj.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/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, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/property-information": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", - "dev": true, - "dependencies": { - "xtend": "^4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/protocols": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", - "integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==", - "dev": true - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "dev": true, - "dependencies": { - "event-stream": "=3.3.4" - }, - "bin": { - "ps-tree": "bin/ps-tree.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/puppeteer-core": { - "version": "13.5.1", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.5.1.tgz", - "integrity": "sha512-dobVqWjV34ilyfQHR3BBnCYaekBYTi5MgegEYBRYd3s3uFy8jUpZEEWbaFjG9ETm+LGzR5Lmr0aF6LLuHtiuCg==", - "dev": true, - "dependencies": { - "cross-fetch": "3.1.5", - "debug": "4.3.3", - "devtools-protocol": "0.0.969999", - "extract-zip": "2.0.1", - "https-proxy-agent": "5.0.0", - "pkg-dir": "4.2.0", - "progress": "2.0.3", - "proxy-from-env": "1.1.0", - "rimraf": "3.0.2", - "tar-fs": "2.1.1", - "unbzip2-stream": "1.4.3", - "ws": "8.5.0" - }, - "engines": { - "node": ">=10.18.1" - } - }, - "node_modules/puppeteer-core/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/puppeteer-core/node_modules/devtools-protocol": { - "version": "0.0.969999", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.969999.tgz", - "integrity": "sha512-6GfzuDWU0OFAuOvBokXpXPLxjOJ5DZ157Ue3sGQQM3LgAamb8m0R0ruSfN0DDu+XG5XJgT50i6zZ/0o8RglreQ==", - "dev": true - }, - "node_modules/puppeteer-core/node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/puppeteer-core/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true, - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", - "dev": true, - "engines": { - "node": ">=0.9" - } - }, - "node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/query-selector-shadow-dom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.0.tgz", - "integrity": "sha512-bK0/0cCI+R8ZmOF1QjT7HupDUYCxbf/9TJgAmSXQxZpftXmTAeil9DRoCnTDkWbvOyZzhcMBwKpptWcdkGFIMg==", - "dev": true - }, - "node_modules/query-string": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", - "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", - "dev": true, - "dependencies": { - "decode-uri-component": "^0.2.0", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/read-pkg-up/node_modules/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, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/read-pkg-up/node_modules/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, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/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, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/read-pkg-up/node_modules/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, - "engines": { - "node": ">=6" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/readdir-glob": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", - "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", - "dev": true, - "dependencies": { - "minimatch": "^3.0.4" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/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, - "dependencies": { - "minimatch": "3.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/recursive-readdir/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", - "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, - "node_modules/regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", - "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/regexpu-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", - "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.0.1", - "regjsgen": "^0.6.0", - "regjsparser": "^0.8.2", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", - "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", - "dev": true - }, - "node_modules/regjsparser": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", - "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/remark": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/remark/-/remark-13.0.0.tgz", - "integrity": "sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA==", - "dev": true, - "dependencies": { - "remark-parse": "^9.0.0", - "remark-stringify": "^9.0.0", - "unified": "^9.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-gfm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-1.0.0.tgz", - "integrity": "sha512-KfexHJCiqvrdBZVbQ6RopMZGwaXz6wFJEfByIuEwGf0arvITHjiKKZ1dpXujjH9KZdm1//XJQwgfnJ3lmXaDPA==", - "dev": true, - "dependencies": { - "mdast-util-gfm": "^0.1.0", - "micromark-extension-gfm": "^0.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-html": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-13.0.2.tgz", - "integrity": "sha512-LhSRQ+3RKdBqB/RGesFWkNNfkGqprDUCwjq54SylfFeNyZby5kqOG8Dn/vYsRoM8htab6EWxFXCY6XIZvMoRiQ==", - "dev": true, - "dependencies": { - "hast-util-sanitize": "^3.0.0", - "hast-util-to-html": "^7.0.0", - "mdast-util-to-hast": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz", - "integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==", - "dev": true, - "dependencies": { - "mdast-util-from-markdown": "^0.8.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-reference-links": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-5.0.0.tgz", - "integrity": "sha512-oSIo6lfDyG/1yYl2jPZNXmD9dgyPxp07mSd7snJagVMsDU6NRlD8i54MwHWUgMoOHTs8lIKPkwaUok/tbr5syQ==", - "dev": true, - "dependencies": { - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-stringify": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.1.tgz", - "integrity": "sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==", - "dev": true, - "dependencies": { - "mdast-util-to-markdown": "^0.6.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-toc": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-7.2.0.tgz", - "integrity": "sha512-ppHepvpbg7j5kPFmU5rzDC4k2GTcPDvWcxXyr/7BZzO1cBSPk0stKtEJdsgAyw2WHKPGxadcHIZRjb2/sHxjkg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.3", - "mdast-util-toc": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-buffer/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-bom-stream/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "dependencies": { - "is-finite": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/replacestream": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", - "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.3", - "object-assign": "^4.0.1", - "readable-stream": "^2.0.2" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "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.3", - "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.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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 - }, - "node_modules/require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "dependencies": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-uncached/node_modules/resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/responselike": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", - "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", - "dev": true, - "dependencies": { - "lowercase-keys": "^2.0.0" - } - }, - "node_modules/resq": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/resq/-/resq-1.10.2.tgz", - "integrity": "sha512-HmgVS3j+FLrEDBTDYysPdPVF9/hioDMJ/otOiQDKqk77YfZeeLOj0qi34yObumcud1gBpk+wpBTEg4kMicD++A==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^2.0.1" - } - }, - "node_modules/resq/node_modules/fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/rgb2hex": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz", - "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "node_modules/rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "dependencies": { - "rx-lite": "*" - } - }, - "node_modules/rxjs": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", - "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/rxjs/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/safe-json-parse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", - "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", - "dev": true - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "deprecated": "This package has been deprecated in favour of @sinonjs/samsam", - "dev": true - }, - "node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "dependencies": { - "sver-compat": "^1.5.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/serialize-error": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", - "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/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, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "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, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sinon": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", - "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@sinonjs/formatio": "^2.0.0", - "diff": "^3.1.0", - "lodash.get": "^4.4.2", - "lolex": "^2.2.0", - "nise": "^1.2.0", - "supports-color": "^5.1.0", - "type-detect": "^4.0.5" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/sinon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/sinon/node_modules/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, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/sirv": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", - "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", - "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^1.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/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 - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/snapdragon/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/snapdragon/node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/socket.io": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", - "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", - "dev": true - }, - "node_modules/socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", - "dev": true, - "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", - "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated", - "dev": true - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true, - "optional": true - }, - "node_modules/space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "node_modules/split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", - "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", - "dev": true, - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/standard-version": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.2.tgz", - "integrity": "sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "conventional-changelog": "3.1.24", - "conventional-changelog-config-spec": "2.1.0", - "conventional-changelog-conventionalcommits": "4.6.1", - "conventional-recommended-bump": "6.1.0", - "detect-indent": "^6.0.0", - "detect-newline": "^3.1.0", - "dotgitignore": "^2.1.0", - "figures": "^3.1.0", - "find-up": "^5.0.0", - "fs-access": "^1.0.1", - "git-semver-tags": "^4.0.0", - "semver": "^7.1.1", - "stringify-package": "^1.0.1", - "yargs": "^16.0.0" - }, - "bin": { - "standard-version": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/standard-version/node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/standard-version/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/standard-version/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/standard-version/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/standard-version/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/standard-version/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/standard-version/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/standard-version/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/standard-version/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/static-extend/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stream-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", - "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", - "dev": true, - "dependencies": { - "readable-stream": "~2.1.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stream-array/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/stream-array/node_modules/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 - }, - "node_modules/stream-array/node_modules/readable-stream": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", - "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "dev": true, - "dependencies": { - "buffer-shims": "^1.0.0", - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/stream-array/node_modules/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 - }, - "node_modules/stream-buffers": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", - "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1" - } - }, - "node_modules/stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, - "dependencies": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "node_modules/stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "node_modules/streamroller": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.4.tgz", - "integrity": "sha512-GI9NzeD+D88UFuIlJkKNDH/IsuR+qIN7Qh8EsmhoRZr9bQoehTraRgwtLUkZbpcAw+hLPfHOypmppz8YyGK68w==", - "dev": true, - "dependencies": { - "date-format": "^4.0.4", - "debug": "^4.3.3", - "fs-extra": "^10.0.1" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", - "dev": true - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/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 - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/stringify-entities": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.1.0.tgz", - "integrity": "sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg==", - "dev": true, - "dependencies": { - "character-entities-html4": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "xtend": "^4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/stringify-package": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", - "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", - "dev": true - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true, - "dependencies": { - "minimist": "^1.1.0" - } - }, - "node_modules/suffix": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/suffix/-/suffix-0.1.1.tgz", - "integrity": "sha1-zFgjFkag7xEC95R47zqSSP2chC8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "dependencies": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/temp-fs": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/temp-fs/-/temp-fs-0.9.9.tgz", - "integrity": "sha1-gHFzBDeHByDpQxUy/igUNk+IA9c=", - "dev": true, - "dependencies": { - "rimraf": "~2.5.2" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/temp-fs/node_modules/rimraf": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", - "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", - "dev": true, - "dependencies": { - "glob": "^7.0.5" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/ternary-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-3.0.0.tgz", - "integrity": "sha512-oIzdi+UL/JdktkT+7KU5tSIQjj8pbShj3OASuvDEhm0NT5lppsm7aXWAmAq4/QMaBIyfuEcNLbAQA+HpaISobQ==", - "dev": true, - "dependencies": { - "duplexify": "^4.1.1", - "fork-stream": "^0.0.4", - "merge-stream": "^2.0.0", - "through2": "^3.0.1" - } - }, - "node_modules/ternary-stream/node_modules/through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, - "node_modules/terser": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.0.tgz", - "integrity": "sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A==", - "dev": true, - "dependencies": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", - "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", - "dev": true, - "dependencies": { - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser-webpack-plugin/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/terser/node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/textextensions": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-3.3.0.tgz", - "integrity": "sha512-mk82dS8eRABNbeVJrEiN5/UMSCliINAuz8mkUwH4SwslkNP//gbEzlWNS5au0z5Dpx40SQxzqZevZkn+WYJ9Dw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://bevry.me/fund" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/through2-filter/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "dependencies": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, - "node_modules/tiny-hashes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tiny-hashes/-/tiny-hashes-1.0.1.tgz", - "integrity": "sha512-knIN5zj4fl7kW4EBU5sLP20DWUvi/rVouvJezV0UAym2DkQaqm365Nyc8F3QEiOvunNDMxR8UhcXd1d5g+Wg1g==" - }, - "node_modules/tiny-lr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", - "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", - "dev": true, - "dependencies": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" - } - }, - "node_modules/tiny-lr/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/to-regex-range/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/to-through/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/trough": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", - "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz", - "integrity": "sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/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, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", - "dev": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/typescript-compare": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz", - "integrity": "sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA==", - "dependencies": { - "typescript-logic": "^0.0.0" - } - }, - "node_modules/typescript-logic": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz", - "integrity": "sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q==" - }, - "node_modules/typescript-tuple": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz", - "integrity": "sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==", - "dependencies": { - "typescript-compare": "^0.0.2" - } - }, - "node_modules/ua-parser-js": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", - "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - } - ], - "engines": { - "node": "*" - } - }, - "node_modules/uglify-js": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.2.tgz", - "integrity": "sha512-peeoTk3hSwYdoc9nrdiEJk+gx1ALCtTjdYuKSXMTDqq7n1W7dHPqWDdSi+BPL0ni2YMeHD7hKUSdbj3TZauY2A==", - "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/undertaker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", - "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "fast-levenshtein": "^1.0.0", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker/node_modules/fast-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", - "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", - "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unified": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz", - "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==", - "dev": true, - "dependencies": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/union-value": { - "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, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/union-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "node_modules/unist-builder": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", - "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-generated": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", - "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", - "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", - "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/unzipper": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.15.tgz", - "integrity": "sha512-2aaUvO4RAeHDvOCuEtth7jrHFaCKTSXPqUkXwADaLBzGbgZGzUDccoEdJ5lW+3RmfpOZYNx0Rw6F6PUzM6caIA==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "engines": { - "node": ">=4", - "yarn": "*" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/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 - }, - "node_modules/vfile": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", - "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^2.0.0", - "vfile-message": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", - "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-reporter": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-6.0.2.tgz", - "integrity": "sha512-GN2bH2gs4eLnw/4jPSgfBjo+XCuvnX9elHICJZjVD4+NM0nsUrMTvdjGY5Sc/XG69XVTgLwj7hknQVc6M9FukA==", - "dev": true, - "dependencies": { - "repeat-string": "^1.5.0", - "string-width": "^4.0.0", - "supports-color": "^6.0.0", - "unist-util-stringify-position": "^2.0.0", - "vfile-sort": "^2.1.2", - "vfile-statistics": "^1.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-reporter/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/vfile-reporter/node_modules/supports-color": { - "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, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/vfile-sort": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.2.tgz", - "integrity": "sha512-tAyUqD2R1l/7Rn7ixdGkhXLD3zsg+XLAeUDUhXearjfIcpL1Hcsj5hHpCoy/gvfK/Ws61+e972fm0F7up7hfYA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-statistics": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.4.tgz", - "integrity": "sha512-lXhElVO0Rq3frgPvFBwahmed3X03vjPF8OcjKMy8+F1xU/3Q3QU3tKEDp743SFtb74PdF0UWpxPvtOP0GCLheA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "dependencies": { - "source-map": "^0.5.1" - } - }, - "node_modules/vinyl/node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vue-template-compiler": { - "version": "2.6.14", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz", - "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==", - "dev": true, - "optional": true, - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "node_modules/walk": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.15.tgz", - "integrity": "sha512-4eRTBZljBfIISK1Vnt69Gvr2w/wc3U6Vtrw7qiN5iqYJPH7LElcYh/iU4XWhdCy2dZqv1ToMyYlybDylfG/5Vg==", - "dev": true, - "dependencies": { - "foreachasync": "^3.0.0" - } - }, - "node_modules/watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webdriver": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-7.16.16.tgz", - "integrity": "sha512-x8UoG9k/P8KDrfSh1pOyNevt9tns3zexoMxp9cKnyA/7HYSErhZYTLGlgxscAXLtQG41cMH/Ba/oBmOx7Hgd8w==", - "dev": true, - "dependencies": { - "@types/node": "^17.0.4", - "@wdio/config": "7.16.16", - "@wdio/logger": "7.16.0", - "@wdio/protocols": "7.16.7", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "got": "^11.0.2", - "ky": "^0.29.0", - "lodash.merge": "^4.6.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/webdriverio": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-7.16.16.tgz", - "integrity": "sha512-caPaEWyuD3Qoa7YkW4xCCQA4v9Pa9wmhFGPvNZh3ERtjMCNi8L/XXOdkekWNZmFh3tY0kFguBj7+fAwSY7HAGw==", - "dev": true, - "dependencies": { - "@types/aria-query": "^5.0.0", - "@types/node": "^17.0.4", - "@wdio/config": "7.16.16", - "@wdio/logger": "7.16.0", - "@wdio/protocols": "7.16.7", - "@wdio/repl": "7.16.14", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "archiver": "^5.0.0", - "aria-query": "^5.0.0", - "css-shorthand-properties": "^1.1.1", - "css-value": "^0.0.1", - "devtools": "7.16.16", - "devtools-protocol": "^0.0.973690", - "fs-extra": "^10.0.0", - "get-port": "^5.1.1", - "grapheme-splitter": "^1.0.2", - "lodash.clonedeep": "^4.5.0", - "lodash.isobject": "^3.0.2", - "lodash.isplainobject": "^4.0.6", - "lodash.zip": "^4.2.0", - "minimatch": "^5.0.0", - "puppeteer-core": "^13.1.3", - "query-selector-shadow-dom": "^1.0.0", - "resq": "^1.9.1", - "rgb2hex": "0.2.5", - "serialize-error": "^8.0.0", - "webdriver": "7.16.16" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/webdriverio/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/webdriverio/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "node_modules/webpack": { - "version": "5.70.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", - "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.2", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-bundle-analyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", - "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", - "dev": true, - "dependencies": { - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "chalk": "^4.1.0", - "commander": "^7.2.0", - "gzip-size": "^6.0.0", - "lodash": "^4.17.20", - "opener": "^1.5.2", - "sirv": "^1.0.7", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/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 - }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/webpack-merge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", - "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-7.0.0.tgz", - "integrity": "sha512-XoAQTHyCaYMo6TS7Atv1HYhtmBgKiVLONJbzLBl2V3eibXQ2IT/MCRM841RW/r3vToKD5ivrTJFWgd/ghoxoRg==", - "dev": true, - "dependencies": { - "fancy-log": "^1.3.3", - "lodash.clone": "^4.3.2", - "lodash.some": "^4.2.2", - "memory-fs": "^0.5.0", - "plugin-error": "^1.0.1", - "supports-color": "^8.1.1", - "through": "^2.3.8", - "vinyl": "^2.2.1" - }, - "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "webpack": "^5.21.2" - } - }, - "node_modules/webpack/node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/webpack/node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/which-typed-array": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", - "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "node_modules/workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/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 - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "dependencies": { - "mkdirp": "^0.5.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/write/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", - "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", - "dev": true - }, - "node_modules/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yarn-install": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yarn-install/-/yarn-install-1.0.0.tgz", - "integrity": "sha1-V/RQULgu/VcYKzlzxUqgXLXSUjA=", - "dev": true, - "dependencies": { - "cac": "^3.0.3", - "chalk": "^1.1.3", - "cross-spawn": "^4.0.2" - }, - "bin": { - "yarn-install": "bin/yarn-install.js", - "yarn-remove": "bin/yarn-remove.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yarn-install/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yarn-install/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yarn-install/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yarn-install/node_modules/cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "node_modules/yarn-install/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/yarn-install/node_modules/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, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yarn-install/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/yarn-install/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/yarn-install/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zip-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", - "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", - "dev": true, - "dependencies": { - "archiver-utils": "^2.1.0", - "compress-commons": "^4.1.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/zip-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/zwitch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", - "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "plugins/eslint": { - "name": "eslint-plugin-prebid", - "version": "1.0.0", - "dev": true, - "license": "Apache-2.0" - } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.0" - } - }, - "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/compat-data": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", - "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", - "dev": true - }, - "@babel/core": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", - "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.3", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - } - }, - "@babel/eslint-parser": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.17.0.tgz", - "integrity": "sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA==", - "dev": true, - "requires": { - "eslint-scope": "^5.1.1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.0" - } - }, - "@babel/generator": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", - "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", - "dev": true, - "requires": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", - "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", - "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", - "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.16.4", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz", - "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", - "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "regexpu-core": "^5.0.1" - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", - "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - } - }, - "@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", - "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz", - "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-module-transforms": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz", - "integrity": "sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", - "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", - "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-wrap-function": "^7.16.8", - "@babel/types": "^7.16.8" - } - }, - "@babel/helper-replace-supers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", - "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-simple-access": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", - "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", - "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", - "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.8", - "@babel/types": "^7.16.8" - } - }, - "@babel/helpers": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", - "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", - "dev": true, - "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.0", - "@babel/types": "^7.17.0" - } - }, - "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", - "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", - "dev": true - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", - "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", - "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.16.7" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", - "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-remap-async-to-generator": "^7.16.8", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", - "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-proposal-class-static-block": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz", - "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.17.6", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", - "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", - "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", - "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", - "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", - "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", - "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", - "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.0", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.16.7" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", - "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", - "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.16.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", - "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.10", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", - "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", - "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", - "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", - "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-remap-async-to-generator": "^7.16.8" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", - "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", - "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", - "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", - "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz", - "integrity": "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", - "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", - "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", - "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", - "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", - "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", - "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", - "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", - "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz", - "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-simple-access": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz", - "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", - "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", - "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", - "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", - "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", - "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", - "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", - "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", - "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", - "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", - "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", - "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", - "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", - "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", - "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", - "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/preset-env": { - "version": "7.16.11", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", - "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.16.8", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", - "@babel/plugin-proposal-async-generator-functions": "^7.16.8", - "@babel/plugin-proposal-class-properties": "^7.16.7", - "@babel/plugin-proposal-class-static-block": "^7.16.7", - "@babel/plugin-proposal-dynamic-import": "^7.16.7", - "@babel/plugin-proposal-export-namespace-from": "^7.16.7", - "@babel/plugin-proposal-json-strings": "^7.16.7", - "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", - "@babel/plugin-proposal-numeric-separator": "^7.16.7", - "@babel/plugin-proposal-object-rest-spread": "^7.16.7", - "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", - "@babel/plugin-proposal-optional-chaining": "^7.16.7", - "@babel/plugin-proposal-private-methods": "^7.16.11", - "@babel/plugin-proposal-private-property-in-object": "^7.16.7", - "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.16.7", - "@babel/plugin-transform-async-to-generator": "^7.16.8", - "@babel/plugin-transform-block-scoped-functions": "^7.16.7", - "@babel/plugin-transform-block-scoping": "^7.16.7", - "@babel/plugin-transform-classes": "^7.16.7", - "@babel/plugin-transform-computed-properties": "^7.16.7", - "@babel/plugin-transform-destructuring": "^7.16.7", - "@babel/plugin-transform-dotall-regex": "^7.16.7", - "@babel/plugin-transform-duplicate-keys": "^7.16.7", - "@babel/plugin-transform-exponentiation-operator": "^7.16.7", - "@babel/plugin-transform-for-of": "^7.16.7", - "@babel/plugin-transform-function-name": "^7.16.7", - "@babel/plugin-transform-literals": "^7.16.7", - "@babel/plugin-transform-member-expression-literals": "^7.16.7", - "@babel/plugin-transform-modules-amd": "^7.16.7", - "@babel/plugin-transform-modules-commonjs": "^7.16.8", - "@babel/plugin-transform-modules-systemjs": "^7.16.7", - "@babel/plugin-transform-modules-umd": "^7.16.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", - "@babel/plugin-transform-new-target": "^7.16.7", - "@babel/plugin-transform-object-super": "^7.16.7", - "@babel/plugin-transform-parameters": "^7.16.7", - "@babel/plugin-transform-property-literals": "^7.16.7", - "@babel/plugin-transform-regenerator": "^7.16.7", - "@babel/plugin-transform-reserved-words": "^7.16.7", - "@babel/plugin-transform-shorthand-properties": "^7.16.7", - "@babel/plugin-transform-spread": "^7.16.7", - "@babel/plugin-transform-sticky-regex": "^7.16.7", - "@babel/plugin-transform-template-literals": "^7.16.7", - "@babel/plugin-transform-typeof-symbol": "^7.16.7", - "@babel/plugin-transform-unicode-escapes": "^7.16.7", - "@babel/plugin-transform-unicode-regex": "^7.16.7", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.16.8", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", - "core-js-compat": "^3.20.2", - "semver": "^6.3.0" - } - }, - "@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/runtime": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz", - "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - } - } - }, - "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - }, - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "@gulp-sourcemaps/identity-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-2.0.1.tgz", - "integrity": "sha512-Tb+nSISZku+eQ4X1lAkevcQa+jknn/OVUgZ3XCxEKIsLsqYuPoJwJOPQeaOk75X3WPftb29GWY1eqE7GLsXb1Q==", - "dev": true, - "requires": { - "acorn": "^6.4.1", - "normalize-path": "^3.0.0", - "postcss": "^7.0.16", - "source-map": "^0.6.0", - "through2": "^3.0.1" - }, - "dependencies": { - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "requires": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - } - }, - "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 - }, - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - } - } - }, - "@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "dev": true, - "requires": { - "normalize-path": "^2.0.1", - "through2": "^2.0.3" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } - } - }, - "@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", - "dev": true - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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 - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jsdevtools/coverage-istanbul-loader": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz", - "integrity": "sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA==", - "dev": true, - "requires": { - "convert-source-map": "^1.7.0", - "istanbul-lib-instrument": "^4.0.3", - "loader-utils": "^2.0.0", - "merge-source-map": "^1.1.0", - "schema-utils": "^2.7.0" - } - }, - "@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true - }, - "@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true - }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/formatio": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", - "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", - "dev": true, - "requires": { - "samsam": "1.3.0" - } - }, - "@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@socket.io/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "requires": { - "defer-to-connect": "^2.0.0" - } - }, - "@types/aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-P+dkdFu0n08PDIvw+9nT9ByQnd+Udc8DaWPb9HKfaPwCvWvQpC5XaMRx2xLWECm9x1VKNps6vEAlirjA6+uNrQ==", - "dev": true - }, - "@types/cacheable-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", - "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", - "dev": true, - "requires": { - "@types/http-cache-semantics": "*", - "@types/keyv": "*", - "@types/node": "*", - "@types/responselike": "*" - } - }, - "@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", - "dev": true - }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "dev": true - }, - "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", - "dev": true - }, - "@types/diff": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.0.2.tgz", - "integrity": "sha512-uw8eYMIReOwstQ0QKF0sICefSy8cNO/v7gOTiIy9SbwuHyEecJUm7qlgueOO5S1udZ5I/irVydHVwMchgzbKTg==", - "dev": true - }, - "@types/easy-table": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/easy-table/-/easy-table-0.0.33.tgz", - "integrity": "sha512-/vvqcJPmZUfQwCgemL0/34G7bIQnCuvgls379ygRlcC1FqNqk3n+VZ15dAO51yl6JNDoWd8vsk+kT8zfZ1VZSw==", - "dev": true - }, - "@types/ejs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.0.tgz", - "integrity": "sha512-DCg+Ka+uDQ31lJ/UtEXVlaeV3d6t81gifaVWKJy4MYVVgvJttyX/viREy+If7fz+tK/gVxTGMtyrFPnm4gjrVA==", - "dev": true - }, - "@types/eslint": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", - "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "@types/fibers": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/fibers/-/fibers-3.1.1.tgz", - "integrity": "sha512-yHoUi46uika0snoTpNcVqUSvgbRndaIps4TUCotrXjtc0DHDoPQckmyXEZ2bX3e4mpJmyEW3hRhCwQa/ISCPaA==", - "dev": true - }, - "@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true - }, - "@types/inquirer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.0.tgz", - "integrity": "sha512-BNoMetRf3gmkpAlV5we+kxyZTle7YibdOntIZbU5pyIfMdcwy784KfeZDAcuyMznkh5OLa17RVXZOGA5LTlkgQ==", - "dev": true, - "requires": { - "@types/through": "*", - "rxjs": "^7.2.0" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/keyv": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", - "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/lodash": { - "version": "4.14.179", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.179.tgz", - "integrity": "sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w==", - "dev": true - }, - "@types/lodash.flattendeep": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/@types/lodash.flattendeep/-/lodash.flattendeep-4.4.6.tgz", - "integrity": "sha512-uLm2MaRVlqJSGsMK0RZpP5T3KqReq+9WbYDHCUhBhp98v56hMG/Yht52bsoTSui9xz2mUvQ9NfG3LrNGDL92Ng==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.pickby": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/@types/lodash.pickby/-/lodash.pickby-4.6.6.tgz", - "integrity": "sha512-NFa13XxlMd9eFi0UFZFWIztpMpXhozbijrx3Yb1viYZphT7jyopIFVoIRF4eYMjruWNEG1rnyrRmg/8ej9T8Iw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.union": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/@types/lodash.union/-/lodash.union-4.6.6.tgz", - "integrity": "sha512-Wu0ZEVNcyCz8eAn6TlUbYWZoGbH9E+iOHxAZbwUoCEXdUiy6qpcz5o44mMXViM4vlPLLCPlkAubEP1gokoSZaw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/mdast": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", - "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", - "dev": true, - "requires": { - "@types/unist": "*" - } - }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "@types/mocha": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", - "integrity": "sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg==", - "dev": true - }, - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "@types/object-inspect": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@types/object-inspect/-/object-inspect-1.8.1.tgz", - "integrity": "sha512-0JTdf3CGV0oWzE6Wa40Ayv2e2GhpP3pEJMcrlM74vBSJPuuNkVwfDnl0SZxyFCXETcB4oKA/MpTVfuYSMOelBg==", - "dev": true - }, - "@types/puppeteer": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-5.4.5.tgz", - "integrity": "sha512-lxCjpDEY+DZ66+W3x5Af4oHnEmUXt0HuaRzkBGE2UZiZEp/V1d3StpLPlmNVu/ea091bdNmVPl44lu8Wy/0ZCA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/recursive-readdir": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@types/recursive-readdir/-/recursive-readdir-2.2.0.tgz", - "integrity": "sha512-HGk753KRu2N4mWduovY4BLjYq4jTOL29gV2OfGdGxHcPSWGFkC5RRIdk+VTs5XmYd7MVAD+JwKrcb5+5Y7FOCg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/stream-buffers": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/stream-buffers/-/stream-buffers-3.0.4.tgz", - "integrity": "sha512-qU/K1tb2yUdhXkLIATzsIPwbtX6BpZk0l3dPW6xqWyhfzzM1ECaQ/8faEnu3CNraLiQ9LHyQQPBGp7N9Fbs25w==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==", - "dev": true - }, - "@types/through": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", - "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-dDZH/tXzwjutnuk4UacGgFRwV+JSLaXL1ikvidfJprkb7L9Nx1njcRHHmi3Dsvt7pgqqTEeucQuOrWHPFgzVHA==", - "dev": true - }, - "@types/ua-parser-js": { - "version": "0.7.36", - "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", - "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==", - "dev": true - }, - "@types/unist": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", - "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", - "dev": true - }, - "@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "requires": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "@types/which": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/which/-/which-1.3.2.tgz", - "integrity": "sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA==", - "dev": true - }, - "@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@types/yauzl": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", - "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", - "dev": true, - "optional": true, - "requires": { - "@types/node": "*" - } - }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "@vue/compiler-core": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.31.tgz", - "integrity": "sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==", - "dev": true, - "optional": true, - "requires": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.31", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - } - } - }, - "@vue/compiler-dom": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.31.tgz", - "integrity": "sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==", - "dev": true, - "optional": true, - "requires": { - "@vue/compiler-core": "3.2.31", - "@vue/shared": "3.2.31" - } - }, - "@vue/compiler-sfc": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.31.tgz", - "integrity": "sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==", - "dev": true, - "optional": true, - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.31", - "@vue/compiler-dom": "3.2.31", - "@vue/compiler-ssr": "3.2.31", - "@vue/reactivity-transform": "3.2.31", - "@vue/shared": "3.2.31", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - } - } - }, - "@vue/compiler-ssr": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.31.tgz", - "integrity": "sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==", - "dev": true, - "optional": true, - "requires": { - "@vue/compiler-dom": "3.2.31", - "@vue/shared": "3.2.31" - } - }, - "@vue/reactivity-transform": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.31.tgz", - "integrity": "sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==", - "dev": true, - "optional": true, - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.31", - "@vue/shared": "3.2.31", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" - } - }, - "@vue/shared": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.31.tgz", - "integrity": "sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==", - "dev": true, - "optional": true - }, - "@wdio/browserstack-service": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/browserstack-service/-/browserstack-service-7.16.16.tgz", - "integrity": "sha512-q4wUh/j0MR2SwhTkmIFif2DaXgH5yzdgOer6G/fac2n81zLCSpQHWO5aQ9T0An9CAd4L2A+t3dmChpBJPkHWSw==", - "dev": true, - "requires": { - "@types/node": "^17.0.4", - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "browserstack-local": "^1.4.5", - "got": "^11.0.2", - "webdriverio": "7.16.16" - } - }, - "@wdio/cli": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-7.16.16.tgz", - "integrity": "sha512-Wz/e5zm1UNHB9RAIsJIM7ioDzVllUwTvhVWOrI7HR/53GmO/cIvAVjpnlglizJNgK8WlbnM/cKNVIXxqxrnFmw==", - "dev": true, - "requires": { - "@types/ejs": "^3.0.5", - "@types/fs-extra": "^9.0.4", - "@types/inquirer": "^8.1.2", - "@types/lodash.flattendeep": "^4.4.6", - "@types/lodash.pickby": "^4.6.6", - "@types/lodash.union": "^4.6.6", - "@types/node": "^17.0.4", - "@types/recursive-readdir": "^2.2.0", - "@wdio/config": "7.16.16", - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "async-exit-hook": "^2.0.1", - "chalk": "^4.0.0", - "chokidar": "^3.0.0", - "cli-spinners": "^2.1.0", - "ejs": "^3.0.1", - "fs-extra": "^10.0.0", - "inquirer": "8.1.5", - "lodash.flattendeep": "^4.4.0", - "lodash.pickby": "^4.6.0", - "lodash.union": "^4.6.0", - "mkdirp": "^1.0.4", - "recursive-readdir": "^2.2.2", - "webdriverio": "7.16.16", - "yargs": "^17.0.0", - "yarn-install": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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 - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "@wdio/logger": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.7.0.tgz", + "integrity": "sha512-XX/OkC8NlvsBdhKsb9j7ZbuQtF/Vuo0xf38PXdqYtVezOrYbDuba0hPG++g/IGNuAF34ZbSi+49cvz4u5w92kQ==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" } }, - "yargs": { - "version": "17.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", - "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - } - } - }, - "@wdio/concise-reporter": { - "version": "7.16.14", - "resolved": "https://registry.npmjs.org/@wdio/concise-reporter/-/concise-reporter-7.16.14.tgz", - "integrity": "sha512-CR+9+skJ3mXPIdRo0AnIJTJHOArrWdKlXTnyZ/DD6M9VrNk5aiTWQyphT/IeHV5+fxjHlMNIf/KgIhj1ewschQ==", - "dev": true, - "requires": { - "@wdio/reporter": "7.16.14", - "@wdio/types": "7.16.14", - "chalk": "^4.0.0", - "pretty-ms": "^7.0.0" - }, - "dependencies": { "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" } }, "color-convert": { @@ -25690,7 +2190,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -25699,55 +2199,33 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } } } }, - "@wdio/config": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-7.16.16.tgz", - "integrity": "sha512-K/ObPuo6Da2liz++OKOIfbdpFwI7UWiFcBylfJkCYbweuXCoW1aUqlKI6rmKPwCH9Uqr/RHWu6p8eo0zWe6xVA==", - "dev": true, - "requires": { - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "deepmerge": "^4.0.0", - "glob": "^7.1.2" - } - }, - "@wdio/local-runner": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-7.16.16.tgz", - "integrity": "sha512-AJaOyM842PWgMffrrXyHJjouVseLHoiL5U1sw2VVproi3ORWHbltl1AMnreU/lrGu9L0CVKHYT1pxu5UbSOCxQ==", - "dev": true, - "requires": { - "@types/stream-buffers": "^3.0.3", - "@wdio/logger": "7.16.0", - "@wdio/repl": "7.16.14", - "@wdio/runner": "7.16.16", - "@wdio/types": "7.16.14", - "async-exit-hook": "^2.0.1", - "split2": "^4.0.0", - "stream-buffers": "^3.0.2" - } - }, "@wdio/logger": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.16.0.tgz", - "integrity": "sha512-/6lOGb2Iow5eSsy7RJOl1kCwsP4eMlG+/QKro5zUJsuyNJSQXf2ejhpkzyKWLgQbHu83WX6cM1014AZuLkzoQg==", + "version": "6.10.10", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-6.10.10.tgz", + "integrity": "sha512-2nh0hJz9HeZE0VIEMI+oPgjr/Q37ohrR9iqsl7f7GW5ik+PnKYCT9Eab5mR1GNMG60askwbskgGC1S9ygtvrSw==", "dev": true, "requires": { - "chalk": "^4.0.0", - "loglevel": "^1.6.0", - "loglevel-plugin-prefix": "^0.8.4", - "strip-ansi": "^6.0.0" + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" }, "dependencies": { "ansi-styles": { @@ -25756,17 +2234,17 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" } }, "color-convert": { @@ -25775,7 +2253,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -25784,65 +2262,82 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } } } }, "@wdio/mocha-framework": { - "version": "7.16.15", - "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-7.16.15.tgz", - "integrity": "sha512-XRya85/RYPZk4MZ7Cvl3oudTdrOo+RyO8b5Ff+dH8hD3GBCACaWgW9AjbsyhvbSTdUlF0gNLPdqOCsxV5XyM3w==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-7.7.4.tgz", + "integrity": "sha512-zLhMJBAp4HOP0qGffCNSA1UBdRystn9o5y7EEQXU6Gu+ktrSOV/RU+pvd+kqHo6RfOIcwShljZVStf3zh8cY6Q==", "dev": true, "requires": { - "@types/mocha": "^9.0.0", - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "expect-webdriverio": "^3.0.0", - "mocha": "^9.0.0" + "@types/mocha": "8.2.2", + "@wdio/logger": "7.7.0", + "@wdio/types": "7.7.3", + "@wdio/utils": "7.7.3", + "expect-webdriverio": "3.1.0", + "mocha": "9.0.1" }, "dependencies": { + "@wdio/logger": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.7.0.tgz", + "integrity": "sha512-XX/OkC8NlvsBdhKsb9j7ZbuQtF/Vuo0xf38PXdqYtVezOrYbDuba0hPG++g/IGNuAF34ZbSi+49cvz4u5w92kQ==", + "dev": true, + "requires": { + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" + } + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" + } + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "requires": { + "anymatch": "3.1.2", + "braces": "3.0.2", + "fsevents": "2.3.2", + "glob-parent": "5.1.2", + "is-binary-path": "2.1.0", + "is-glob": "4.0.1", + "normalize-path": "3.0.0", + "readdirp": "3.5.0" } }, "color-convert": { @@ -25851,7 +2346,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -25860,6 +2355,23 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "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 + } + } + }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -25872,83 +2384,67 @@ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "locate-path": "6.0.0", + "path-exists": "4.0.0" } }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "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 }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^5.0.0" - } - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "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.7" + "p-locate": "5.0.0" } }, "mocha": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.1.tgz", - "integrity": "sha512-T7uscqjJVS46Pq1XDXyo9Uvey9gd3huT/DD9cYBb4K2Xc/vbKRPUWK067bxDQRK0yIz6Jxk73IrnimvASzBNAQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.1.tgz", + "integrity": "sha512-9zwsavlRO+5csZu6iRtl3GHImAbhERoDsZwdRkdJ/bE+eVplmoxNKE901ZJ9LdSchYBjSCPbjKc5XvcAri2ylw==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", + "chokidar": "3.5.1", + "debug": "4.3.1", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.2.0", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.2.0", - "serialize-javascript": "6.0.0", + "nanoid": "3.1.23", + "serialize-javascript": "5.0.1", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", - "workerpool": "6.2.0", + "wide-align": "1.1.3", + "workerpool": "6.1.4", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } + } } }, "ms": { @@ -25957,19 +2453,13 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", - "dev": true - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "yocto-queue": "^0.1.0" + "yocto-queue": "0.1.0" } }, "p-locate": { @@ -25978,20 +2468,26 @@ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^3.0.2" + "p-limit": "3.1.0" } }, - "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 + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "2.3.0" + } }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } }, "yargs": { "version": "16.2.0", @@ -25999,13 +2495,13 @@ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "cliui": "7.0.4", + "escalade": "3.1.1", + "get-caller-file": "2.0.5", + "require-directory": "2.1.1", + "string-width": "4.2.2", + "y18n": "5.0.8", + "yargs-parser": "20.2.4" } }, "yargs-parser": { @@ -26017,105 +2513,298 @@ } }, "@wdio/protocols": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-7.16.7.tgz", - "integrity": "sha512-Wv40pNQcLiPzQ3o98Mv4A8T1EBQ6k4khglz/e2r16CTm+F3DDYh8eLMAsU5cgnmuwwDKX1EyOiFwieykBn5MCg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-7.7.4.tgz", + "integrity": "sha512-gfGPOjvqUws3/dTnrXbCYP2keYE6O5BK5qHWnOEu6c7ubE4hebxV8W5c822L7ntabc1e38+diEbM+qFuIT890Q==", "dev": true }, "@wdio/repl": { - "version": "7.16.14", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-7.16.14.tgz", - "integrity": "sha512-Ezih0Y+lsGkKv3H3U56hdWgZiQGA3VaAYguSLd9+g1xbQq+zMKqSmfqECD9bAy+OgCCiVTRstES6lHZxJVPhAg==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-7.7.3.tgz", + "integrity": "sha512-7nhvUa3Zd5Ny9topJGRZwkomlveuO3RIv+jBUHgQ2jiDIGvG9MroHxKEniIbscVSsD32XFOOZY59kSpX1b50VQ==", "dev": true, "requires": { - "@wdio/utils": "7.16.14" + "@wdio/utils": "7.7.3" } }, "@wdio/reporter": { - "version": "7.16.14", - "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-7.16.14.tgz", - "integrity": "sha512-e/I2oGfqjx9+zI4NT/garqxm7Afnos1EcrGSNu75WmP3PNJt4i+9DKkROu4PM6XWcpUB4v2UF7Mv/NrL3TU9aA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-7.7.3.tgz", + "integrity": "sha512-zAUGgP/FZ3XF5s4RUcDGIAeum3WzkA9ll5lymytxhh/9Jj9/5c77o498ic3RGQlB8FTz+5SVmw08r7g3uekI8g==", "dev": true, "requires": { - "@types/diff": "^5.0.0", - "@types/node": "^17.0.4", - "@types/object-inspect": "^1.8.0", - "@types/supports-color": "^8.1.0", - "@types/tmp": "^0.2.0", - "@wdio/types": "7.16.14", - "diff": "^5.0.0", - "fs-extra": "^10.0.0", - "object-inspect": "^1.10.3", - "supports-color": "8.1.1" + "@types/node": "14.17.4", + "@wdio/types": "7.7.3", + "fs-extra": "10.0.0" + }, + "dependencies": { + "@types/node": { + "version": "14.17.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz", + "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==", + "dev": true + } } }, "@wdio/runner": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-7.16.16.tgz", - "integrity": "sha512-Tt2ja6GukGPq1m98WP26yOWUGwzK1y7gPTLy6rKlamz3mOBC7koL0T9+iqcFREquUe4CMy2jWp1lqvPlwMbu7g==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-7.7.4.tgz", + "integrity": "sha512-Ahfrv3TM9y2KMjWI1xKc+tnLVO+X1/Gf5QPjprmLlRxf/rSQDfX+wMmQP/g0wsLtm4pXy0kR1K/76WWvZgzSkw==", "dev": true, "requires": { - "@wdio/config": "7.16.16", - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "deepmerge": "^4.0.0", - "gaze": "^1.1.2", - "webdriver": "7.16.16", - "webdriverio": "7.16.16" + "@wdio/config": "7.7.3", + "@wdio/logger": "7.7.0", + "@wdio/types": "7.7.3", + "@wdio/utils": "7.7.3", + "deepmerge": "4.2.2", + "gaze": "1.1.3", + "webdriver": "7.7.4", + "webdriverio": "7.7.4" + }, + "dependencies": { + "@wdio/logger": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.7.0.tgz", + "integrity": "sha512-XX/OkC8NlvsBdhKsb9j7ZbuQtF/Vuo0xf38PXdqYtVezOrYbDuba0hPG++g/IGNuAF34ZbSi+49cvz4u5w92kQ==", + "dev": true, + "requires": { + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } + } } }, "@wdio/spec-reporter": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-7.19.1.tgz", - "integrity": "sha512-qnZkn3VcyBPtcorUtpyCFE8v5ubyWmR7mFETXNzyriHyvjvk+NeFCWaFcIehpXYXiAmNpAwyfnZoIY6tkKQixQ==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-7.7.3.tgz", + "integrity": "sha512-5elsNfZd3kbBaKY5IK5ZmdZsWZNSOCqXnM2fYryAh2RBoXbcXkak4D5PbLehusZhp6CQ7UpXEKf4BDDYfd0ebw==", "dev": true, "requires": { - "@types/easy-table": "^0.0.33", - "@wdio/reporter": "7.19.1", - "@wdio/types": "7.19.1", - "chalk": "^4.0.0", - "easy-table": "^1.1.1", - "pretty-ms": "^7.0.0" + "@types/easy-table": "0.0.32", + "@wdio/reporter": "7.7.3", + "@wdio/types": "7.7.3", + "chalk": "4.1.1", + "easy-table": "1.1.1", + "pretty-ms": "7.0.1" }, "dependencies": { - "@wdio/reporter": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-7.19.1.tgz", - "integrity": "sha512-sWmBBV4dPCZkGk9Qq0m35T/vHGen0N10nH4osQcVP3IZJqpo2eLIH4w+X6EUbjZ2GdgOA2bLMMzb1bl9JqnGPg==", - "dev": true, - "requires": { - "@types/diff": "^5.0.0", - "@types/node": "^17.0.4", - "@types/object-inspect": "^1.8.0", - "@types/supports-color": "^8.1.0", - "@types/tmp": "^0.2.0", - "@wdio/types": "7.19.1", - "diff": "^5.0.0", - "fs-extra": "^10.0.0", - "object-inspect": "^1.10.3", - "supports-color": "8.1.1" - }, - "dependencies": { - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } + } + } + }, + "@wdio/sync": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@wdio/sync/-/sync-7.7.4.tgz", + "integrity": "sha512-x0ZU78Je0yl05TfwiNtkKkJZ+90y6MndR4z5n/m6ADRzSGdFOazGJSFO0h2bN8MkPRusfqYsJwB6MKftCP0URA==", + "dev": true, + "requires": { + "@types/fibers": "3.1.0", + "@types/puppeteer": "5.4.3", + "@wdio/logger": "7.7.0", + "@wdio/types": "7.7.3", + "fibers": "5.0.0", + "webdriverio": "7.7.4" + }, + "dependencies": { + "@wdio/logger": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.7.0.tgz", + "integrity": "sha512-XX/OkC8NlvsBdhKsb9j7ZbuQtF/Vuo0xf38PXdqYtVezOrYbDuba0hPG++g/IGNuAF34ZbSi+49cvz4u5w92kQ==", + "dev": true, + "requires": { + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.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" } }, - "@wdio/types": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.19.1.tgz", - "integrity": "sha512-mOodKlmvYxpj8P5BhjggEGpXuiRSlsyn2ClG8QqJ3lfXgOtOVEzFNfv/Ai7TkHr+lHDQNXLjllCjSqoCHhwlqg==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } + } + } + }, + "@wdio/types": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.7.3.tgz", + "integrity": "sha512-ZZBQHCXKjZSQj9pf4df/QhfgQQj0vzm9hkK7YyNM+S+qnW0LExL8qQKLxTlGHDaYxk/+Jrd9pcZrJXRCoSnUaA==", + "dev": true, + "requires": { + "@types/node": "14.17.4", + "got": "11.8.2" + }, + "dependencies": { + "@types/node": { + "version": "14.17.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz", + "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==", + "dev": true + } + } + }, + "@wdio/utils": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-7.7.3.tgz", + "integrity": "sha512-bvOoE2gve8Z8HFguVw0RMp5BbSmJR4zSr8DwbwnA8RSL3NshKlRk33HWYLmKsxjkH+ZWI2ihFbpvLD4W4imXag==", + "dev": true, + "requires": { + "@wdio/logger": "7.7.0", + "@wdio/types": "7.7.3" + }, + "dependencies": { + "@wdio/logger": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.7.0.tgz", + "integrity": "sha512-XX/OkC8NlvsBdhKsb9j7ZbuQtF/Vuo0xf38PXdqYtVezOrYbDuba0hPG++g/IGNuAF34ZbSi+49cvz4u5w92kQ==", "dev": true, "requires": { - "@types/node": "^17.0.4", - "got": "^11.8.1" + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" } }, "ansi-styles": { @@ -26124,17 +2813,17 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" } }, "color-convert": { @@ -26143,7 +2832,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -26152,210 +2841,33 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } } } }, - "@wdio/sync": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/@wdio/sync/-/sync-7.16.16.tgz", - "integrity": "sha512-MbVFAteaAOxHLKkMiMzOnh1hzINAK2U41GDIfy1yaPumcw1pNuJIhWrBYxprNMlqt8srk++wqQWgj5XpFjCL6g==", - "dev": true, - "requires": { - "@types/fibers": "^3.1.0", - "@types/puppeteer": "^5.4.0", - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "fibers": "^5.0.0", - "webdriverio": "7.16.16" - } - }, - "@wdio/types": { - "version": "7.16.14", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.16.14.tgz", - "integrity": "sha512-AyNI9iBSos9xWBmiFAF3sBs6AJXO/55VppU/eeF4HRdbZMtMarnvMuahM+jlUrA3vJSmDW+ufelG0MT//6vrnw==", - "dev": true, - "requires": { - "@types/node": "^17.0.4", - "got": "^11.8.1" - } - }, - "@wdio/utils": { - "version": "7.16.14", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-7.16.14.tgz", - "integrity": "sha512-wwin8nVpIlhmXJkq6GJw9aDDzgLOJKgXTcEua0T2sdXjoW78u5Ly/GZrFXTjMGhacFvoZfitTrjyfyy4CxMVvw==", - "dev": true, - "requires": { - "@wdio/logger": "7.16.0", - "@wdio/types": "7.16.14", - "p-iteration": "^1.1.8" - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" + "jsonparse": "1.3.1", + "through": "2.3.8" } }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -26363,12 +2875,12 @@ "dev": true }, "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "mime-types": "2.1.31", + "negotiator": "0.6.2" } }, "acorn": { @@ -26377,12 +2889,28 @@ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", "dev": true, - "requires": {} + "requires": { + "acorn": "4.0.13" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true }, "acorn-node": { "version": "1.8.2", @@ -26390,9 +2918,9 @@ "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", "dev": true, "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" + "acorn": "7.4.1", + "acorn-walk": "7.2.0", + "xtend": "4.0.2" } }, "acorn-walk": { @@ -26414,23 +2942,64 @@ "dev": true }, "ajv": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", - "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.1.0", + "json-schema-traverse": "0.3.1" + }, + "dependencies": { + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + } + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "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": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true + "dev": true }, "ansi-colors": { "version": "4.1.1", @@ -26444,7 +3013,7 @@ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "requires": { - "type-fest": "^0.21.3" + "type-fest": "0.21.3" } }, "ansi-gray": { @@ -26463,9 +3032,9 @@ "dev": true }, "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "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": { @@ -26474,7 +3043,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.3" } }, "ansi-wrap": { @@ -26489,8 +3058,8 @@ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "normalize-path": "3.0.0", + "picomatch": "2.3.0" } }, "append-buffer": { @@ -26499,7 +3068,7 @@ "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", "dev": true, "requires": { - "buffer-equal": "^1.0.0" + "buffer-equal": "1.0.0" } }, "archiver": { @@ -26508,31 +3077,20 @@ "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", "dev": true, "requires": { - "archiver-utils": "^2.1.0", - "async": "^3.2.0", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.0.0", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" + "archiver-utils": "2.1.0", + "async": "3.2.0", + "buffer-crc32": "0.2.13", + "readable-stream": "3.6.0", + "readdir-glob": "1.1.1", + "tar-stream": "2.2.0", + "zip-stream": "4.1.0" }, "dependencies": { "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } } } }, @@ -26542,16 +3100,42 @@ "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "dev": true, "requires": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" + "glob": "7.1.7", + "graceful-fs": "4.2.6", + "lazystream": "1.0.0", + "lodash.defaults": "4.2.0", + "lodash.difference": "4.5.0", + "lodash.flatten": "4.4.0", + "lodash.isplainobject": "4.0.6", + "lodash.union": "4.6.0", + "normalize-path": "3.0.0", + "readable-stream": "2.3.7" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } } }, "archy": { @@ -26561,20 +3145,21 @@ "dev": true }, "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "@babel/runtime": "7.14.6", + "@babel/runtime-corejs3": "7.14.7" } }, - "aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", - "dev": true - }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -26587,7 +3172,7 @@ "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", "dev": true, "requires": { - "make-iterator": "^1.0.0" + "make-iterator": "1.0.1" } }, "arr-flatten": { @@ -26602,7 +3187,7 @@ "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", "dev": true, "requires": { - "make-iterator": "^1.0.0" + "make-iterator": "1.0.1" } }, "arr-union": { @@ -26647,16 +3232,16 @@ "dev": true }, "array-includes": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", - "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" + "call-bind": "1.0.2", + "define-properties": "1.1.3", + "es-abstract": "1.18.3", + "get-intrinsic": "1.1.1", + "is-string": "1.0.6" } }, "array-initial": { @@ -26665,8 +3250,8 @@ "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", "dev": true, "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" + "array-slice": "1.1.0", + "is-number": "4.0.0" }, "dependencies": { "is-number": { @@ -26683,7 +3268,7 @@ "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", "dev": true, "requires": { - "is-number": "^4.0.0" + "is-number": "4.0.0" }, "dependencies": { "is-number": { @@ -26706,9 +3291,17 @@ "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", "dev": true, "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" + "default-compare": "1.0.0", + "get-value": "2.0.6", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } } }, "array-uniq": { @@ -26724,14 +3317,14 @@ "dev": true }, "array.prototype.flat": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", - "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0" + "call-bind": "1.0.2", + "define-properties": "1.1.3", + "es-abstract": "1.18.3" } }, "arrify": { @@ -26741,24 +3334,59 @@ "dev": true }, "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "dev": true, "requires": { - "safer-buffer": "~2.1.0" + "bn.js": "4.12.0", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1", + "safer-buffer": "2.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } } }, "assert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", - "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, "requires": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" + "object-assign": "4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } } }, "assert-plus": { @@ -26786,9 +3414,9 @@ "dev": true }, "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true }, "async-done": { @@ -26797,10 +3425,10 @@ "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" + "end-of-stream": "1.4.4", + "once": "1.4.0", + "process-nextick-args": "2.0.1", + "stream-exhaust": "1.0.2" } }, "async-each": { @@ -26815,13 +3443,19 @@ "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", "dev": true }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, "async-settle": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", "dev": true, "requires": { - "async-done": "^1.2.2" + "async-done": "1.3.2" } }, "asynckit": { @@ -26837,9 +3471,9 @@ "dev": true }, "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz", + "integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==", "dev": true }, "aws-sign2": { @@ -26860,9 +3494,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" + "chalk": "1.1.3", + "esutils": "2.0.3", + "js-tokens": "3.0.2" }, "dependencies": { "ansi-regex": { @@ -26883,11 +3517,11 @@ "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" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "js-tokens": { @@ -26902,7 +3536,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "supports-color": { @@ -26913,115 +3547,16 @@ } } }, - "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" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - } - } - }, - "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" - }, - "dependencies": { - "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" - } - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - } - } - }, - "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-loader": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz", - "integrity": "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", + "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", "dev": true, "requires": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^1.4.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" + "find-cache-dir": "3.3.1", + "loader-utils": "1.4.0", + "make-dir": "3.1.0", + "schema-utils": "2.7.1" }, "dependencies": { "json5": { @@ -27030,7 +3565,7 @@ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "minimist": "^1.2.0" + "minimist": "1.2.5" } }, "loader-utils": { @@ -27039,20 +3574,11 @@ "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", "dev": true, "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.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" + "big.js": "5.2.2", + "emojis-list": "3.0.0", + "json5": "1.0.1" + } + } } }, "babel-plugin-dynamic-import-node": { @@ -27061,37 +3587,37 @@ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", "dev": true, "requires": { - "object.assign": "^4.1.0" + "object.assign": "4.1.2" } }, "babel-plugin-polyfill-corejs2": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", - "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz", + "integrity": "sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ==", "dev": true, "requires": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.1", - "semver": "^6.1.1" + "@babel/compat-data": "7.14.7", + "@babel/helper-define-polyfill-provider": "0.2.3", + "semver": "6.3.0" } }, "babel-plugin-polyfill-corejs3": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", - "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.3.tgz", + "integrity": "sha512-rCOFzEIJpJEAU14XCcV/erIf/wZQMmMT5l5vXOpL5uoznyOGfDIjPj6FVytMvtzaKSTSVKouOCTPJ5OMUZH30g==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" + "@babel/helper-define-polyfill-provider": "0.2.3", + "core-js-compat": "3.15.1" } }, "babel-plugin-polyfill-regenerator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", - "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz", + "integrity": "sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.1" + "@babel/helper-define-polyfill-provider": "0.2.3" } }, "babel-plugin-transform-object-assign": { @@ -27099,48 +3625,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz", "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "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" - }, - "dependencies": { - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "dev": true - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "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==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - } + "babel-runtime": "6.26.0" } }, "babel-runtime": { @@ -27148,8 +3633,8 @@ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.6.12", + "regenerator-runtime": "0.11.1" }, "dependencies": { "core-js": { @@ -27159,90 +3644,10 @@ } } }, - "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": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "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" - }, - "dependencies": { - "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 - } - } - }, "babelify": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz", "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==", - "dev": true, - "requires": {} - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, "bach": { @@ -27251,15 +3656,15 @@ "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", "dev": true, "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" + "arr-filter": "1.1.2", + "arr-flatten": "1.1.0", + "arr-map": "2.0.2", + "array-each": "1.0.1", + "array-initial": "1.1.0", + "array-last": "1.3.0", + "async-done": "1.3.2", + "async-settle": "1.0.0", + "now-and-later": "2.0.1" } }, "bail": { @@ -27280,13 +3685,13 @@ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.3.0", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.2", + "pascalcase": "0.1.1" }, "dependencies": { "define-property": { @@ -27295,11 +3700,46 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.3" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.3" + } + }, + "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.3" } } } }, + "base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", + "dev": true + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -27333,7 +3773,7 @@ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "requires": { - "tweetnacl": "^0.14.3" + "tweetnacl": "0.14.5" } }, "beeper": { @@ -27342,10 +3782,22 @@ "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", "dev": true }, + "bfj": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", + "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", + "dev": true, + "requires": { + "bluebird": "3.7.2", + "check-types": "8.0.3", + "hoopy": "0.1.4", + "tryer": "1.0.1" + } + }, "big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", "dev": true }, "big.js": { @@ -27360,8 +3812,8 @@ "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", "dev": true, "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" + "buffers": "0.1.1", + "chainsaw": "0.1.0" } }, "binary-extensions": { @@ -27392,28 +3844,29 @@ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "buffer": "5.7.1", + "inherits": "2.0.4", + "readable-stream": "3.6.0" }, "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true } } }, "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", "dev": true }, "body": { @@ -27422,10 +3875,10 @@ "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", "dev": true, "requires": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" + "continuable-cache": "0.3.1", + "error": "7.2.1", + "raw-body": "1.1.7", + "safe-json-parse": "1.0.1" }, "dependencies": { "bytes": { @@ -27440,8 +3893,8 @@ "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, "requires": { - "bytes": "1", - "string_decoder": "0.10" + "bytes": "1.0.0", + "string_decoder": "0.10.31" } }, "string_decoder": { @@ -27453,35 +3906,20 @@ } }, "body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", + "bytes": "3.1.0", + "content-type": "1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "1.1.2", + "http-errors": "1.7.2", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "on-finished": "2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "1.6.18" } }, "brace-expansion": { @@ -27490,7 +3928,7 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.2", "concat-map": "0.0.1" } }, @@ -27500,9 +3938,15 @@ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "7.0.1" } }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, "browser-resolve": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", @@ -27526,17 +3970,104 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "1.2.0", + "browserify-des": "1.0.2", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.1", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "requires": { + "bn.js": "5.2.0", + "randombytes": "2.1.0" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "5.2.0", + "browserify-rsa": "4.1.0", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "elliptic": "6.5.4", + "inherits": "2.0.4", + "parse-asn1": "5.1.6", + "readable-stream": "3.6.0", + "safe-buffer": "5.2.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.11" + } + }, "browserslist": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.0.tgz", - "integrity": "sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ==", + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001313", - "electron-to-chromium": "^1.4.76", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" + "caniuse-lite": "1.0.30001239", + "colorette": "1.2.2", + "electron-to-chromium": "1.3.755", + "escalade": "3.1.1", + "node-releases": "1.1.73" } }, "browserstack": { @@ -27545,7 +4076,7 @@ "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==", "dev": true, "requires": { - "https-proxy-agent": "^2.2.1" + "https-proxy-agent": "2.2.4" }, "dependencies": { "agent-base": { @@ -27554,7 +4085,7 @@ "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "requires": { - "es6-promisify": "^5.0.0" + "es6-promisify": "5.0.0" } }, "debug": { @@ -27563,7 +4094,7 @@ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.3" } }, "https-proxy-agent": { @@ -27572,22 +4103,28 @@ "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" + "agent-base": "4.3.0", + "debug": "3.2.7" } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true } } }, "browserstack-local": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.9.tgz", - "integrity": "sha512-V+q8HQwRQFr9nd32xR66ZZ3VDWa3Kct4IMMudhKgcuD7cWrvvFARZOibx71II+Rf7P5nMQpWWxl9z/3p927nbg==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.8.tgz", + "integrity": "sha512-s+mc3gTOJwELdLWi4qFVKtGwMbb5JWsR+JxKlMaJkRJxoZ0gg3WREgPxAN0bm6iU5+S4Bi0sz0oxBRZT8BiNsQ==", "dev": true, "requires": { - "https-proxy-agent": "^4.0.0", - "is-running": "^2.1.0", - "ps-tree": "=1.2.0", - "temp-fs": "^0.9.9" + "https-proxy-agent": "4.0.0", + "is-running": "2.1.0", + "ps-tree": "1.2.0", + "temp-fs": "0.9.9" } }, "browserstacktunnel-wrapper": { @@ -27596,8 +4133,8 @@ "integrity": "sha512-GCV599FUUxNOCFl3WgPnfc5dcqq9XTmMXoxWpqkvmk0R9TOIoqmjENNU6LY6DtgIL6WfBVbg/jmWtnM5K6UYSg==", "dev": true, "requires": { - "https-proxy-agent": "^2.2.1", - "unzipper": "^0.9.3" + "https-proxy-agent": "2.2.4", + "unzipper": "0.9.15" }, "dependencies": { "agent-base": { @@ -27606,7 +4143,7 @@ "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "requires": { - "es6-promisify": "^5.0.0" + "es6-promisify": "5.0.0" } }, "debug": { @@ -27615,7 +4152,7 @@ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.3" } }, "https-proxy-agent": { @@ -27624,9 +4161,15 @@ "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" + "agent-base": "4.3.0", + "debug": "3.2.7" } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true } } }, @@ -27636,8 +4179,8 @@ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "base64-js": "1.5.1", + "ieee754": "1.2.1" } }, "buffer-crc32": { @@ -27653,9 +4196,9 @@ "dev": true }, "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "buffer-indexof-polyfill": { @@ -27670,16 +4213,28 @@ "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", "dev": true }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, "buffers": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", "dev": true }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, "cac": { "version": "3.0.4", @@ -27687,145 +4242,38 @@ "integrity": "sha1-bSTO7Dcu/lybeYgIvH9JtHJCpO8=", "dev": true, "requires": { - "camelcase-keys": "^3.0.0", - "chalk": "^1.1.3", - "indent-string": "^3.0.0", - "minimist": "^1.2.0", - "read-pkg-up": "^1.0.1", - "suffix": "^0.1.0", - "text-table": "^0.2.0" + "camelcase-keys": "3.0.0", + "chalk": "1.1.3", + "indent-string": "3.2.0", + "minimist": "1.2.5", + "read-pkg-up": "1.0.1", + "suffix": "0.1.1", + "text-table": "0.2.0" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "camelcase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-3.0.0.tgz", - "integrity": "sha1-/AxsNgNj9zd+N5O5oWvM8QcMHKQ=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "map-obj": "^1.0.0" - } - }, - "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" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "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 - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "strip-ansi": { @@ -27834,16 +4282,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" + "ansi-regex": "2.1.1" } }, "supports-color": { @@ -27860,15 +4299,15 @@ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "collection-visit": "1.0.0", + "component-emitter": "1.3.0", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.1", + "to-object-path": "0.3.0", + "union-value": "1.0.1", + "unset-value": "1.0.0" } }, "cacheable-lookup": { @@ -27883,30 +4322,19 @@ "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", "dev": true, "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - } + "clone-response": "1.0.2", + "get-stream": "5.2.0", + "http-cache-semantics": "4.1.0", + "keyv": "4.0.3", + "lowercase-keys": "2.0.0", + "normalize-url": "6.1.0", + "responselike": "2.0.0" } }, "cached-path-relative": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz", - "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", + "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", "dev": true }, "call-bind": { @@ -27915,8 +4343,8 @@ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "1.1.1", + "get-intrinsic": "1.1.1" } }, "caller-path": { @@ -27925,7 +4353,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "^0.2.0" + "callsites": "0.2.0" }, "dependencies": { "callsites": { @@ -27943,34 +4371,25 @@ "dev": true }, "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-3.0.0.tgz", + "integrity": "sha1-/AxsNgNj9zd+N5O5oWvM8QcMHKQ=", "dev": true, "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "dependencies": { - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true - } + "camelcase": "3.0.0", + "map-obj": "1.0.1" } }, "caniuse-lite": { - "version": "1.0.30001320", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", - "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", + "version": "1.0.30001239", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001239.tgz", + "integrity": "sha512-cyBkXJDMeI4wthy8xJ2FvDU6+0dtcZSJW3voUF8+e9f1bBeuvyZfc3PNbkOETyhbR+dGCPzn9E7MA3iwzusOhQ==", "dev": true }, "caseless": { @@ -27985,19 +4404,28 @@ "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==", "dev": true }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", "dev": true, "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.1", + "type-detect": "4.0.8" } }, "chainsaw": { @@ -28006,7 +4434,7 @@ "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", "dev": true, "requires": { - "traverse": ">=0.3.0 <0.4" + "traverse": "0.3.9" } }, "chalk": { @@ -28015,26 +4443,9 @@ "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": { - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "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" - } - } + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" } }, "character-entities": { @@ -28073,20 +4484,26 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "check-types": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz", + "integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==", + "dev": true + }, "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "anymatch": "3.1.2", + "braces": "3.0.2", + "fsevents": "2.3.2", + "glob-parent": "5.1.2", + "is-binary-path": "2.1.0", + "is-glob": "4.0.1", + "normalize-path": "3.0.0", + "readdirp": "3.6.0" } }, "chownr": { @@ -28096,15 +4513,15 @@ "dev": true }, "chrome-launcher": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.0.tgz", - "integrity": "sha512-ZQqX5kb9H0+jy1OqLnWampfocrtSZaGl7Ny3F9GRha85o4odbL8x55paUzh51UC7cEmZ5obp3H2Mm70uC2PpRA==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.14.0.tgz", + "integrity": "sha512-W//HpflaW6qBGrmuskup7g+XJZN6w03ko9QSIe5CtcTal2u0up5SeReK3Ll1Why4Ey8dPkv8XSodZyHPnGbVHQ==", "dev": true, "requires": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0" + "@types/node": "15.12.4", + "escape-string-regexp": "4.0.0", + "is-wsl": "2.2.0", + "lighthouse-logger": "1.2.0" }, "dependencies": { "escape-string-regexp": { @@ -28115,11 +4532,15 @@ } } }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } }, "circular-json": { "version": "0.3.3", @@ -28133,10 +4554,10 @@ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" }, "dependencies": { "define-property": { @@ -28145,64 +4566,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-descriptor": "0.1.6" } } } @@ -28213,13 +4577,13 @@ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "requires": { - "restore-cursor": "^3.1.0" + "restore-cursor": "3.1.0" } }, "cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz", + "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==", "dev": true }, "cli-width": { @@ -28234,15 +4598,15 @@ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "string-width": "4.2.2", + "strip-ansi": "6.0.0", + "wrap-ansi": "7.0.0" } }, "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "clone-buffer": { @@ -28257,7 +4621,7 @@ "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "1.0.1" } }, "clone-stats": { @@ -28272,9 +4636,35 @@ "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", "dev": true, "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" + "inherits": "2.0.3", + "process-nextick-args": "2.0.1", + "readable-stream": "2.3.7" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } } }, "co": { @@ -28295,9 +4685,9 @@ "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", "dev": true, "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "arr-map": "2.0.2", + "for-own": "1.0.0", + "make-iterator": "1.0.1" } }, "collection-visit": { @@ -28306,8 +4696,8 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, "color-convert": { @@ -28331,6 +4721,12 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -28343,7 +4739,7 @@ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "comma-separated-tokens": { @@ -28353,9 +4749,9 @@ "dev": true }, "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, "commondir": { @@ -28370,8 +4766,8 @@ "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, "requires": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" + "array-ify": "1.0.0", + "dot-prop": "5.3.0" } }, "component-emitter": { @@ -28386,23 +4782,10 @@ "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", "dev": true, "requires": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "buffer-crc32": "0.2.13", + "crc32-stream": "4.0.2", + "normalize-path": "3.0.0", + "readable-stream": "3.6.0" } }, "concat-map": { @@ -28417,10 +4800,36 @@ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "buffer-from": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.7", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } } }, "concat-with-sourcemaps": { @@ -28429,7 +4838,7 @@ "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", "dev": true, "requires": { - "source-map": "^0.6.1" + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -28448,25 +4857,8 @@ "requires": { "debug": "2.6.9", "finalhandler": "1.1.2", - "parseurl": "~1.3.3", + "parseurl": "1.3.3", "utils-merge": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } } }, "connect-livereload": { @@ -28475,19 +4867,34 @@ "integrity": "sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==", "dev": true }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "consolidate": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.16.0.tgz", + "integrity": "sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==", + "dev": true, + "optional": true, + "requires": { + "bluebird": "3.7.2" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", "requires": { - "safe-buffer": "5.2.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - } + "safe-buffer": "5.1.2" } }, "content-type": { @@ -28507,27 +4914,27 @@ "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", "dev": true, "requires": { - "conventional-changelog-angular": "^5.0.12", - "conventional-changelog-atom": "^2.0.8", - "conventional-changelog-codemirror": "^2.0.8", - "conventional-changelog-conventionalcommits": "^4.5.0", - "conventional-changelog-core": "^4.2.1", - "conventional-changelog-ember": "^2.0.9", - "conventional-changelog-eslint": "^3.0.9", - "conventional-changelog-express": "^2.0.6", - "conventional-changelog-jquery": "^3.0.11", - "conventional-changelog-jshint": "^2.0.9", - "conventional-changelog-preset-loader": "^2.3.4" + "conventional-changelog-angular": "5.0.12", + "conventional-changelog-atom": "2.0.8", + "conventional-changelog-codemirror": "2.0.8", + "conventional-changelog-conventionalcommits": "4.5.0", + "conventional-changelog-core": "4.2.2", + "conventional-changelog-ember": "2.0.9", + "conventional-changelog-eslint": "3.0.9", + "conventional-changelog-express": "2.0.6", + "conventional-changelog-jquery": "3.0.11", + "conventional-changelog-jshint": "2.0.9", + "conventional-changelog-preset-loader": "2.3.4" } }, "conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.12.tgz", + "integrity": "sha512-5GLsbnkR/7A89RyHLvvoExbiGbd9xKdKqDTrArnPbOqBqG/2wIosu0fHwpeIRI8Tl94MhVNBXcLJZl92ZQ5USw==", "dev": true, "requires": { - "compare-func": "^2.0.0", - "q": "^1.5.1" + "compare-func": "2.0.0", + "q": "1.5.1" } }, "conventional-changelog-atom": { @@ -28536,7 +4943,7 @@ "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", "dev": true, "requires": { - "q": "^1.5.1" + "q": "1.5.1" } }, "conventional-changelog-codemirror": { @@ -28545,7 +4952,7 @@ "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", "dev": true, "requires": { - "q": "^1.5.1" + "q": "1.5.1" } }, "conventional-changelog-config-spec": { @@ -28555,63 +4962,190 @@ "dev": true }, "conventional-changelog-conventionalcommits": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz", - "integrity": "sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.5.0.tgz", + "integrity": "sha512-buge9xDvjjOxJlyxUnar/+6i/aVEVGA7EEh4OafBCXPlLUQPGbRUBhBUveWRxzvR8TEjhKEP4BdepnpG2FSZXw==", "dev": true, "requires": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" + "compare-func": "2.0.0", + "lodash": "4.17.21", + "q": "1.5.1" } }, "conventional-changelog-core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", - "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", - "dev": true, - "requires": { - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-parser": "^3.2.0", - "dateformat": "^3.0.0", - "get-pkg-repo": "^4.0.0", - "git-raw-commits": "^2.0.8", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^4.1.1", - "lodash": "^4.17.15", - "normalize-package-data": "^3.0.0", - "q": "^1.5.1", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0", - "through2": "^4.0.0" + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.2.tgz", + "integrity": "sha512-7pDpRUiobQDNkwHyJG7k9f6maPo9tfPzkSWbRq97GGiZqisElhnvUZSvyQH20ogfOjntB5aadvv6NNcKL1sReg==", + "dev": true, + "requires": { + "add-stream": "1.0.0", + "conventional-changelog-writer": "4.1.0", + "conventional-commits-parser": "3.2.1", + "dateformat": "3.0.3", + "get-pkg-repo": "1.4.0", + "git-raw-commits": "2.0.10", + "git-remote-origin-url": "2.0.0", + "git-semver-tags": "4.1.1", + "lodash": "4.17.21", + "normalize-package-data": "3.0.2", + "q": "1.5.1", + "read-pkg": "3.0.0", + "read-pkg-up": "3.0.0", + "shelljs": "0.8.4", + "through2": "4.0.2" }, "dependencies": { - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dev": true, + "requires": { + "lru-cache": "6.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "4.2.6", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "4.0.0" + } + }, + "normalize-package-data": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz", + "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==", + "dev": true, + "requires": { + "hosted-git-info": "4.0.2", + "resolve": "1.20.0", + "semver": "7.3.5", + "validate-npm-package-license": "3.0.4" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.3.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "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=", + "dev": true, + "requires": { + "error-ex": "1.3.2", + "json-parse-better-errors": "1.0.2" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "pify": "3.0.0" } }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "load-json-file": "4.0.0", + "normalize-package-data": "2.5.0", + "path-type": "3.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "2.8.9", + "resolve": "1.20.0", + "semver": "5.7.1", + "validate-npm-package-license": "3.0.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "read-pkg-up": { @@ -28620,8 +5154,8 @@ "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" + "find-up": "2.1.0", + "read-pkg": "3.0.0" } }, "semver": { @@ -28630,8 +5164,20 @@ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "6.0.0" } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -28641,7 +5187,7 @@ "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", "dev": true, "requires": { - "q": "^1.5.1" + "q": "1.5.1" } }, "conventional-changelog-eslint": { @@ -28650,7 +5196,7 @@ "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", "dev": true, "requires": { - "q": "^1.5.1" + "q": "1.5.1" } }, "conventional-changelog-express": { @@ -28659,7 +5205,7 @@ "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", "dev": true, "requires": { - "q": "^1.5.1" + "q": "1.5.1" } }, "conventional-changelog-jquery": { @@ -28668,7 +5214,7 @@ "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", "dev": true, "requires": { - "q": "^1.5.1" + "q": "1.5.1" } }, "conventional-changelog-jshint": { @@ -28677,8 +5223,8 @@ "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", "dev": true, "requires": { - "compare-func": "^2.0.0", - "q": "^1.5.1" + "compare-func": "2.0.0", + "q": "1.5.1" } }, "conventional-changelog-preset-loader": { @@ -28688,35 +5234,30 @@ "dev": true }, "conventional-changelog-writer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", - "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", - "dev": true, - "requires": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.1.0.tgz", + "integrity": "sha512-WwKcUp7WyXYGQmkLsX4QmU42AZ1lqlvRW9mqoyiQzdD+rJWbTepdWoKJuwXTS+yq79XKnQNa93/roViPQrAQgw==", + "dev": true, + "requires": { + "compare-func": "2.0.0", + "conventional-commits-filter": "2.0.7", + "dateformat": "3.0.3", + "handlebars": "4.7.7", + "json-stringify-safe": "5.0.1", + "lodash": "4.17.21", + "meow": "8.1.2", + "semver": "6.3.0", + "split": "1.0.1", + "through2": "4.0.2" }, "dependencies": { - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true - }, "split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "requires": { - "through": "2" + "through": "2.3.8" } } } @@ -28727,44 +5268,23 @@ "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", "dev": true, "requires": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" + "lodash.ismatch": "4.4.0", + "modify-values": "1.0.1" } }, "conventional-commits-parser": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.1.tgz", + "integrity": "sha512-OG9kQtmMZBJD/32NEw5IhN5+HnBqVjy03eC+I71I0oQRFA5rOgA4OtPOYG7mz1GkCfCNxn3gKIX8EiHJYuf1cA==", "dev": true, "requires": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "requires": { - "readable-stream": "^3.0.0" - } - } + "JSONStream": "1.3.5", + "is-text-path": "1.0.1", + "lodash": "4.17.21", + "meow": "8.1.2", + "split2": "3.2.2", + "through2": "4.0.2", + "trim-off-newlines": "1.0.1" } }, "conventional-recommended-bump": { @@ -28773,14 +5293,14 @@ "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", "dev": true, "requires": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^2.3.4", - "conventional-commits-filter": "^2.0.7", - "conventional-commits-parser": "^3.2.0", - "git-raw-commits": "^2.0.8", - "git-semver-tags": "^4.1.1", - "meow": "^8.0.0", - "q": "^1.5.1" + "concat-stream": "2.0.0", + "conventional-changelog-preset-loader": "2.3.4", + "conventional-commits-filter": "2.0.7", + "conventional-commits-parser": "3.2.1", + "git-raw-commits": "2.0.10", + "git-semver-tags": "4.1.1", + "meow": "8.1.2", + "q": "1.5.1" }, "dependencies": { "concat-stream": { @@ -28789,21 +5309,10 @@ "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "buffer-from": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "3.6.0", + "typedarray": "0.0.6" } } } @@ -28814,13 +5323,13 @@ "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, "requires": { - "safe-buffer": "~5.1.1" + "safe-buffer": "5.1.2" } }, "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" }, "cookie-signature": { "version": "1.0.6", @@ -28839,22 +5348,30 @@ "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", "dev": true, "requires": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" + "each-props": "1.3.2", + "is-plain-object": "5.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + } } }, "core-js": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", - "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==" + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.1.tgz", + "integrity": "sha512-h8VbZYnc9pDzueiS2610IULDkpFFPunHwIpl8yRwFahAEEdSpHlTy3h3z3rKq5h11CaUdBEeRViu9AYvbxiMeg==" }, "core-js-compat": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz", - "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==", + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.1.tgz", + "integrity": "sha512-xGhzYMX6y7oEGQGAJmP2TmtBLvR4nZmRGEcFa3ubHOq5YEp51gGN9AovVa0AoujGZIq+Wm6dISiYyGNfdflYww==", "dev": true, "requires": { - "browserslist": "^4.19.1", + "browserslist": "4.16.6", "semver": "7.0.0" }, "dependencies": { @@ -28867,14 +5384,14 @@ } }, "core-js-pure": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz", - "integrity": "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==" + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.1.tgz", + "integrity": "sha512-OZuWHDlYcIda8sJLY4Ec6nWq2hRjlyCqCZ+jCflyleMkVt3tPedDVErvHslyS2nbO+SlBFMSBJYvtLMwxnrzjA==" }, "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, "cors": { @@ -28883,31 +5400,52 @@ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "dev": true, "requires": { - "object-assign": "^4", - "vary": "^1" + "object-assign": "4.1.1", + "vary": "1.1.2" } }, "coveralls": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", - "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz", + "integrity": "sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==", "dev": true, "requires": { - "js-yaml": "^3.13.1", - "lcov-parse": "^1.0.0", - "log-driver": "^1.2.7", - "minimist": "^1.2.5", - "request": "^2.88.2" + "js-yaml": "3.14.1", + "lcov-parse": "1.0.0", + "log-driver": "1.2.7", + "minimist": "1.2.5", + "request": "2.88.2" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.1" + } + } } }, "crc-32": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", - "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", "dev": true, "requires": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.3.1" + "exit-on-epipe": "1.0.1", + "printj": "1.1.2" } }, "crc32-stream": { @@ -28916,46 +5454,98 @@ "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", "dev": true, "requires": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" + "crc-32": "1.2.0", + "readable-stream": "3.6.0" + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "4.12.0", + "elliptic": "6.5.4" }, "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true } } }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "md5.js": "1.3.5", + "ripemd160": "2.0.2", + "sha.js": "2.4.11" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "inherits": "2.0.3", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" + } + }, "criteo-direct-rsa-validate": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/criteo-direct-rsa-validate/-/criteo-direct-rsa-validate-1.1.0.tgz", "integrity": "sha512-7gQ3zX+d+hS/vOxzLrZ4aRAceB7qNJ0VzaGNpcWjDCmtOpASB50USJDupTik/H2nHgiSAA3VNZ3SFuONs8LR9Q==" }, - "cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", "dev": true, "requires": { - "node-fetch": "2.6.7" + "lru-cache": "4.1.5", + "which": "1.3.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + } } }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "browserify-cipher": "1.0.1", + "browserify-sign": "4.2.1", + "create-ecdh": "4.0.4", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "diffie-hellman": "5.0.3", + "inherits": "2.0.3", + "pbkdf2": "3.1.2", + "public-encrypt": "4.0.3", + "randombytes": "2.1.0", + "randomfill": "1.0.4" } }, "crypto-js": { @@ -28969,16 +5559,32 @@ "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", "dev": true, "requires": { - "inherits": "^2.0.4", - "source-map": "^0.6.1", - "source-map-resolve": "^0.6.0" + "inherits": "2.0.4", + "source-map": "0.6.1", + "source-map-resolve": "0.6.0" }, "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "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 + }, + "source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "dev": true, + "requires": { + "atob": "2.1.2", + "decode-uri-component": "0.2.0" + } } } }, @@ -28994,13 +5600,19 @@ "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", "dev": true }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "array-find-index": "^1.0.1" + "array-find-index": "1.0.2" } }, "custom-event": { @@ -29015,8 +5627,8 @@ "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dev": true, "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" + "es5-ext": "0.10.53", + "type": "1.2.0" } }, "dargs": { @@ -29031,19 +5643,19 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "date-format": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.4.tgz", - "integrity": "sha512-/jyf4rhB17ge328HJuJjAcmRtCsGd+NDeAtahRBTaK6vSPR6MO5HlrAit3Nn7dVjaa6sowW0WXt8yQtLyZQFRg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", + "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", "dev": true }, "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true }, "de-indent": { @@ -29054,12 +5666,11 @@ "optional": true }, "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "ms": "2.1.2" + "ms": "2.0.0" } }, "debug-fabulous": { @@ -29068,9 +5679,9 @@ "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", "dev": true, "requires": { - "debug": "3.X", - "memoizee": "0.4.X", - "object-assign": "4.X" + "debug": "3.2.7", + "memoizee": "0.4.15", + "object-assign": "4.1.1" }, "dependencies": { "debug": { @@ -29079,15 +5690,21 @@ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.3" } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true } } }, "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, "decamelize-keys": { @@ -29096,14 +5713,14 @@ "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", "dev": true, "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" + "decamelize": "1.2.0", + "map-obj": "1.0.1" }, "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true } } @@ -29120,7 +5737,7 @@ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, "requires": { - "mimic-response": "^3.1.0" + "mimic-response": "3.1.0" }, "dependencies": { "mimic-response": { @@ -29137,7 +5754,7 @@ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { - "type-detect": "^4.0.0" + "type-detect": "4.0.8" } }, "deep-equal": { @@ -29146,27 +5763,35 @@ "integrity": "sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "es-get-iterator": "^1.1.1", - "get-intrinsic": "^1.0.1", - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.2", - "is-regex": "^1.1.1", - "isarray": "^2.0.5", - "object-is": "^1.1.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.3", - "which-boxed-primitive": "^1.0.1", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.2" + "call-bind": "1.0.2", + "es-get-iterator": "1.1.2", + "get-intrinsic": "1.1.1", + "is-arguments": "1.1.0", + "is-date-object": "1.0.4", + "is-regex": "1.1.3", + "isarray": "2.0.5", + "object-is": "1.1.5", + "object-keys": "1.1.1", + "object.assign": "4.1.2", + "regexp.prototype.flags": "1.3.1", + "side-channel": "1.0.4", + "which-boxed-primitive": "1.0.2", + "which-collection": "1.0.1", + "which-typed-array": "1.1.4" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } } }, "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, "deepmerge": { @@ -29181,7 +5806,15 @@ "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, "requires": { - "kind-of": "^5.0.2" + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } } }, "default-resolution": { @@ -29196,15 +5829,7 @@ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "^1.0.2" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - } + "clone": "1.0.4" } }, "defer-to-connect": { @@ -29219,7 +5844,7 @@ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { - "object-keys": "^1.0.12" + "object-keys": "1.1.1" } }, "define-property": { @@ -29228,8 +5853,39 @@ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.3" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.3" + } + }, + "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.3" + } + } } }, "defined": { @@ -29249,6 +5905,16 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", @@ -29273,9 +5939,9 @@ "dev": true }, "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, "detective": { @@ -29284,50 +5950,104 @@ "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", "dev": true, "requires": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" + "acorn-node": "1.8.2", + "defined": "1.0.0", + "minimist": "1.2.5" } }, "devtools": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/devtools/-/devtools-7.16.16.tgz", - "integrity": "sha512-M0kzkuSgfEhpqIis3gdtWsNjn/HQ+vRAmEzDnbYx/7FfjFxhSv1d+rOOT20pvd60soItMYpsOova1igACEGkGQ==", - "dev": true, - "requires": { - "@types/node": "^17.0.4", - "@types/ua-parser-js": "^0.7.33", - "@wdio/config": "7.16.16", - "@wdio/logger": "7.16.0", - "@wdio/protocols": "7.16.7", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "chrome-launcher": "^0.15.0", - "edge-paths": "^2.1.0", - "puppeteer-core": "^13.1.3", - "query-selector-shadow-dom": "^1.0.0", - "ua-parser-js": "^1.0.1", - "uuid": "^8.0.0" + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/devtools/-/devtools-7.7.4.tgz", + "integrity": "sha512-rkO9k6yOA2XzFTph9y+gO/387653jou0La7QSLd57XTQiM3D/UODqLBt+fMVu8w3fdQzZHVAlIIvP4B8rkXY1Q==", + "dev": true, + "requires": { + "@types/node": "14.17.4", + "@wdio/config": "7.7.3", + "@wdio/logger": "7.7.0", + "@wdio/protocols": "7.7.4", + "@wdio/types": "7.7.3", + "@wdio/utils": "7.7.3", + "chrome-launcher": "0.14.0", + "edge-paths": "2.2.1", + "puppeteer-core": "9.1.1", + "query-selector-shadow-dom": "1.0.0", + "ua-parser-js": "0.7.28", + "uuid": "8.3.2" }, "dependencies": { - "ua-parser-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.2.tgz", - "integrity": "sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==", + "@types/node": { + "version": "14.17.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz", + "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==", + "dev": true + }, + "@wdio/logger": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.7.0.tgz", + "integrity": "sha512-XX/OkC8NlvsBdhKsb9j7ZbuQtF/Vuo0xf38PXdqYtVezOrYbDuba0hPG++g/IGNuAF34ZbSi+49cvz4u5w92kQ==", + "dev": true, + "requires": { + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.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 }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } } } }, "devtools-protocol": { - "version": "0.0.973690", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.973690.tgz", - "integrity": "sha512-myh3hSFp0YWa2GED11PmbLhV4dv9RdO7YUz27XJrbQLnP5bMbZL6dfOOILTHO57yH0kX5GfuOZBsg/4NamfPvQ==", + "version": "0.0.892017", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.892017.tgz", + "integrity": "sha512-23yn1+zeMBlWiZTtrCViNQt+W+FRDw5rEetI19bMuyKIYeK11xo/dS+Hmuu8ifGJnJvXUU3Y79IoxSPWZWcVOA==", "dev": true }, "di": { @@ -29343,11 +6063,30 @@ "dev": true }, "diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "version": "27.0.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.1.tgz", + "integrity": "sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==", "dev": true }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "4.12.0", + "miller-rabin": "4.0.1", + "randombytes": "2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, "dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -29359,7 +6098,7 @@ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { - "esutils": "^2.0.2" + "esutils": "2.0.3" } }, "doctrine-temporary-fork": { @@ -29368,7 +6107,7 @@ "integrity": "sha512-nliqOv5NkE4zMON4UA6AMJE6As35afs8aYXATpU4pTUdIKiARZwrJVEP1boA3Rx1ZXHVkwxkhcq4VkqvsuRLsA==", "dev": true, "requires": { - "esutils": "^2.0.2" + "esutils": "2.0.3" } }, "documentation": { @@ -29380,51 +6119,51 @@ "@babel/core": "7.12.3", "@babel/generator": "7.12.1", "@babel/parser": "7.12.3", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "@vue/compiler-sfc": "^3.0.11", - "ansi-html": "^0.0.7", - "babelify": "^10.0.0", - "chalk": "^2.3.0", - "chokidar": "^3.4.0", - "concat-stream": "^1.6.0", - "diff": "^4.0.1", + "@babel/traverse": "7.14.7", + "@babel/types": "7.14.5", + "@vue/compiler-sfc": "3.1.2", + "ansi-html": "0.0.7", + "babelify": "10.0.0", + "chalk": "2.4.2", + "chokidar": "3.5.2", + "concat-stream": "1.6.2", + "diff": "4.0.2", "doctrine-temporary-fork": "2.1.0", - "get-port": "^5.0.0", - "git-url-parse": "^11.1.2", + "get-port": "5.1.1", + "git-url-parse": "11.4.4", "github-slugger": "1.2.0", - "glob": "^7.1.2", - "globals-docs": "^2.4.0", - "highlight.js": "^10.7.2", - "ini": "^1.3.5", - "js-yaml": "^3.10.0", - "lodash": "^4.17.10", - "mdast-util-find-and-replace": "^1.1.1", - "mdast-util-inject": "^1.1.0", - "micromatch": "^3.1.5", - "mime": "^2.2.0", - "module-deps-sortable": "^5.0.3", - "parse-filepath": "^1.0.2", - "pify": "^5.0.0", - "read-pkg-up": "^4.0.0", - "remark": "^13.0.0", - "remark-gfm": "^1.0.0", - "remark-html": "^13.0.1", - "remark-reference-links": "^5.0.0", - "remark-toc": "^7.2.0", - "resolve": "^1.8.1", - "stream-array": "^1.1.2", - "strip-json-comments": "^2.0.1", - "tiny-lr": "^1.1.0", - "unist-builder": "^2.0.3", - "unist-util-visit": "^2.0.3", - "vfile": "^4.0.0", - "vfile-reporter": "^6.0.0", - "vfile-sort": "^2.1.0", - "vinyl": "^2.1.0", - "vinyl-fs": "^3.0.2", - "vue-template-compiler": "^2.6.12", - "yargs": "^15.3.1" + "glob": "7.1.7", + "globals-docs": "2.4.1", + "highlight.js": "10.7.3", + "ini": "1.3.8", + "js-yaml": "3.14.1", + "lodash": "4.17.21", + "mdast-util-find-and-replace": "1.1.1", + "mdast-util-inject": "1.1.0", + "micromatch": "3.1.10", + "mime": "2.5.2", + "module-deps-sortable": "5.0.3", + "parse-filepath": "1.0.2", + "pify": "5.0.0", + "read-pkg-up": "4.0.0", + "remark": "13.0.0", + "remark-gfm": "1.0.0", + "remark-html": "13.0.1", + "remark-reference-links": "5.0.0", + "remark-toc": "7.2.0", + "resolve": "1.20.0", + "stream-array": "1.1.2", + "strip-json-comments": "2.0.1", + "tiny-lr": "1.1.1", + "unist-builder": "2.0.3", + "unist-util-visit": "2.0.3", + "vfile": "4.2.1", + "vfile-reporter": "6.0.2", + "vfile-sort": "2.2.2", + "vinyl": "2.2.1", + "vinyl-fs": "3.0.3", + "vue-template-compiler": "2.6.14", + "yargs": "15.4.1" }, "dependencies": { "@babel/core": { @@ -29433,22 +6172,22 @@ "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.1", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.1", - "@babel/parser": "^7.12.3", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" + "@babel/code-frame": "7.14.5", + "@babel/generator": "7.12.1", + "@babel/helper-module-transforms": "7.14.5", + "@babel/helpers": "7.14.6", + "@babel/parser": "7.12.3", + "@babel/template": "7.14.5", + "@babel/traverse": "7.14.7", + "@babel/types": "7.14.5", + "convert-source-map": "1.8.0", + "debug": "4.3.1", + "gensync": "1.0.0-beta.2", + "json5": "2.2.0", + "lodash": "4.17.21", + "resolve": "1.20.0", + "semver": "5.7.1", + "source-map": "0.5.7" } }, "@babel/generator": { @@ -29457,9 +6196,9 @@ "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", "dev": true, "requires": { - "@babel/types": "^7.12.1", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "@babel/types": "7.14.5", + "jsesc": "2.5.2", + "source-map": "0.5.7" } }, "@babel/parser": { @@ -29474,18 +6213,62 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.4", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "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.1" + } + } } }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "string-width": "4.2.2", + "strip-ansi": "6.0.0", + "wrap-ansi": "6.2.0" } }, "color-convert": { @@ -29494,7 +6277,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -29503,76 +6286,258 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "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.1" + } + } + } + }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "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": "^5.0.0", - "path-exists": "^4.0.0" + "locate-path": "3.0.0" } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "argparse": "1.0.10", + "esprima": "4.0.1" } }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { - "p-try": "^2.0.0" + "graceful-fs": "4.2.6", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, - "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==", + "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-limit": "^2.2.0" + "p-locate": "3.0.0", + "path-exists": "3.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==", + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.3", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", "dev": true }, - "path-exists": { + "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-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.3.0" + } + }, + "parse-json": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "1.3.2", + "json-parse-better-errors": "1.0.2" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", "dev": true }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "4.0.0", + "normalize-package-data": "2.5.0", + "path-type": "3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "3.0.0", + "read-pkg": "3.0.0" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + }, "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" + "ansi-styles": "4.3.0", + "string-width": "4.2.2", + "strip-ansi": "6.0.0" } }, "y18n": { @@ -29587,17 +6552,53 @@ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "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": "^18.1.2" + "cliui": "6.0.0", + "decamelize": "1.2.0", + "find-up": "4.1.0", + "get-caller-file": "2.0.5", + "require-directory": "2.1.1", + "require-main-filename": "2.0.0", + "set-blocking": "2.0.0", + "string-width": "4.2.2", + "which-module": "2.0.0", + "y18n": "4.0.3", + "yargs-parser": "18.1.3" + }, + "dependencies": { + "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" + } + }, + "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-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.3.0" + } + }, + "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 + } } }, "yargs-parser": { @@ -29606,8 +6607,8 @@ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "camelcase": "5.3.1", + "decamelize": "1.2.0" } } } @@ -29618,19 +6619,25 @@ "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", "dev": true, "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" + "custom-event": "1.0.1", + "ent": "2.2.0", + "extend": "3.0.2", + "void-elements": "2.0.1" } }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "requires": { - "is-obj": "^2.0.0" + "is-obj": "2.0.0" } }, "dotgitignore": { @@ -29639,8 +6646,8 @@ "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", "dev": true, "requires": { - "find-up": "^3.0.0", - "minimatch": "^3.0.4" + "find-up": "3.0.0", + "minimatch": "3.0.4" }, "dependencies": { "find-up": { @@ -29649,7 +6656,7 @@ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "3.0.0" } }, "locate-path": { @@ -29658,17 +6665,8 @@ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" + "p-locate": "3.0.0", + "path-exists": "3.0.0" } }, "p-locate": { @@ -29677,13 +6675,13 @@ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "p-limit": "2.3.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==", + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true } } @@ -29705,30 +6703,69 @@ "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "requires": { - "readable-stream": "^2.0.2" + "readable-stream": "2.3.7" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } } }, "duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, "requires": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" + "end-of-stream": "1.4.4", + "inherits": "2.0.3", + "readable-stream": "2.3.7", + "stream-shift": "1.0.1" }, "dependencies": { "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "safe-buffer": "5.1.2" } } } @@ -29739,29 +6776,26 @@ "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", "dev": true, "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0" } }, "easy-table": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", - "integrity": "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.1.1.tgz", + "integrity": "sha512-C9Lvm0WFcn2RgxbMnTbXZenMIWcBtkzMr+dWqq/JsVoGFSVUVlPqeOa5LP5kM0I3zoOazFpckOEb2/0LDFfToQ==", "dev": true, "requires": { - "ansi-regex": "^5.0.1", - "wcwidth": "^1.0.1" + "ansi-regex": "3.0.0", + "wcwidth": "1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } } }, "ecc-jsbn": { @@ -29770,8 +6804,8 @@ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" } }, "edge-paths": { @@ -29780,8 +6814,8 @@ "integrity": "sha512-AI5fC7dfDmCdKo3m5y7PkYE8m6bMqR6pvVpgtrZkkhcJXFLelUgkjrhk3kXXx8Kbw2cRaTT4LkOR7hqf39KJdw==", "dev": true, "requires": { - "@types/which": "^1.3.2", - "which": "^2.0.2" + "@types/which": "1.3.2", + "which": "2.0.2" } }, "ee-first": { @@ -29795,19 +6829,48 @@ "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", "dev": true, "requires": { - "jake": "^10.6.1" + "jake": "10.8.2" } }, "electron-to-chromium": { - "version": "1.4.78", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.78.tgz", - "integrity": "sha512-o61+D/Lx7j/E0LIin/efOqeHpXhwi1TaQco9vUcRmr91m25SfZY6L5hWJDv/r+6kNjboFKgBw1LbfM0lbhuK6Q==", + "version": "1.3.755", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.755.tgz", + "integrity": "sha512-BJ1s/kuUuOeo1bF/EM2E4yqW9te0Hpof3wgwBx40AWJE18zsD1Tqo0kr7ijnOc+lRsrlrqKPauJAHqaxOItoUA==", "dev": true }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "requires": { + "bn.js": "4.12.0", + "brorand": "1.1.0", + "hash.js": "1.1.7", + "hmac-drbg": "1.0.1", + "inherits": "2.0.4", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + } + } + }, "emoji-regex": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", - "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", + "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 }, "emojis-list": { @@ -29827,44 +6890,72 @@ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "requires": { - "once": "^1.4.0" + "once": "1.4.0" } }, "engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-4.1.1.tgz", + "integrity": "sha512-t2E9wLlssQjGw0nluF6aYyfX8LwYU8Jj0xct+pAhfWfv/YrBn6TSNtEYsgxHIfaMqfrLx07czcMg9bMN6di+3w==", "dev": true, "requires": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", + "accepts": "1.3.7", "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" + "cookie": "0.4.1", + "cors": "2.8.5", + "debug": "4.3.1", + "engine.io-parser": "4.0.2", + "ws": "7.4.6" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "dev": true + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + }, + "ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "dev": true + } } }, "engine.io-parser": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", - "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz", + "integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==", "dev": true, "requires": { - "@socket.io/base64-arraybuffer": "~1.0.2" + "base64-arraybuffer": "0.1.4" } }, "enhanced-resolve": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", - "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", "dev": true, "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "graceful-fs": "4.2.6", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.9" } }, "enquirer": { @@ -29873,7 +6964,7 @@ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "dev": true, "requires": { - "ansi-colors": "^4.1.1" + "ansi-colors": "4.1.1" } }, "ent": { @@ -29888,7 +6979,7 @@ "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", "dev": true, "requires": { - "prr": "~1.0.1" + "prr": "1.0.1" } }, "error": { @@ -29897,7 +6988,7 @@ "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", "dev": true, "requires": { - "string-template": "~0.2.1" + "string-template": "0.2.1" } }, "error-ex": { @@ -29906,35 +6997,31 @@ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "is-arrayish": "0.2.1" } }, "es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dev": true, + "requires": { + "call-bind": "1.0.2", + "es-to-primitive": "1.2.1", + "function-bind": "1.1.1", + "get-intrinsic": "1.1.1", + "has": "1.0.3", + "has-symbols": "1.0.2", + "is-callable": "1.2.3", + "is-negative-zero": "2.0.1", + "is-regex": "1.1.3", + "is-string": "1.0.6", + "object-inspect": "1.10.3", + "object-keys": "1.1.1", + "object.assign": "4.1.2", + "string.prototype.trimend": "1.0.4", + "string.prototype.trimstart": "1.0.4", + "unbox-primitive": "1.0.1" } }, "es-get-iterator": { @@ -29943,48 +7030,50 @@ "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.0", - "has-symbols": "^1.0.1", - "is-arguments": "^1.1.0", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.5", - "isarray": "^2.0.5" + "call-bind": "1.0.2", + "get-intrinsic": "1.1.1", + "has-symbols": "1.0.2", + "is-arguments": "1.1.0", + "is-map": "2.0.2", + "is-set": "2.0.2", + "is-string": "1.0.6", + "isarray": "2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } } }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, "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" + "is-callable": "1.2.3", + "is-date-object": "1.0.4", + "is-symbol": "1.0.4" } }, "es5-ext": { - "version": "0.10.57", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.57.tgz", - "integrity": "sha512-L7cCNoPwTkAp7IBHxrKLsh7NKiVFkcdxlP9vbVw9QUvb7gF0Mz9bEBN0WY9xqdTjGF907EMT/iG013vnbqwu1Q==", + "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.3", - "next-tick": "^1.1.0" + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.3", + "next-tick": "1.0.0" } }, "es5-shim": { - "version": "4.6.5", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.6.5.tgz", - "integrity": "sha512-vfQ4UAai8szn0sAubCy97xnZ4sJVDD1gt/Grn736hg8D7540wemIb1YPrYZSTqlM2H69EQX1or4HU/tSwRTI3w==", + "version": "4.5.15", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.15.tgz", + "integrity": "sha512-FYpuxEjMeDvU4rulKqFdukQyZSTpzhg4ScQHrAosrlVpR6GFyaw14f74yn2+4BugniIS0Frpg7TvwZocU4ZMTw==", "dev": true }, "es6-iterator": { @@ -29993,16 +7082,24 @@ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" + "d": "1.0.1", + "es5-ext": "0.10.53", + "es6-symbol": "3.1.3" } }, - "es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=", - "dev": true + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.1", + "es5-ext": "0.10.53", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.3", + "event-emitter": "0.3.5" + } }, "es6-promise": { "version": "4.2.8", @@ -30016,7 +7113,32 @@ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { - "es6-promise": "^4.0.3" + "es6-promise": "4.2.8" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.1", + "es5-ext": "0.10.53", + "es6-iterator": "2.0.3", + "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.0.1", + "es5-ext": "0.10.53" + } + } } }, "es6-symbol": { @@ -30025,8 +7147,8 @@ "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "dev": true, "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" + "d": "1.0.1", + "ext": "1.4.0" } }, "es6-weak-map": { @@ -30035,10 +7157,10 @@ "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "dev": true, "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" + "d": "1.0.1", + "es5-ext": "0.10.53", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.3" } }, "escalade": { @@ -30064,13 +7186,19 @@ "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.3", + "optionator": "0.8.3", + "source-map": "0.2.0" }, "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, "estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", @@ -30083,8 +7211,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "1.1.2", + "type-check": "0.3.2" } }, "optionator": { @@ -30093,12 +7221,12 @@ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "word-wrap": "1.2.3" } }, "prelude-ls": { @@ -30114,7 +7242,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": ">=0.0.4" + "amdefine": "1.0.1" } }, "type-check": { @@ -30123,57 +7251,68 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "1.1.2" } } } }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.3", + "esrecurse": "4.3.0", + "estraverse": "4.3.0" + } + }, "eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.29.0.tgz", + "integrity": "sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA==", "dev": true, "requires": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "@eslint/eslintrc": "0.4.2", + "ajv": "6.12.6", + "chalk": "4.1.1", + "cross-spawn": "7.0.3", + "debug": "4.3.1", + "doctrine": "3.0.0", + "enquirer": "2.3.6", + "escape-string-regexp": "4.0.0", + "eslint-scope": "5.1.1", + "eslint-utils": "2.1.0", + "eslint-visitor-keys": "2.1.0", + "espree": "7.3.1", + "esquery": "1.4.0", + "esutils": "2.0.3", + "fast-deep-equal": "3.1.3", + "file-entry-cache": "6.0.1", + "functional-red-black-tree": "1.0.1", + "glob-parent": "5.1.2", + "globals": "13.9.0", + "ignore": "4.0.6", + "import-fresh": "3.3.0", + "imurmurhash": "0.1.4", + "is-glob": "4.0.1", + "js-yaml": "3.14.1", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.4.1", + "lodash.merge": "4.6.2", + "minimatch": "3.0.4", + "natural-compare": "1.4.0", + "optionator": "0.9.1", + "progress": "2.0.3", + "regexpp": "3.2.0", + "semver": "7.3.5", + "strip-ansi": "6.0.0", + "strip-json-comments": "3.1.1", + "table": "6.7.1", + "text-table": "0.2.0", + "v8-compile-cache": "2.3.0" }, "dependencies": { "@babel/code-frame": { @@ -30182,7 +7321,7 @@ "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "dev": true, "requires": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "7.14.5" } }, "ajv": { @@ -30191,10 +7330,10 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "3.1.3", + "fast-json-stable-stringify": "2.1.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.4.1" } }, "ansi-styles": { @@ -30203,17 +7342,26 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" } }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" } }, "color-convert": { @@ -30222,7 +7370,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -30231,6 +7379,26 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "3.1.1", + "shebang-command": "2.0.0", + "which": "2.0.2" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -30238,36 +7406,61 @@ "dev": true }, "globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", + "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", + "dev": true, + "requires": { + "type-fest": "0.20.2" + } + }, + "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 + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "type-fest": "^0.20.2" + "yallist": "4.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 + }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "6.0.0" } }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } }, "type-fest": { @@ -30275,6 +7468,12 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -30282,38 +7481,26 @@ "version": "10.2.1", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", - "dev": true, - "requires": {} + "dev": true }, "eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", "dev": true, "requires": { - "debug": "^3.2.7", - "resolve": "^1.20.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } + "debug": "2.6.9", + "resolve": "1.20.0" } }, "eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", + "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", "dev": true, "requires": { - "debug": "^3.2.7", - "find-up": "^2.1.0" + "debug": "3.2.7", + "pkg-dir": "2.0.0" }, "dependencies": { "debug": { @@ -30322,7 +7509,71 @@ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.3" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.3.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "2.1.0" } } } @@ -30333,53 +7584,153 @@ "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", "dev": true, "requires": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" + "eslint-utils": "2.1.0", + "regexpp": "3.2.0" } }, "eslint-plugin-import": { - "version": "2.25.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", - "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", - "dev": true, - "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.2", - "has": "^1.0.3", - "is-core-module": "^2.8.0", - "is-glob": "^4.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.5", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.12.0" + "version": "2.23.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", + "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", + "dev": true, + "requires": { + "array-includes": "3.1.3", + "array.prototype.flat": "1.2.4", + "debug": "2.6.9", + "doctrine": "2.1.0", + "eslint-import-resolver-node": "0.3.4", + "eslint-module-utils": "2.6.1", + "find-up": "2.1.0", + "has": "1.0.3", + "is-core-module": "2.4.0", + "minimatch": "3.0.4", + "object.values": "1.1.4", + "pkg-up": "2.0.0", + "read-pkg-up": "3.0.0", + "resolve": "1.20.0", + "tsconfig-paths": "3.9.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "ms": "2.0.0" + "esutils": "2.0.3" } }, - "doctrine": { + "find-up": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "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", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "4.2.6", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.3.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "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=", + "dev": true, + "requires": { + "error-ex": "1.3.2", + "json-parse-better-errors": "1.0.2" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "4.0.0", + "normalize-package-data": "2.5.0", + "path-type": "3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { - "esutils": "^2.0.2" + "find-up": "2.1.0", + "read-pkg": "3.0.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true } } @@ -30390,38 +7741,37 @@ "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", "dev": true, "requires": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" + "eslint-plugin-es": "3.0.1", + "eslint-utils": "2.1.0", + "ignore": "5.1.8", + "minimatch": "3.0.4", + "resolve": "1.20.0", + "semver": "6.3.0" }, "dependencies": { "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true } } }, "eslint-plugin-prebid": { - "version": "file:plugins/eslint" + "version": "file:plugins/eslint", + "dev": true }, "eslint-plugin-promise": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz", - "integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==", - "dev": true, - "requires": {} + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz", + "integrity": "sha512-NGmI6BH5L12pl7ScQHbg7tvtk4wPxxj8yPHH47NvSmMtFneC077PSeY3huFj06ZWZvtbfxSPt3RuOQD5XcR4ng==", + "dev": true }, "eslint-plugin-standard": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", - "dev": true, - "requires": {} + "dev": true }, "eslint-scope": { "version": "5.1.1", @@ -30429,8 +7779,8 @@ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "esrecurse": "4.3.0", + "estraverse": "4.3.0" } }, "eslint-utils": { @@ -30439,7 +7789,7 @@ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.1.0" + "eslint-visitor-keys": "1.3.0" }, "dependencies": { "eslint-visitor-keys": { @@ -30462,9 +7812,9 @@ "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", "dev": true, "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" + "acorn": "7.4.1", + "acorn-jsx": "5.3.1", + "eslint-visitor-keys": "1.3.0" }, "dependencies": { "eslint-visitor-keys": { @@ -30476,9 +7826,9 @@ } }, "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "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": { @@ -30487,13 +7837,13 @@ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { - "estraverse": "^5.1.0" + "estraverse": "5.2.0" }, "dependencies": { "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true } } @@ -30504,13 +7854,13 @@ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { - "estraverse": "^5.2.0" + "estraverse": "5.2.0" }, "dependencies": { "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true } } @@ -30525,8 +7875,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "optional": true + "dev": true }, "esutils": { "version": "2.0.3", @@ -30545,8 +7894,8 @@ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14" + "d": "1.0.1", + "es5-ext": "0.10.53" } }, "event-stream": { @@ -30555,21 +7904,13 @@ "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", + "duplexer": "0.1.2", + "from": "0.1.7", + "map-stream": "0.1.0", "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - }, - "dependencies": { - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - } + "split": "0.3.3", + "stream-combiner": "0.0.4", + "through": "2.3.8" } }, "eventemitter3": { @@ -30584,19 +7925,29 @@ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.5", + "safe-buffer": "5.1.2" + } + }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "cross-spawn": "6.0.5", + "get-stream": "4.1.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.3", + "strip-eof": "1.0.0" }, "dependencies": { "cross-spawn": { @@ -30605,11 +7956,20 @@ "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" + "nice-try": "1.0.5", + "path-key": "2.0.1", + "semver": "5.7.1", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "3.0.0" } }, "path-key": { @@ -30630,7 +7990,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "1.0.0" } }, "shebang-regex": { @@ -30645,7 +8005,7 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } } } @@ -30662,31 +8022,22 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -30695,77 +8046,59 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + } + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.4" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.1.1", + "repeat-element": "1.1.4", + "repeat-string": "1.6.1" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "kind-of": "3.2.2" } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "isarray": "1.0.0" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } } } }, @@ -30775,101 +8108,91 @@ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "^1.0.1" + "homedir-polyfill": "1.0.3" } }, "expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.2.tgz", + "integrity": "sha512-YJFNJe2+P2DqH+ZrXy+ydRQYO87oxRUonZImpDodR1G7qo3NYd3pL+NQ9Keqpez3cehczYwZDBC3A7xk3n7M/w==", "dev": true, "requires": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" + "@jest/types": "27.0.2", + "ansi-styles": "5.2.0", + "jest-get-type": "27.0.1", + "jest-matcher-utils": "27.0.2", + "jest-message-util": "27.0.2", + "jest-regex-util": "27.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } } }, "expect-webdriverio": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/expect-webdriverio/-/expect-webdriverio-3.1.4.tgz", - "integrity": "sha512-65FTS3bmxcIp0cq6fLb/72TrCQXBCpwPLC7SwMWdpPlLq461mXcK1BPKJJjnIC587aXSKD+3E4hvnlCtwDmXfg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/expect-webdriverio/-/expect-webdriverio-3.1.0.tgz", + "integrity": "sha512-Kn4Rtu5vKbDo95WNcjZ9XVz/qTPGZzumP9w7VSV4OxY5z6BAqSI2jb85EsqPxpavs33P+9Qse4Z+d5ilDD/dQw==", "dev": true, "requires": { - "expect": "^27.0.2", - "jest-matcher-utils": "^27.0.2" + "expect": "27.0.2", + "jest-matcher-utils": "27.0.2" } }, "express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "requires": { - "accepts": "~1.3.8", + "accepts": "1.3.7", "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "1.0.4", + "cookie": "0.4.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.2", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", + "proxy-addr": "2.0.7", + "qs": "6.7.0", + "range-parser": "1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "1.5.0", + "type-is": "1.6.18", "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - } + "vary": "1.1.2" } }, "ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", "dev": true, "requires": { - "type": "^2.5.0" + "type": "2.5.0" }, "dependencies": { "type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", + "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", "dev": true } } @@ -30886,8 +8209,19 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } } }, "external-editor": { @@ -30896,9 +8230,9 @@ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "chardet": "0.7.0", + "iconv-lite": "0.4.24", + "tmp": "0.0.33" } }, "extglob": { @@ -30907,14 +8241,14 @@ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -30923,7 +8257,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "extend-shallow": { @@ -30932,14 +8266,37 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.3" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.3" + } + }, + "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.3" + } } } }, @@ -30949,20 +8306,26 @@ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" + "@types/yauzl": "2.9.1", + "debug": "4.3.1", + "get-stream": "5.2.0", + "yauzl": "2.10.0" }, "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "pump": "^3.0.0" + "ms": "2.1.2" } + }, + "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 } } }, @@ -30984,10 +8347,10 @@ "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", "dev": true, "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "parse-node-version": "1.0.1", + "time-stamp": "1.1.0" } }, "fast-deep-equal": { @@ -31014,7 +8377,7 @@ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "websocket-driver": ">=0.5.1" + "websocket-driver": "0.7.4" } }, "fd-slicer": { @@ -31023,16 +8386,16 @@ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "dev": true, "requires": { - "pend": "~1.2.0" + "pend": "1.2.0" } }, "fibers": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/fibers/-/fibers-5.0.1.tgz", - "integrity": "sha512-VMC7Frt87Oo0AOJ6EcPFbi+tZmkQ4tD85aatwyWL6I9cYMJmm2e+pXUJsfGZ36U7MffXtjou2XIiWJMtHriErw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fibers/-/fibers-5.0.0.tgz", + "integrity": "sha512-UpGv/YAZp7mhKHxDvC1tColrroGRX90sSvh8RMZV9leo+e5+EkRVgCEZPlmXeo3BUNQTZxUaVdLskq1Q2FyCPg==", "dev": true, "requires": { - "detect-libc": "^1.0.3" + "detect-libc": "1.0.3" } }, "figures": { @@ -31041,7 +8404,7 @@ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5" + "escape-string-regexp": "1.0.5" } }, "file-entry-cache": { @@ -31050,7 +8413,7 @@ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { - "flat-cache": "^3.0.4" + "flat-cache": "3.0.4" } }, "file-uri-to-path": { @@ -31066,16 +8429,28 @@ "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", "dev": true, "requires": { - "minimatch": "^3.0.4" + "minimatch": "3.0.4" } }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", + "dev": true + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "to-regex-range": "^5.0.1" + "to-regex-range": "5.0.1" } }, "filter-obj": { @@ -31090,83 +8465,163 @@ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.3", + "statuses": "1.5.0", + "unpipe": "1.0.0" + } + }, + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "requires": { + "commondir": "1.0.1", + "make-dir": "3.1.0", + "pkg-dir": "4.2.0" + } + }, + "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" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "1.0.0", + "is-glob": "4.0.1", + "micromatch": "3.1.10", + "resolve-dir": "1.0.1" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, "requires": { - "ms": "2.0.0" + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.4", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "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.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "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.1" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.3", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, "fined": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.2" } }, "flagged-respawn": { @@ -31187,14 +8642,25 @@ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "flatted": "3.1.1", + "rimraf": "3.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "7.1.7" + } + } } }, "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", "dev": true }, "flush-write-stream": { @@ -31203,14 +8669,40 @@ "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", "dev": true, "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" + "inherits": "2.0.3", + "readable-stream": "2.3.7" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } } }, "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", "dev": true }, "for-in": { @@ -31225,7 +8717,7 @@ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { - "for-in": "^1.0.1" + "for-in": "1.0.2" } }, "foreach": { @@ -31258,9 +8750,9 @@ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "asynckit": "0.4.0", + "combined-stream": "1.0.8", + "mime-types": "2.1.31" } }, "forwarded": { @@ -31274,7 +8766,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "^0.2.2" + "map-cache": "0.2.2" } }, "fresh": { @@ -31294,7 +8786,7 @@ "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", "dev": true, "requires": { - "null-check": "^1.0.0" + "null-check": "1.0.0" } }, "fs-constants": { @@ -31304,14 +8796,14 @@ "dev": true }, "fs-extra": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", - "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "dev": true, "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "graceful-fs": "4.2.6", + "jsonfile": "6.1.0", + "universalify": "2.0.0" } }, "fs-mkdirp-stream": { @@ -31320,18 +8812,42 @@ "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" + "graceful-fs": "4.2.6", + "through2": "2.0.5" }, "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "readable-stream": "2.3.7", + "xtend": "4.0.2" } } } @@ -31342,9 +8858,9 @@ "integrity": "sha1-3QI/kwE77iRTHxszUUw3sg/ZM0k=", "dev": true, "requires": { - "fs-extra": "~0.6.1", - "mkdirp": "~0.3.5", - "walk": "^2.3.9" + "fs-extra": "0.6.4", + "mkdirp": "0.3.5", + "walk": "2.3.14" }, "dependencies": { "fs-extra": { @@ -31353,10 +8869,10 @@ "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", "dev": true, "requires": { - "jsonfile": "~1.0.1", - "mkdirp": "0.3.x", - "ncp": "~0.4.2", - "rimraf": "~2.2.0" + "jsonfile": "1.0.1", + "mkdirp": "0.3.5", + "ncp": "0.4.2", + "rimraf": "2.2.8" } }, "jsonfile": { @@ -31389,6 +8905,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "optional": true }, "fstream": { @@ -31397,10 +8914,10 @@ "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" + "graceful-fs": "4.2.6", + "inherits": "2.0.3", + "mkdirp": "0.5.5", + "rimraf": "2.5.4" }, "dependencies": { "mkdirp": { @@ -31409,16 +8926,7 @@ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "^1.2.5" - } - }, - "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" + "minimist": "1.2.5" } } } @@ -31428,7 +8936,7 @@ "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.10.tgz", "integrity": "sha512-7xBjdT+oMYOPWgwFxNiNzF4ubeUvim4zs1DnQqSSGyxu8UD7AW/6Z0iFsVRwuVSIZKUks2en2VHHotmNfj3ipw==", "requires": { - "typescript-tuple": "^2.2.1" + "typescript-tuple": "2.2.1" } }, "function-bind": { @@ -31449,7 +8957,41 @@ "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", "dev": true, "requires": { - "globule": "^1.0.0" + "globule": "1.3.2" + } + }, + "generic-names": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-2.0.1.tgz", + "integrity": "sha512-kPCHWa1m9wGG/OwQpeweTwM/PYiQLrUIxXbt/P4Nic3LbGjCP0YwrALHW1uNLKZ0LIMg+RF+XRlj2ekT9ZlZAQ==", + "dev": true, + "optional": true, + "requires": { + "loader-utils": "1.4.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "optional": true, + "requires": { + "minimist": "1.2.5" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "optional": true, + "requires": { + "big.js": "5.2.2", + "emojis-list": "3.0.0", + "json5": "1.0.1" + } + } } }, "gensync": { @@ -31476,61 +9018,130 @@ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "function-bind": "1.1.1", + "has": "1.0.3", + "has-symbols": "1.0.2" } }, "get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz", + "integrity": "sha1-xztInAbYDMVTbCyFP54FIyBWly0=", "dev": true, "requires": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" + "hosted-git-info": "2.8.9", + "meow": "3.7.0", + "normalize-package-data": "2.5.0", + "parse-github-repo-url": "1.4.1", + "through2": "2.0.5" }, "dependencies": { - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "camelcase": "2.1.1", + "map-obj": "1.0.1" } }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "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": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "repeating": "2.0.1" } }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.5", + "normalize-package-data": "2.5.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" } }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "2.3.7", + "xtend": "4.0.2" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true } } @@ -31548,22 +9159,12 @@ "dev": true }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "pump": "3.0.0" } }, "get-value": { @@ -31578,42 +9179,20 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", + "integrity": "sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==", "dev": true, "requires": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "requires": { - "readable-stream": "^3.0.0" - } - } + "dargs": "7.0.0", + "lodash": "4.17.21", + "meow": "8.1.2", + "split2": "3.2.2", + "through2": "4.0.2" } }, "git-remote-origin-url": { @@ -31622,16 +9201,8 @@ "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", "dev": true, "requires": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } + "gitconfiglocal": "1.0.0", + "pify": "2.3.0" } }, "git-semver-tags": { @@ -31640,27 +9211,27 @@ "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", "dev": true, "requires": { - "meow": "^8.0.0", - "semver": "^6.0.0" + "meow": "8.1.2", + "semver": "6.3.0" } }, "git-up": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.5.tgz", - "integrity": "sha512-YUvVDg/vX3d0syBsk/CKUTib0srcQME0JyHkL5BaYdwLsiCslPWmDSi8PUMo9pXYjrryMcmsCoCgsTpSCJEQaA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.2.tgz", + "integrity": "sha512-kbuvus1dWQB2sSW4cbfTeGpCMd8ge9jx9RKnhXhuJ7tnvT+NIrTVfYZxjtflZddQYcmdOTlkAcjmx7bor+15AQ==", "dev": true, "requires": { - "is-ssh": "^1.3.0", - "parse-url": "^6.0.0" + "is-ssh": "1.3.3", + "parse-url": "5.0.5" } }, "git-url-parse": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.6.0.tgz", - "integrity": "sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g==", + "version": "11.4.4", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.4.4.tgz", + "integrity": "sha512-Y4o9o7vQngQDIU9IjyCmRJBin5iYjI5u9ZITnddRZpD7dcCFQj2sL2XuMNbLRE4b4B/4ENPsp2Q8P44fjAZ0Pw==", "dev": true, "requires": { - "git-up": "^4.0.0" + "git-up": "4.0.2" } }, "gitconfiglocal": { @@ -31669,7 +9240,7 @@ "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", "dev": true, "requires": { - "ini": "^1.3.2" + "ini": "1.3.8" } }, "github-slugger": { @@ -31678,21 +9249,65 @@ "integrity": "sha512-wIaa75k1vZhyPm9yWrD08A5Xnx/V+RmzGrpjQuLemGKSb77Qukiaei58Bogrl/LZSADDfPzKJX8jhLs4CRTl7Q==", "dev": true, "requires": { - "emoji-regex": ">=6.0.0 <=6.1.1" + "emoji-regex": "6.1.1" + }, + "dependencies": { + "emoji-regex": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", + "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", + "dev": true + } } }, "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "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" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "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" + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } } }, "glob-parent": { @@ -31701,7 +9316,7 @@ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { - "is-glob": "^4.0.1" + "is-glob": "4.0.1" } }, "glob-stream": { @@ -31710,16 +9325,16 @@ "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", "dev": true, "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" + "extend": "3.0.2", + "glob": "7.1.7", + "glob-parent": "3.1.0", + "is-negated-glob": "1.0.0", + "ordered-read-streams": "1.0.1", + "pumpify": "1.5.1", + "readable-stream": "2.3.7", + "remove-trailing-separator": "1.1.0", + "to-absolute-glob": "2.0.2", + "unique-stream": "2.3.1" }, "dependencies": { "glob-parent": { @@ -31728,8 +9343,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "is-glob": "3.1.0", + "path-dirname": "1.0.2" } }, "is-glob": { @@ -31738,30 +9353,48 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "2.1.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" } } } }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, "glob-watcher": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" + "anymatch": "2.0.0", + "async-done": "1.3.2", + "chokidar": "2.1.8", + "is-negated-glob": "1.0.0", + "just-debounce": "1.1.0", + "normalize-path": "3.0.0", + "object.defaults": "1.1.0" }, "dependencies": { "anymatch": { @@ -31770,8 +9403,8 @@ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "micromatch": "3.1.10", + "normalize-path": "2.1.1" }, "dependencies": { "normalize-path": { @@ -31780,7 +9413,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "remove-trailing-separator": "1.1.0" } } } @@ -31797,16 +9430,27 @@ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.4", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "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.1" + } + } } }, "chokidar": { @@ -31815,27 +9459,18 @@ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "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" + "anymatch": "2.0.0", + "async-each": "1.0.3", + "braces": "2.3.2", + "fsevents": "1.2.13", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.1", + "normalize-path": "3.0.0", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1", + "upath": "1.2.0" } }, "fill-range": { @@ -31844,10 +9479,21 @@ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "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.1" + } + } } }, "fsevents": { @@ -31857,8 +9503,8 @@ "dev": true, "optional": true, "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" + "bindings": "1.5.0", + "nan": "2.14.2" } }, "glob-parent": { @@ -31867,8 +9513,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "is-glob": "3.1.0", + "path-dirname": "1.0.2" }, "dependencies": { "is-glob": { @@ -31877,7 +9523,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "2.1.1" } } } @@ -31888,14 +9534,64 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "1.13.1" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.3", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } }, "readdirp": { "version": "2.2.1", @@ -31903,9 +9599,18 @@ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "graceful-fs": "4.2.6", + "micromatch": "3.1.10", + "readable-stream": "2.3.7" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" } }, "to-regex-range": { @@ -31914,8 +9619,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "3.0.0", + "repeat-string": "1.6.1" } } } @@ -31926,9 +9631,9 @@ "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" } }, "global-prefix": { @@ -31937,11 +9642,11 @@ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.3", + "ini": "1.3.8", + "is-windows": "1.0.2", + "which": "1.3.1" }, "dependencies": { "which": { @@ -31950,7 +9655,7 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } } } @@ -31968,39 +9673,14 @@ "dev": true }, "globule": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.3.tgz", - "integrity": "sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", + "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", "dev": true, "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "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" - } - }, - "minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } + "glob": "7.1.7", + "lodash": "4.17.21", + "minimatch": "3.0.4" } }, "glogg": { @@ -32009,32 +9689,32 @@ "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", "dev": true, "requires": { - "sparkles": "^1.0.0" + "sparkles": "1.0.1" } }, "got": { - "version": "11.8.3", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", - "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", + "version": "11.8.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", + "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", "dev": true, "requires": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" + "@sindresorhus/is": "4.0.1", + "@szmarczak/http-timer": "4.0.5", + "@types/cacheable-request": "6.0.1", + "@types/responselike": "1.0.0", + "cacheable-lookup": "5.0.4", + "cacheable-request": "7.0.2", + "decompress-response": "6.0.0", + "http2-wrapper": "1.0.3", + "lowercase-keys": "2.0.0", + "p-cancelable": "2.1.1", + "responselike": "2.0.0" } }, "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, "grapheme-splitter": { @@ -32055,647 +9735,423 @@ "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", "dev": true, "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - } - }, - "gulp-clean": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/gulp-clean/-/gulp-clean-0.3.2.tgz", - "integrity": "sha1-o0fUc6zqQBgvk1WHpFGUFnGSgQI=", - "dev": true, - "requires": { - "gulp-util": "^2.2.14", - "rimraf": "^2.2.8", - "through2": "^0.4.2" + "glob-watcher": "5.0.5", + "gulp-cli": "2.3.0", + "undertaker": "1.3.0", + "vinyl-fs": "3.0.3" }, "dependencies": { - "ansi-regex": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", - "dev": true - }, - "ansi-styles": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", - "dev": true - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "chalk": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true, - "requires": { - "ansi-styles": "^1.1.0", - "escape-string-regexp": "^1.0.0", - "has-ansi": "^0.1.0", - "strip-ansi": "^0.3.0", - "supports-color": "^0.2.0" - } - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "gulp-util": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", - "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", - "dev": true, - "requires": { - "chalk": "^0.5.0", - "dateformat": "^1.0.7-1.2.3", - "lodash._reinterpolate": "^2.4.1", - "lodash.template": "^2.4.1", - "minimist": "^0.2.0", - "multipipe": "^0.1.0", - "through2": "^0.5.0", - "vinyl": "^0.2.1" - }, - "dependencies": { - "through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" - } - }, - "xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true - } - } - }, - "has-ansi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true, - "requires": { - "ansi-regex": "^0.2.0" - } - }, - "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" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "lodash._reinterpolate": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", - "dev": true - }, - "lodash.defaults": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", - "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1", - "lodash.keys": "~2.4.1" - } - }, - "lodash.template": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", - "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true, - "requires": { - "lodash._escapestringchar": "~2.4.1", - "lodash._reinterpolate": "~2.4.1", - "lodash.defaults": "~2.4.1", - "lodash.escape": "~2.4.1", - "lodash.keys": "~2.4.1", - "lodash.templatesettings": "~2.4.1", - "lodash.values": "~2.4.1" - } - }, - "lodash.templatesettings": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~2.4.1", - "lodash.escape": "~2.4.1" - } - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - } - } - }, - "minimist": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.1.tgz", - "integrity": "sha512-GY8fANSrTMfBVfInqJAY41QkOM+upUTytK1jZ0c8+3HdHrJxBJ3rF5i9moClXTE8uUSnUo8cAsCoxDXvSY4DHg==", - "dev": true - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { + "ansi-colors": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "ansi-wrap": "0.1.0" } }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" } }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" + "gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "requires": { + "ansi-colors": "1.1.0", + "archy": "1.0.0", + "array-sort": "1.0.0", + "color-support": "1.1.3", + "concat-stream": "1.6.2", + "copy-props": "2.0.5", + "fancy-log": "1.3.3", + "gulplog": "1.0.0", + "interpret": "1.4.0", + "isobject": "3.0.1", + "liftoff": "3.1.0", + "matchdep": "2.0.0", + "mute-stdout": "1.0.1", + "pretty-hrtime": "1.0.3", + "replace-homedir": "1.0.0", + "semver-greatest-satisfied-range": "1.1.0", + "v8flags": "3.2.0", + "yargs": "7.1.2" } }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "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": { - "glob": "^7.1.3" + "number-is-nan": "1.0.1" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, - "strip-ansi": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true, - "requires": { - "ansi-regex": "^0.2.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "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": { - "is-utf8": "^0.2.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "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": { - "get-stdin": "^4.0.1" + "ansi-regex": "2.1.1" } }, - "supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, - "through2": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", - "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { - "readable-stream": "~1.0.17", - "xtend": "~2.1.1" + "string-width": "1.0.2", + "strip-ansi": "3.0.1" } }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", "dev": true }, - "vinyl": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", - "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "yargs": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", "dev": true, "requires": { - "clone-stats": "~0.0.1" + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.3", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.2", + "yargs-parser": "5.0.1" } }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "yargs-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", "dev": true, "requires": { - "object-keys": "~0.4.0" + "camelcase": "3.0.0", + "object.assign": "4.1.2" } } } }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" + "gulp-clean": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/gulp-clean/-/gulp-clean-0.3.2.tgz", + "integrity": "sha1-o0fUc6zqQBgvk1WHpFGUFnGSgQI=", + "dev": true, + "requires": { + "gulp-util": "2.2.20", + "rimraf": "2.5.4", + "through2": "0.4.2" }, "dependencies": { - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", "dev": true }, "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "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=", + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "camelcase": "2.1.1", + "map-obj": "1.0.1" } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" } }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", "dev": true }, - "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=", + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "get-stdin": "4.0.1", + "meow": "3.7.0" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "gulp-util": { + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", + "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "chalk": "0.5.1", + "dateformat": "1.0.12", + "lodash._reinterpolate": "2.4.1", + "lodash.template": "2.4.1", + "minimist": "0.2.1", + "multipipe": "0.1.2", + "through2": "0.5.1", + "vinyl": "0.2.3" + }, + "dependencies": { + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "3.0.0" + } + } } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", "dev": true, "requires": { - "error-ex": "^1.2.0" + "ansi-regex": "0.2.1" } }, - "path-exists": { + "indent-string": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "repeating": "2.0.1" } }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.5", + "normalize-package-data": "2.5.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } } }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "minimist": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.1.tgz", + "integrity": "sha512-GY8fANSrTMfBVfInqJAY41QkOM+upUTytK1jZ0c8+3HdHrJxBJ3rF5i9moClXTE8uUSnUo8cAsCoxDXvSY4DHg==", "dev": true }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" } }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "indent-string": "2.1.0", + "strip-indent": "1.0.1" } }, + "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-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "0.2.1" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "get-stdin": "4.0.1" } }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", "dev": true }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "requires": { + "object-keys": "0.4.0" + } + } } }, - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, - "yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "vinyl": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", "dev": true, "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" + "clone-stats": "0.0.1" } }, - "yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true } } }, @@ -32705,19 +10161,43 @@ "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", "dev": true, "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" + "concat-with-sourcemaps": "1.1.0", + "through2": "2.0.5", + "vinyl": "2.2.1" }, "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "readable-stream": "2.3.7", + "xtend": "4.0.2" } } } @@ -32728,15 +10208,15 @@ "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", "dev": true, "requires": { - "ansi-colors": "^2.0.5", - "connect": "^3.6.6", - "connect-livereload": "^0.6.0", - "fancy-log": "^1.3.2", - "map-stream": "^0.0.7", - "send": "^0.16.2", - "serve-index": "^1.9.1", - "serve-static": "^1.13.2", - "tiny-lr": "^1.1.1" + "ansi-colors": "2.0.5", + "connect": "3.7.0", + "connect-livereload": "0.6.1", + "fancy-log": "1.3.3", + "map-stream": "0.0.7", + "send": "0.16.2", + "serve-index": "1.9.1", + "serve-static": "1.14.1", + "tiny-lr": "1.1.1" }, "dependencies": { "ansi-colors": { @@ -32745,31 +10225,22 @@ "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "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", + "depd": "1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "statuses": "1.4.0" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", "dev": true }, "mime": { @@ -32778,12 +10249,6 @@ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", "dev": true }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", @@ -32791,18 +10256,18 @@ "dev": true, "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", "fresh": "0.5.2", - "http-errors": "~1.6.2", + "http-errors": "1.6.3", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" + "on-finished": "2.3.0", + "range-parser": "1.2.1", + "statuses": "1.4.0" } }, "setprototypeof": { @@ -32825,9 +10290,9 @@ "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", "dev": true, "requires": { - "eslint": "^4.0.0", - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.0" + "eslint": "4.19.1", + "fancy-log": "1.3.3", + "plugin-error": "1.0.1" }, "dependencies": { "acorn": { @@ -32842,7 +10307,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "^3.0.4" + "acorn": "3.3.0" }, "dependencies": { "acorn": { @@ -32853,24 +10318,11 @@ } } }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, "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, - "requires": {} + "dev": true }, "ansi-escapes": { "version": "3.2.0", @@ -32884,6 +10336,15 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, "chardet": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", @@ -32896,7 +10357,7 @@ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "restore-cursor": "2.0.0" } }, "cli-width": { @@ -32911,9 +10372,9 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "lru-cache": "4.1.5", + "shebang-command": "1.2.0", + "which": "1.3.1" } }, "debug": { @@ -32922,7 +10383,7 @@ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.3" } }, "doctrine": { @@ -32931,7 +10392,7 @@ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "^2.0.2" + "esutils": "2.0.3" } }, "eslint": { @@ -32940,44 +10401,44 @@ "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", - "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^1.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.4.2", + "concat-stream": "1.6.2", + "cross-spawn": "5.1.0", + "debug": "3.2.7", + "doctrine": "2.1.0", + "eslint-scope": "3.7.3", + "eslint-visitor-keys": "1.3.0", + "espree": "3.5.4", + "esquery": "1.4.0", + "esutils": "2.0.3", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.7", + "globals": "11.12.0", + "ignore": "3.3.10", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.14.1", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.21", + "minimatch": "3.0.4", + "mkdirp": "0.5.5", + "natural-compare": "1.4.0", + "optionator": "0.8.3", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.3", + "regexpp": "1.1.0", + "require-uncached": "1.0.3", + "semver": "5.7.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", "table": "4.0.2", - "text-table": "~0.2.0" + "text-table": "0.2.0" } }, "eslint-scope": { @@ -32986,8 +10447,8 @@ "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "esrecurse": "4.3.0", + "estraverse": "4.3.0" } }, "eslint-visitor-keys": { @@ -33002,8 +10463,8 @@ "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" + "acorn": "5.7.4", + "acorn-jsx": "3.0.1" } }, "external-editor": { @@ -33012,24 +10473,18 @@ "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" + "chardet": "0.4.2", + "iconv-lite": "0.4.24", + "tmp": "0.0.33" } }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5" + "escape-string-regexp": "1.0.5" } }, "file-entry-cache": { @@ -33038,8 +10493,8 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "1.3.4", + "object-assign": "4.1.1" } }, "flat-cache": { @@ -33048,10 +10503,10 @@ "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", "dev": true, "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" + "circular-json": "0.3.3", + "graceful-fs": "4.2.6", + "rimraf": "2.6.3", + "write": "0.2.1" } }, "ignore": { @@ -33066,20 +10521,20 @@ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", + "ansi-escapes": "3.2.0", + "chalk": "2.4.2", + "cli-cursor": "2.1.0", + "cli-width": "2.2.1", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.21", "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" + "run-async": "2.4.1", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" } }, "is-fullwidth-code-point": { @@ -33088,11 +10543,15 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.1" + } }, "levn": { "version": "0.3.0", @@ -33100,18 +10559,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "prelude-ls": "1.1.2", + "type-check": "0.3.2" } }, "mimic-fn": { @@ -33126,9 +10575,15 @@ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "^1.2.5" + "minimist": "1.2.5" } }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -33141,7 +10596,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "1.2.0" } }, "optionator": { @@ -33150,12 +10605,12 @@ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "word-wrap": "1.2.3" } }, "prelude-ls": { @@ -33176,8 +10631,8 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "onetime": "2.0.1", + "signal-exit": "3.0.3" } }, "rimraf": { @@ -33186,7 +10641,7 @@ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "glob": "^7.1.3" + "glob": "7.1.7" } }, "semver": { @@ -33201,7 +10656,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "1.0.0" } }, "shebang-regex": { @@ -33216,7 +10671,7 @@ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0" + "is-fullwidth-code-point": "2.0.0" } }, "string-width": { @@ -33225,8 +10680,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" } }, "strip-ansi": { @@ -33235,21 +10690,27 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.4.2", + "lodash": "4.17.21", "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "string-width": "2.1.1" } }, "type-check": { @@ -33258,7 +10719,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "1.1.2" } }, "which": { @@ -33267,25 +10728,83 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true } } }, "gulp-footer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-2.1.0.tgz", - "integrity": "sha512-CK3nRBP3PG59XN2L1rDLkBHA7goYsW+tJuVQccLP9jq3mpBT2kuRq0ImgNjrUkDbF948aCVQH4J7uIEqiZ2MHA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-2.0.2.tgz", + "integrity": "sha512-HsG5VOgKHFRqZXnHGI6oGhPDg70p9pobM+dYOnjBZVLMQUHzLG6bfaPNRJ7XG707E+vWO3TfN0CND9UrYhk94g==", "dev": true, "requires": { - "lodash": "^4.17.21", - "map-stream": "^0.0.7" + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "map-stream": "0.0.7" + }, + "dependencies": { + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + } } }, "gulp-header": { @@ -33294,20 +10813,75 @@ "integrity": "sha512-LMGiBx+qH8giwrOuuZXSGvswcIUh0OiioNkUpLhNyvaC6/Ga8X6cfAeme2L5PqsbXMhL8o8b/OmVqIQdxprhcQ==", "dev": true, "requires": { - "concat-with-sourcemaps": "^1.1.0", - "lodash.template": "^4.5.0", + "concat-with-sourcemaps": "1.1.0", + "lodash.template": "4.5.0", "map-stream": "0.0.7", - "through2": "^2.0.0" + "through2": "2.0.5" }, "dependencies": { + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.templatesettings": "4.2.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0" + } + }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "readable-stream": "2.3.7", + "xtend": "4.0.2" } } } @@ -33318,19 +10892,25 @@ "integrity": "sha512-fCUEngzNiEZEK2YuPm+sdMpO6ukb8+/qzbGfJBXyNOXz85bCG7yBI+pPSl+N90d7gnLvMsarthsAImx0qy7BAw==", "dev": true, "requires": { - "gulp-match": "^1.1.0", - "ternary-stream": "^3.0.0", - "through2": "^3.0.1" + "gulp-match": "1.1.0", + "ternary-stream": "3.0.0", + "through2": "3.0.2" }, "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, "through2": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", "dev": true, "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" + "inherits": "2.0.4", + "readable-stream": "3.6.0" } } } @@ -33341,7 +10921,7 @@ "integrity": "sha1-HNRF+9AJ4Np2lZoDp/SbNWav+Gg=", "dev": true, "requires": { - "through2": "^0.6.3" + "through2": "0.6.5" }, "dependencies": { "isarray": { @@ -33356,10 +10936,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "string_decoder": { @@ -33374,8 +10954,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.2" } } } @@ -33386,7 +10966,7 @@ "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", "dev": true, "requires": { - "minimatch": "^3.0.3" + "minimatch": "3.0.4" } }, "gulp-replace": { @@ -33395,17 +10975,17 @@ "integrity": "sha512-HcPHpWY4XdF8zxYkDODHnG2+7a3nD/Y8Mfu3aBgMiCFDW3X2GiOKXllsAmILcxe3KZT2BXoN18WrpEFm48KfLQ==", "dev": true, "requires": { - "@types/node": "^14.14.41", - "@types/vinyl": "^2.0.4", - "istextorbinary": "^3.0.0", - "replacestream": "^4.0.3", - "yargs-parser": ">=5.0.0-security.0" + "@types/node": "14.17.4", + "@types/vinyl": "2.0.4", + "istextorbinary": "3.3.0", + "replacestream": "4.0.3", + "yargs-parser": "20.2.9" }, "dependencies": { "@types/node": { - "version": "14.18.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", - "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "version": "14.17.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz", + "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==", "dev": true } } @@ -33416,12 +10996,12 @@ "integrity": "sha512-wHNCgmqbWkk1c6Gc2dOL5SprcoeujQdeepICwfQRo91DIylTE7a794VEE+leq3cE2YDoiS5ulvRfKVIEMazcTQ==", "dev": true, "requires": { - "chalk": "^3.0.0", - "fancy-log": "^1.3.3", - "lodash.template": "^4.5.0", - "plugin-error": "^1.0.1", - "through2": "^3.0.1", - "tslib": "^1.10.0" + "chalk": "3.0.0", + "fancy-log": "1.3.3", + "lodash.template": "4.5.0", + "plugin-error": "1.0.1", + "through2": "3.0.2", + "tslib": "1.14.1" }, "dependencies": { "ansi-styles": { @@ -33430,7 +11010,7 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, "chalk": { @@ -33439,8 +11019,8 @@ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" } }, "color-convert": { @@ -33449,14 +11029,51 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "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 + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.templatesettings": "4.2.0" } }, - "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 + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0" + } }, "supports-color": { "version": "7.2.0", @@ -33464,7 +11081,7 @@ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } }, "through2": { @@ -33473,8 +11090,8 @@ "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", "dev": true, "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" + "inherits": "2.0.4", + "readable-stream": "3.6.0" } } } @@ -33485,17 +11102,17 @@ "integrity": "sha512-RqvUckJkuYqy4VaIH60RMal4ZtG0IbQ6PXMNkNsshEGJ9cldUPRb/YCgboYae+CLAs1HQNb4ADTKCx65HInquQ==", "dev": true, "requires": { - "@gulp-sourcemaps/identity-map": "^2.0.1", - "@gulp-sourcemaps/map-sources": "^1.0.0", - "acorn": "^6.4.1", - "convert-source-map": "^1.0.0", - "css": "^3.0.0", - "debug-fabulous": "^1.0.0", - "detect-newline": "^2.0.0", - "graceful-fs": "^4.0.0", - "source-map": "^0.6.0", - "strip-bom-string": "^1.0.0", - "through2": "^2.0.0" + "@gulp-sourcemaps/identity-map": "2.0.1", + "@gulp-sourcemaps/map-sources": "1.0.0", + "acorn": "6.4.2", + "convert-source-map": "1.8.0", + "css": "3.0.0", + "debug-fabulous": "1.1.0", + "detect-newline": "2.1.0", + "graceful-fs": "4.2.6", + "source-map": "0.6.1", + "strip-bom-string": "1.0.0", + "through2": "2.0.5" }, "dependencies": { "acorn": { @@ -33504,34 +11121,64 @@ "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, "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 }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "readable-stream": "2.3.7", + "xtend": "4.0.2" } } } }, "gulp-terser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-terser/-/gulp-terser-2.1.0.tgz", - "integrity": "sha512-lQ3+JUdHDVISAlUIUSZ/G9Dz/rBQHxOiYDQ70IVWFQeh4b33TC1MCIU+K18w07PS3rq/CVc34aQO4SUbdaNMPQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gulp-terser/-/gulp-terser-2.0.1.tgz", + "integrity": "sha512-XCrnCXP8ovNpgLK9McJIXlgm0j3W2TsiWu7K9y3m+Sn5XZgUzi6U8MPHtS3NdLMic9poCj695N0ARJ2B6atypw==", "dev": true, "requires": { - "plugin-error": "^1.0.1", - "terser": "^5.9.0", - "through2": "^4.0.2", - "vinyl-sourcemaps-apply": "^0.2.1" + "plugin-error": "1.0.1", + "terser": "5.4.0", + "through2": "4.0.2", + "vinyl-sourcemaps-apply": "0.2.1" } }, "gulp-util": { @@ -33540,24 +11187,24 @@ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.3", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.5", + "multipipe": "0.1.2", + "object-assign": "3.0.0", "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" + "through2": "2.0.5", + "vinyl": "0.5.3" }, "dependencies": { "ansi-regex": { @@ -33578,32 +11225,38 @@ "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" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, "clone-stats": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", "dev": true }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, "lodash.escape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "^3.0.0" + "lodash._root": "3.0.1" } }, "lodash.keys": { @@ -33612,9 +11265,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" } }, "lodash.template": { @@ -33623,15 +11276,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" } }, "lodash.templatesettings": { @@ -33640,8 +11293,8 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" } }, "object-assign": { @@ -33650,13 +11303,43 @@ "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", "dev": true }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, "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" + "ansi-regex": "2.1.1" } }, "supports-color": { @@ -33671,8 +11354,8 @@ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "readable-stream": "2.3.7", + "xtend": "4.0.2" } }, "vinyl": { @@ -33681,8 +11364,8 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } } @@ -33694,16 +11377,25 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "^1.0.0" + "glogg": "1.0.2" } }, "gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", + "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", "dev": true, "requires": { - "duplexer": "^0.1.2" + "duplexer": "0.1.2", + "pify": "4.0.1" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } } }, "handlebars": { @@ -33712,11 +11404,11 @@ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" + "minimist": "1.2.5", + "neo-async": "2.6.2", + "source-map": "0.6.1", + "uglify-js": "3.13.9", + "wordwrap": "1.0.0" }, "dependencies": { "source-map": { @@ -33739,8 +11431,8 @@ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" + "ajv": "6.12.6", + "har-schema": "2.0.0" }, "dependencies": { "ajv": { @@ -33749,10 +11441,10 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "3.1.3", + "fast-json-stable-stringify": "2.1.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.4.1" } } } @@ -33769,7 +11461,7 @@ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "^1.1.1" + "function-bind": "1.1.1" } }, "has-ansi": { @@ -33778,7 +11470,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" }, "dependencies": { "ansi-regex": { @@ -33796,9 +11488,9 @@ "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==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "has-gulplog": { @@ -33807,33 +11499,24 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "^1.0.0" + "sparkles": "1.0.1" } }, "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" } }, "has-values": { @@ -33842,15 +11525,29 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-number": "3.0.0", + "kind-of": "4.0.0" }, "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } }, "kind-of": { "version": "4.0.0", @@ -33858,11 +11555,53 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "2.0.4", + "readable-stream": "3.6.0", + "safe-buffer": "5.2.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", + "dev": true, + "optional": true + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, "hast-util-is-element": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz", @@ -33875,7 +11614,7 @@ "integrity": "sha512-+2I0x2ZCAyiZOO/sb4yNLFmdwPBnyJ4PBkVTUMKMqBwYNA+lXSgOmoRXlJFazoyid9QPogRRKgKhVEodv181sA==", "dev": true, "requires": { - "xtend": "^4.0.0" + "xtend": "4.0.2" } }, "hast-util-to-html": { @@ -33884,16 +11623,16 @@ "integrity": "sha512-yk2+1p3EJTEE9ZEUkgHsUSVhIpCsL/bvT8E5GzmWc+N1Po5gBw+0F8bo7dpxXR0nu0bQVxVZGX2lBGF21CmeDw==", "dev": true, "requires": { - "ccount": "^1.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-is-element": "^1.0.0", - "hast-util-whitespace": "^1.0.0", - "html-void-elements": "^1.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0", - "stringify-entities": "^3.0.1", - "unist-util-is": "^4.0.0", - "xtend": "^4.0.0" + "ccount": "1.1.0", + "comma-separated-tokens": "1.0.8", + "hast-util-is-element": "1.1.0", + "hast-util-whitespace": "1.0.4", + "html-void-elements": "1.0.5", + "property-information": "5.6.0", + "space-separated-tokens": "1.1.5", + "stringify-entities": "3.1.0", + "unist-util-is": "4.1.0", + "xtend": "4.0.2" } }, "hast-util-whitespace": { @@ -33903,9 +11642,9 @@ "dev": true }, "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "highlight.js": { @@ -33914,14 +11653,15 @@ "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", "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=", + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" + "hash.js": "1.1.7", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" } }, "homedir-polyfill": { @@ -33930,9 +11670,15 @@ "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, "requires": { - "parse-passwd": "^1.0.0" + "parse-passwd": "1.0.0" } }, + "hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "dev": true + }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -33958,21 +11704,21 @@ "dev": true }, "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" + "depd": "1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": "1.5.0", + "toidentifier": "1.0.0" } }, "http-parser-js": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", - "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", "dev": true }, "http-proxy": { @@ -33981,9 +11727,9 @@ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" + "eventemitter3": "4.0.7", + "follow-redirects": "1.14.1", + "requires-port": "1.0.0" } }, "http-signature": { @@ -33992,9 +11738,9 @@ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.16.1" } }, "http2-wrapper": { @@ -34003,18 +11749,41 @@ "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", "dev": true, "requires": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" + "quick-lru": "5.1.1", + "resolve-alpn": "1.1.2" } }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, "https-proxy-agent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", "dev": true, "requires": { - "agent-base": "5", - "debug": "4" + "agent-base": "5.1.1", + "debug": "4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } } }, "iconv-lite": { @@ -34022,9 +11791,22 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true, + "optional": true + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -34043,8 +11825,8 @@ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "parent-module": "1.0.1", + "resolve-from": "4.0.0" }, "dependencies": { "resolve-from": { @@ -34062,9 +11844,15 @@ "dev": true }, "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "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", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "dev": true }, "inflight": { @@ -34073,14 +11861,14 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.8", @@ -34089,25 +11877,25 @@ "dev": true }, "inquirer": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.5.tgz", - "integrity": "sha512-G6/9xUqmt/r+UvufSyrPpt84NYwhKZ9jLsgMbQzlx804XErNupor8WQdBnBRrXmBfTPpuwf1sV+ss2ovjgdXIg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.1.tgz", + "integrity": "sha512-hUDjc3vBkh/uk1gPfMAD/7Z188Q8cvTGl0nxwaCdwSbzFh6ZKkZh+s2ozVxbE5G9ZNRyeY0+lgbAIOUFsFf98w==", + "dev": true, + "requires": { + "ansi-escapes": "4.3.2", + "chalk": "4.1.1", + "cli-cursor": "3.1.0", + "cli-width": "3.0.0", + "external-editor": "3.1.0", + "figures": "3.2.0", + "lodash": "4.17.21", "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.2.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" + "ora": "5.4.1", + "run-async": "2.4.1", + "rxjs": "6.6.7", + "string-width": "4.2.2", + "strip-ansi": "6.0.0", + "through": "2.3.8" }, "dependencies": { "ansi-styles": { @@ -34116,17 +11904,17 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" } }, "color-convert": { @@ -34135,7 +11923,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -34144,43 +11932,29 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } } } }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, "interpret": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", @@ -34198,24 +11972,27 @@ "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", "dev": true, "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" + "is-relative": "1.0.0", + "is-windows": "1.0.2" } }, "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } } } }, @@ -34231,18 +12008,17 @@ "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", "dev": true, "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" + "is-alphabetical": "1.0.4", + "is-decimal": "1.0.4" } }, "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bind": "1.0.2" } }, "is-arrayish": { @@ -34252,13 +12028,10 @@ "dev": true }, "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true }, "is-binary-path": { "version": "2.1.0", @@ -34266,65 +12039,64 @@ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "requires": { - "binary-extensions": "^2.0.0" + "binary-extensions": "2.2.0" } }, "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bind": "1.0.2" } }, "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", "dev": true }, "is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", "dev": true, "requires": { - "has": "^1.0.3" + "has": "1.0.3" } }, "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } } } }, "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "dev": true }, "is-decimal": { "version": "1.0.4", @@ -34333,20 +12105,20 @@ "dev": true }, "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" }, "dependencies": { "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } @@ -34357,26 +12129,27 @@ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-plain-object": "^2.0.4" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } + "is-primitive": "2.0.0" } }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -34392,25 +12165,16 @@ "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 - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "is-extglob": "2.1.1" } }, "is-hexadecimal": { @@ -34431,16 +12195,6 @@ "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", "dev": true }, - "is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, "is-negated-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", @@ -34448,45 +12202,22 @@ "dev": true }, "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", "dev": true }, "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true }, "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true }, "is-obj": { "version": "2.0.0", @@ -34495,15 +12226,30 @@ "dev": true }, "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, "is-promise": { @@ -34513,13 +12259,13 @@ "dev": true }, "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bind": "1.0.2", + "has-symbols": "1.0.2" } }, "is-relative": { @@ -34528,7 +12274,7 @@ "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "requires": { - "is-unc-path": "^1.0.0" + "is-unc-path": "1.0.0" } }, "is-resolvable": { @@ -34549,19 +12295,13 @@ "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", "dev": true }, - "is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", - "dev": true - }, "is-ssh": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.3.tgz", "integrity": "sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ==", "dev": true, "requires": { - "protocols": "^1.1.0" + "protocols": "1.4.8" } }, "is-stream": { @@ -34571,13 +12311,10 @@ "dev": true }, "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true }, "is-symbol": { "version": "1.0.4", @@ -34585,7 +12322,7 @@ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "has-symbols": "1.0.2" } }, "is-text-path": { @@ -34594,20 +12331,20 @@ "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", "dev": true, "requires": { - "text-extensions": "^1.0.0" + "text-extensions": "1.9.0" } }, "is-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", - "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0" + "available-typed-arrays": "1.0.4", + "call-bind": "1.0.2", + "es-abstract": "1.18.3", + "foreach": "2.0.5", + "has-symbols": "1.0.2" } }, "is-typedarray": { @@ -34622,7 +12359,7 @@ "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, "requires": { - "unc-path-regex": "^0.1.2" + "unc-path-regex": "0.1.2" } }, "is-unicode-supported": { @@ -34649,24 +12386,11 @@ "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", "dev": true }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", + "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==", + "dev": true }, "is-windows": { "version": "1.0.2", @@ -34680,13 +12404,13 @@ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, "requires": { - "is-docker": "^2.0.0" + "is-docker": "2.2.1" } }, "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "isbinaryfile": { @@ -34719,33 +12443,54 @@ "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.7.7", + "js-yaml": "3.14.1", + "mkdirp": "0.5.5", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.1", + "wordwrap": "1.0.0" }, "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "has-flag": { @@ -34754,13 +12499,31 @@ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.1" + }, + "dependencies": { + "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 + } + } + }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "^1.2.5" + "minimist": "1.2.5" } }, "resolve": { @@ -34775,7 +12538,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } }, "which": { @@ -34784,15 +12547,15 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } } } }, "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", "dev": true }, "istanbul-lib-instrument": { @@ -34801,10 +12564,10 @@ "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, "requires": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" + "@babel/core": "7.14.6", + "@istanbuljs/schema": "0.1.3", + "istanbul-lib-coverage": "3.0.0", + "semver": "6.3.0" } }, "istanbul-lib-report": { @@ -34813,33 +12576,54 @@ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" + "istanbul-lib-coverage": "3.0.0", + "make-dir": "3.1.0", + "supports-color": "7.2.0" }, "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } } } }, "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", "dev": true, "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "debug": "4.3.1", + "istanbul-lib-coverage": "3.0.0", + "source-map": "0.6.1" }, "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -34849,13 +12633,13 @@ } }, "istanbul-reports": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", - "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", "dev": true, "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "html-escaper": "2.0.2", + "istanbul-lib-report": "3.0.0" } }, "istextorbinary": { @@ -34864,8 +12648,8 @@ "integrity": "sha512-Tvq1W6NAcZeJ8op+Hq7tdZ434rqnMx4CCZ7H0ff83uEloDvVbqAwaMTZcafKGJT0VHkYzuXUiCY4hlXQg6WfoQ==", "dev": true, "requires": { - "binaryextensions": "^2.2.0", - "textextensions": "^3.2.0" + "binaryextensions": "2.3.0", + "textextensions": "3.3.0" } }, "jake": { @@ -34874,30 +12658,22 @@ "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", "dev": true, "requires": { - "async": "0.9.x", - "chalk": "^2.4.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - } + "async": "0.9.2", + "chalk": "2.4.2", + "filelist": "1.0.2", + "minimatch": "3.0.4" } }, "jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.2.tgz", + "integrity": "sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==", "dev": true, "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "chalk": "4.1.1", + "diff-sequences": "27.0.1", + "jest-get-type": "27.0.1", + "pretty-format": "27.0.2" }, "dependencies": { "ansi-styles": { @@ -34906,17 +12682,17 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" } }, "color-convert": { @@ -34925,7 +12701,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -34934,33 +12710,39 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } } } }, "jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "version": "27.0.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.1.tgz", + "integrity": "sha512-9Tggo9zZbu0sHKebiAijyt1NM77Z0uO4tuWOxUCujAiSeXv30Vb5D4xVF4UR4YWNapcftj+PbByU54lKD7/xMg==", "dev": true }, "jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz", + "integrity": "sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA==", "dev": true, "requires": { - "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "chalk": "4.1.1", + "jest-diff": "27.0.2", + "jest-get-type": "27.0.1", + "pretty-format": "27.0.2" }, "dependencies": { "ansi-styles": { @@ -34969,17 +12751,17 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" } }, "color-convert": { @@ -34988,7 +12770,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -34997,32 +12779,38 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } } } }, "jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", + "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "dev": true, + "requires": { + "@babel/code-frame": "7.14.5", + "@jest/types": "27.0.2", + "@types/stack-utils": "2.0.0", + "chalk": "4.1.1", + "graceful-fs": "4.2.6", + "micromatch": "4.0.4", + "pretty-format": "27.0.2", + "slash": "3.0.0", + "stack-utils": "2.0.3" }, "dependencies": { "ansi-styles": { @@ -35031,17 +12819,17 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" } }, "color-convert": { @@ -35050,7 +12838,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -35059,15 +12847,11 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "supports-color": { "version": "7.2.0", @@ -35075,21 +12859,16 @@ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } } } }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } + "jest-regex-util": { + "version": "27.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.1.tgz", + "integrity": "sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==", + "dev": true }, "js-tokens": { "version": "4.0.0", @@ -35098,21 +12877,12 @@ "dev": true }, "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "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 - } + "argparse": "2.0.1" } }, "jsbn": { @@ -35133,6 +12903,12 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -35146,9 +12922,9 @@ "dev": true }, "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, "json-schema-traverse": { @@ -35175,7 +12951,7 @@ "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, "requires": { - "minimist": "^1.2.5" + "minimist": "1.2.5" } }, "jsonfile": { @@ -35184,8 +12960,8 @@ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "graceful-fs": "4.2.6", + "universalify": "2.0.0" } }, "jsonparse": { @@ -35194,25 +12970,15 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", - "json-schema": "0.4.0", + "json-schema": "0.2.3", "verror": "1.10.0" } }, @@ -35234,44 +13000,49 @@ "dev": true }, "karma": { - "version": "6.3.17", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.17.tgz", - "integrity": "sha512-2TfjHwrRExC8yHoWlPBULyaLwAFmXmxQrcuFImt/JsAsSZu1uOWTZ1ZsWjqQtWpHLiatJOHL5jFjXSJIgCd01g==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.2.0", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" + "version": "6.3.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.4.tgz", + "integrity": "sha512-hbhRogUYIulfkBTZT7xoPrCYhRBnBoqbbL4fszWD0ReFGUxU+LYBr3dwKdAluaDQ/ynT9/7C+Lf7pPNW4gSx4Q==", + "dev": true, + "requires": { + "body-parser": "1.19.0", + "braces": "3.0.2", + "chokidar": "3.5.2", + "colors": "1.4.0", + "connect": "3.7.0", + "di": "0.0.1", + "dom-serialize": "2.2.1", + "glob": "7.1.7", + "graceful-fs": "4.2.6", + "http-proxy": "1.18.1", + "isbinaryfile": "4.0.8", + "lodash": "4.17.21", + "log4js": "6.3.0", + "mime": "2.5.2", + "minimatch": "3.0.4", + "qjobs": "1.2.0", + "range-parser": "1.2.1", + "rimraf": "3.0.2", + "socket.io": "3.1.2", + "source-map": "0.6.1", + "tmp": "0.2.1", + "ua-parser-js": "0.7.28", + "yargs": "16.2.0" }, "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { - "minimist": "^1.2.5" + "glob": "7.1.7" } }, "source-map": { @@ -35286,7 +13057,7 @@ "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", "dev": true, "requires": { - "rimraf": "^3.0.0" + "rimraf": "3.0.2" } }, "yargs": { @@ -35295,29 +13066,22 @@ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "cliui": "7.0.4", + "escalade": "3.1.1", + "get-caller-file": "2.0.5", + "require-directory": "2.1.1", + "string-width": "4.2.2", + "y18n": "5.0.8", + "yargs-parser": "20.2.9" } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true } } }, "karma-babel-preprocessor": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-8.0.2.tgz", - "integrity": "sha512-6ZUnHwaK2EyhgxbgeSJW6n6WZUYSEdekHIV/qDUnPgMkVzQBHEvd07d2mTL5AQjV8uTUgH6XslhaPrp+fHWH2A==", - "dev": true, - "requires": {} + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-8.0.1.tgz", + "integrity": "sha512-5upyawNi3c7Gg6tPH1FWRVTmUijGf3v1GV4ScLM/2jKdDP18SlaKlUpu8eJrRI3STO8qK1bkqFcdgAA364nLYQ==", + "dev": true }, "karma-browserstack-launcher": { "version": "1.4.0", @@ -35325,17 +13089,16 @@ "integrity": "sha512-bUQK84U+euDfOUfEjcF4IareySMOBNRLrrl9q6cttIe8f011Ir6olLITTYMOJDcGY58wiFIdhPHSPd9Pi6+NfQ==", "dev": true, "requires": { - "browserstack": "~1.5.1", - "browserstacktunnel-wrapper": "~2.0.2", - "q": "~1.5.0" + "browserstack": "1.5.3", + "browserstacktunnel-wrapper": "2.0.4", + "q": "1.5.1" } }, "karma-chai": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", - "dev": true, - "requires": {} + "dev": true }, "karma-chrome-launcher": { "version": "3.1.0", @@ -35343,7 +13106,7 @@ "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", "dev": true, "requires": { - "which": "^1.2.1" + "which": "1.3.1" }, "dependencies": { "which": { @@ -35352,38 +13115,23 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } } } }, "karma-coverage": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.0.tgz", - "integrity": "sha512-gPVdoZBNDZ08UCzdMHHhEImKrw1+PAOQOIiffv1YsvxFhBjqvo/SVXNk4tqn1SYqX0BJZT6S/59zgxiBe+9OuA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.0.3.tgz", + "integrity": "sha512-atDvLQqvPcLxhED0cmXYdsPMCQuh6Asa9FMZW1bhNqlVEhJoB9qyZ2BY1gu7D/rr5GLGb5QzYO4siQskxaWP/g==", "dev": true, "requires": { - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.0.5", - "minimatch": "^3.0.4" - }, - "dependencies": { - "istanbul-lib-instrument": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", - "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - } - } + "istanbul-lib-coverage": "3.0.0", + "istanbul-lib-instrument": "4.0.3", + "istanbul-lib-report": "3.0.0", + "istanbul-lib-source-maps": "4.0.0", + "istanbul-reports": "3.0.2", + "minimatch": "3.0.4" } }, "karma-coverage-istanbul-reporter": { @@ -35392,24 +13140,33 @@ "integrity": "sha512-wE4VFhG/QZv2Y4CdAYWDbMmcAHeS926ZIji4z+FkB2aF/EposRb6DP6G5ncT/wXhqUfAb/d7kZrNKPonbvsATw==", "dev": true, "requires": { - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^3.0.6", - "istanbul-reports": "^3.0.2", - "minimatch": "^3.0.4" + "istanbul-lib-coverage": "3.0.0", + "istanbul-lib-report": "3.0.0", + "istanbul-lib-source-maps": "3.0.6", + "istanbul-reports": "3.0.2", + "minimatch": "3.0.4" }, "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, "istanbul-lib-source-maps": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", "dev": true, "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" + "debug": "4.3.1", + "istanbul-lib-coverage": "2.0.5", + "make-dir": "2.1.0", + "rimraf": "2.7.1", + "source-map": "0.6.1" }, "dependencies": { "istanbul-lib-coverage": { @@ -35426,10 +13183,16 @@ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "pify": "4.0.1", + "semver": "5.7.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 + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -35442,7 +13205,7 @@ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { - "glob": "^7.1.3" + "glob": "7.1.7" } }, "semver": { @@ -35465,17 +13228,17 @@ "integrity": "sha1-zdADM8znfC5M4D46yT8vjs0fuVI=", "dev": true, "requires": { - "es5-shim": "^4.0.5" + "es5-shim": "4.5.15" } }, "karma-firefox-launcher": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.2.tgz", - "integrity": "sha512-VV9xDQU1QIboTrjtGVD4NCfzIH7n01ZXqy/qpBhnOeGVOkG5JYPEm8kuSd7psHE6WouZaQ9Ool92g8LFweSNMA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.1.tgz", + "integrity": "sha512-VzDMgPseXak9DtfyE1O5bB2BwsMy1zzO1kUxVW1rP0yhC4tDNJ0p3JoFdzvrK4QqVzdqUMa9Rx9YzkdFp8hz3Q==", "dev": true, "requires": { - "is-wsl": "^2.2.0", - "which": "^2.0.1" + "is-wsl": "2.2.0", + "which": "2.0.2" } }, "karma-ie-launcher": { @@ -35484,7 +13247,7 @@ "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", "dev": true, "requires": { - "lodash": "^4.6.1" + "lodash": "4.17.21" } }, "karma-mocha": { @@ -35493,7 +13256,7 @@ "integrity": "sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ==", "dev": true, "requires": { - "minimist": "^1.2.3" + "minimist": "1.2.5" } }, "karma-mocha-reporter": { @@ -35502,9 +13265,9 @@ "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", "dev": true, "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "strip-ansi": "^4.0.0" + "chalk": "2.4.2", + "log-symbols": "2.2.0", + "strip-ansi": "4.0.0" }, "dependencies": { "ansi-regex": { @@ -35513,13 +13276,22 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "2.4.2" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -35528,29 +13300,25 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/karma-opera-launcher/-/karma-opera-launcher-1.0.0.tgz", "integrity": "sha1-+lFihTGh0L6EstjcDX7iCfyP+Ro=", - "dev": true, - "requires": {} + "dev": true }, "karma-safari-launcher": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/karma-safari-launcher/-/karma-safari-launcher-1.0.0.tgz", "integrity": "sha1-lpgqLMR9BmquccVTursoMZEVos4=", - "dev": true, - "requires": {} + "dev": true }, "karma-script-launcher": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/karma-script-launcher/-/karma-script-launcher-1.0.0.tgz", "integrity": "sha1-zQF8TeXvCeWp2nkydhdhCN1LVC0=", - "dev": true, - "requires": {} + "dev": true }, "karma-sinon": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/karma-sinon/-/karma-sinon-1.0.5.tgz", "integrity": "sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo=", - "dev": true, - "requires": {} + "dev": true }, "karma-sourcemap-loader": { "version": "0.3.8", @@ -35558,7 +13326,7 @@ "integrity": "sha512-zorxyAakYZuBcHRJE+vbrK2o2JXLFWK8VVjiT/6P+ltLBUGUvqTEkUiQ119MGdOrK7mrmxXHZF1/pfT6GgIZ6g==", "dev": true, "requires": { - "graceful-fs": "^4.1.2" + "graceful-fs": "4.2.6" } }, "karma-spec-reporter": { @@ -35567,33 +13335,67 @@ "integrity": "sha1-LpxyB+pyZ3EmAln4K+y1QyCeRAo=", "dev": true, "requires": { - "colors": "^1.1.2" + "colors": "1.4.0" } }, "karma-webpack": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-5.0.0.tgz", - "integrity": "sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.5.tgz", + "integrity": "sha512-nRudGJWstvVuA6Tbju9tyGUfXTtI1UXMXoRHVmM2/78D0q6s/Ye2IC157PKNDC15PWFGR0mVIRtWLAdcfsRJoA==", "dev": true, "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "webpack-merge": "^4.1.5" + "async": "2.6.3", + "babel-runtime": "6.26.0", + "loader-utils": "1.4.0", + "lodash": "4.17.21", + "source-map": "0.5.7", + "webpack-dev-middleware": "2.0.6" + }, + "dependencies": { + "async": { + "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.21" + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "1.2.5" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "5.2.2", + "emojis-list": "3.0.0", + "json5": "1.0.1" + } + } } }, "keyv": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.1.tgz", - "integrity": "sha512-tGv1yP6snQVDSM4X6yxrv2zzq/EvpW+oYiUz6aueW1u9CtS8RzUQYxxmFwgZlO2jSgCxQbchhxaqXXp2hnKGpQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", "dev": true, "requires": { "json-buffer": "3.0.1" } }, "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, "konan": { @@ -35602,33 +13404,59 @@ "integrity": "sha512-7ZhYV84UzJ0PR/RJnnsMZcAbn+kLasJhVNWsu8ZyVEJYRpGA5XESQ9d/7zOa08U0Ou4cmB++hMNY/3OSV9KIbg==", "dev": true, "requires": { - "@babel/parser": "^7.10.5", - "@babel/traverse": "^7.10.5" + "@babel/parser": "7.14.7", + "@babel/traverse": "7.14.7" } }, - "ky": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/ky/-/ky-0.29.0.tgz", - "integrity": "sha512-01TBSOqlHmLfcQhHseugGHLxPtU03OyZWaLDWt5MfzCkijG6xWFvAQPhKVn0cR2MMjYvBP9keQ8A3+rQEhLO5g==", - "dev": true - }, "last-run": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", "dev": true, "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" + "default-resolution": "2.0.0", + "es6-weak-map": "2.0.3" } }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, "lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "dev": true, "requires": { - "readable-stream": "^2.0.5" + "readable-stream": "2.3.7" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } } }, "lcid": { @@ -35637,7 +13465,7 @@ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "1.0.0" } }, "lcov-parse": { @@ -35652,7 +13480,7 @@ "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", "dev": true, "requires": { - "flush-write-stream": "^1.0.2" + "flush-write-stream": "1.1.1" } }, "levn": { @@ -35661,8 +13489,8 @@ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "prelude-ls": "1.2.1", + "type-check": "0.4.0" } }, "liftoff": { @@ -35671,58 +13499,30 @@ "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", "dev": true, "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } + "extend": "3.0.2", + "findup-sync": "3.0.0", + "fined": "1.2.0", + "flagged-respawn": "1.0.1", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", + "rechoir": "0.6.2", + "resolve": "1.20.0" } }, "lighthouse-logger": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.3.0.tgz", - "integrity": "sha512-BbqAKApLb9ywUli+0a+PcV04SyJ/N1q/8qgCNe6U97KbPCS1BTksEuHFLYdvc8DltuhfxIUBqDZsC0bBGtl3lA==", + "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.9", - "marky": "^1.2.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "debug": "2.6.9", + "marky": "1.2.2" } }, "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "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 }, "listenercount": { @@ -35732,9 +13532,9 @@ "dev": true }, "live-connect-js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-2.3.1.tgz", - "integrity": "sha512-4IT8NEOOTNmoYpw5CTxdugSF2w9xqfOujrEqx6zLPdTT3xq/lLdxxvRTREDi+qYHDsCDovdiNO3uOSoemdTCdA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-2.0.0.tgz", + "integrity": "sha512-Xhrj1JU5LoLjJuujjTlvDfc/n3Shzk2hPlYmLdCx/lsltFFVuCFa9uM8u5mcHlmOUKP5pu9I54bAITxZBMHoXg==", "requires": { "tiny-hashes": "1.0.1" } @@ -35746,50 +13546,42 @@ "dev": true }, "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } + "graceful-fs": "4.2.6", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" } }, "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", "dev": true }, "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", "dev": true, "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "big.js": "5.2.2", + "emojis-list": "3.0.0", + "json5": "2.2.0" } }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "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": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "4.1.0" } }, "lodash": { @@ -35822,7 +13614,7 @@ "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", "dev": true, "requires": { - "lodash._htmlescapes": "~2.4.1" + "lodash._htmlescapes": "2.4.1" } }, "lodash._escapestringchar": { @@ -35874,9 +13666,9 @@ "dev": true }, "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", "dev": true }, "lodash._reunescapedhtml": { @@ -35885,8 +13677,8 @@ "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", "dev": true, "requires": { - "lodash._htmlescapes": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._htmlescapes": "2.4.1", + "lodash.keys": "2.4.1" } }, "lodash._root": { @@ -35901,9 +13693,16 @@ "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1" + "lodash._objecttypes": "2.4.1" } }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true, + "optional": true + }, "lodash.clone": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", @@ -35940,9 +13739,9 @@ "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", "dev": true, "requires": { - "lodash._escapehtmlchar": "~2.4.1", - "lodash._reunescapedhtml": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._escapehtmlchar": "2.4.1", + "lodash._reunescapedhtml": "2.4.1", + "lodash.keys": "2.4.1" } }, "lodash.flatten": { @@ -35999,9 +13798,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" }, "dependencies": { "lodash.isobject": { @@ -36010,7 +13809,7 @@ "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1" + "lodash._objecttypes": "2.4.1" } } } @@ -36040,22 +13839,40 @@ "dev": true }, "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" + "lodash._escapestringchar": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.defaults": "2.4.1", + "lodash.escape": "2.4.1", + "lodash.keys": "2.4.1", + "lodash.templatesettings": "2.4.1", + "lodash.values": "2.4.1" + }, + "dependencies": { + "lodash.defaults": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1", + "lodash.keys": "2.4.1" + } + } } }, "lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0" + "lodash._reinterpolate": "2.4.1", + "lodash.escape": "2.4.1" } }, "lodash.truncate": { @@ -36076,7 +13893,7 @@ "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", "dev": true, "requires": { - "lodash.keys": "~2.4.1" + "lodash.keys": "2.4.1" } }, "lodash.zip": { @@ -36092,31 +13909,106 @@ "dev": true }, "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^2.0.1" + "chalk": "4.1.1", + "is-unicode-supported": "0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } + } } }, "log4js": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.2.tgz", - "integrity": "sha512-k80cggS2sZQLBwllpT1p06GtfvzMmSdUCkW96f0Hj83rKGJDAu2vZjt9B9ag2vx8Zz1IXzxoLgqvRJCdMKybGg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", + "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", "dev": true, "requires": { - "date-format": "^4.0.4", - "debug": "^4.3.3", - "flatted": "^3.2.5", - "rfdc": "^1.3.0", - "streamroller": "^3.0.4" + "date-format": "3.0.0", + "debug": "4.3.1", + "flatted": "2.0.2", + "rfdc": "1.3.0", + "streamroller": "2.2.4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "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 + } } }, "loglevel": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", - "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", + "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", "dev": true }, "loglevel-plugin-prefix": { @@ -36125,44 +14017,42 @@ "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", "dev": true }, + "loglevelnext": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", + "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", + "dev": true, + "requires": { + "es6-symbol": "3.1.3", + "object.assign": "4.1.2" + } + }, "lolex": { "version": "2.7.5", "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", "dev": true }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, "longest-streak": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==", "dev": true }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", - "dev": true, - "requires": { - "get-func-name": "^2.0.0" + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.3" } }, "lowercase-keys": { @@ -36172,12 +14062,13 @@ "dev": true }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, "requires": { - "yallist": "^4.0.0" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } }, "lru-queue": { @@ -36186,17 +14077,17 @@ "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", "dev": true, "requires": { - "es5-ext": "~0.10.2" + "es5-ext": "0.10.53" } }, "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", "dev": true, "optional": true, "requires": { - "sourcemap-codec": "^1.4.8" + "sourcemap-codec": "1.4.8" } }, "make-dir": { @@ -36205,7 +14096,7 @@ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { - "semver": "^6.0.0" + "semver": "6.3.0" } }, "make-iterator": { @@ -36214,15 +14105,7 @@ "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", "dev": true, "requires": { - "kind-of": "^6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } + "kind-of": "6.0.3" } }, "map-cache": { @@ -36232,15 +14115,15 @@ "dev": true }, "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true }, "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", "dev": true }, "map-visit": { @@ -36249,7 +14132,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "^1.0.0" + "object-visit": "1.0.1" } }, "markdown-table": { @@ -36258,13 +14141,13 @@ "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", "dev": true, "requires": { - "repeat-string": "^1.0.0" + "repeat-string": "1.6.1" } }, "marky": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.4.tgz", - "integrity": "sha512-zd2/GiSn6U3/jeFVZ0J9CA1LzQ8RfIVvXkb/U0swFHF/zT+dVohTAWjmo2DcIuofmIIIROlwTbd+shSeXmxr0w==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.2.tgz", + "integrity": "sha512-k1dB2HNeaNyORco8ulVEhctyEGkKHb2YWAhDsxeFlW2nROIirsctBYzKwwS3Vza+sKTS1zO4Z+n9/+9WbGLIxQ==", "dev": true }, "matchdep": { @@ -36273,22 +14156,74 @@ "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", "dev": true, "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", + "findup-sync": "2.0.0", + "micromatch": "3.1.10", + "resolve": "1.20.0", "stack-trace": "0.0.10" }, "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.4", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "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.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "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.1" + } + } + } + }, "findup-sync": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "dev": true, "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.10", + "resolve-dir": "1.0.1" } }, "is-glob": { @@ -36297,18 +14232,86 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.3", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" } } } }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "3.1.0", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, "mdast-util-definitions": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", "dev": true, "requires": { - "unist-util-visit": "^2.0.0" + "unist-util-visit": "2.0.3" } }, "mdast-util-find-and-replace": { @@ -36317,9 +14320,9 @@ "integrity": "sha512-9cKl33Y21lyckGzpSmEQnIDjEfeeWelN5s1kUW1LwdB0Fkuq2u+4GdqcGEygYxJE8GVqCl0741bYXHgamfWAZA==", "dev": true, "requires": { - "escape-string-regexp": "^4.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" + "escape-string-regexp": "4.0.0", + "unist-util-is": "4.1.0", + "unist-util-visit-parents": "3.1.1" }, "dependencies": { "escape-string-regexp": { @@ -36336,11 +14339,11 @@ "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==", "dev": true, "requires": { - "@types/mdast": "^3.0.0", - "mdast-util-to-string": "^2.0.0", - "micromark": "~2.11.0", - "parse-entities": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" + "@types/mdast": "3.0.3", + "mdast-util-to-string": "2.0.0", + "micromark": "2.11.4", + "parse-entities": "2.0.0", + "unist-util-stringify-position": "2.0.3" }, "dependencies": { "mdast-util-to-string": { @@ -36357,11 +14360,11 @@ "integrity": "sha512-NNkhDx/qYcuOWB7xHUGWZYVXvjPFFd6afg6/e2g+SV4r9q5XUcCbV4Wfa3DLYIiD+xAEZc6K4MGaE/m0KDcPwQ==", "dev": true, "requires": { - "mdast-util-gfm-autolink-literal": "^0.1.0", - "mdast-util-gfm-strikethrough": "^0.2.0", - "mdast-util-gfm-table": "^0.1.0", - "mdast-util-gfm-task-list-item": "^0.1.0", - "mdast-util-to-markdown": "^0.6.1" + "mdast-util-gfm-autolink-literal": "0.1.3", + "mdast-util-gfm-strikethrough": "0.2.3", + "mdast-util-gfm-table": "0.1.6", + "mdast-util-gfm-task-list-item": "0.1.6", + "mdast-util-to-markdown": "0.6.5" } }, "mdast-util-gfm-autolink-literal": { @@ -36370,9 +14373,9 @@ "integrity": "sha512-GjmLjWrXg1wqMIO9+ZsRik/s7PLwTaeCHVB7vRxUwLntZc8mzmTsLVr6HW1yLokcnhfURsn5zmSVdi3/xWWu1A==", "dev": true, "requires": { - "ccount": "^1.0.0", - "mdast-util-find-and-replace": "^1.1.0", - "micromark": "^2.11.3" + "ccount": "1.1.0", + "mdast-util-find-and-replace": "1.1.1", + "micromark": "2.11.4" } }, "mdast-util-gfm-strikethrough": { @@ -36381,7 +14384,7 @@ "integrity": "sha512-5OQLXpt6qdbttcDG/UxYY7Yjj3e8P7X16LzvpX8pIQPYJ/C2Z1qFGMmcw+1PZMUM3Z8wt8NRfYTvCni93mgsgA==", "dev": true, "requires": { - "mdast-util-to-markdown": "^0.6.0" + "mdast-util-to-markdown": "0.6.5" } }, "mdast-util-gfm-table": { @@ -36390,8 +14393,8 @@ "integrity": "sha512-j4yDxQ66AJSBwGkbpFEp9uG/LS1tZV3P33fN1gkyRB2LoRL+RR3f76m0HPHaby6F4Z5xr9Fv1URmATlRRUIpRQ==", "dev": true, "requires": { - "markdown-table": "^2.0.0", - "mdast-util-to-markdown": "~0.6.0" + "markdown-table": "2.0.0", + "mdast-util-to-markdown": "0.6.5" } }, "mdast-util-gfm-task-list-item": { @@ -36400,7 +14403,7 @@ "integrity": "sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A==", "dev": true, "requires": { - "mdast-util-to-markdown": "~0.6.0" + "mdast-util-to-markdown": "0.6.5" } }, "mdast-util-inject": { @@ -36409,7 +14412,7 @@ "integrity": "sha1-2wa4tYW+lZotzS+H9HK6m3VvNnU=", "dev": true, "requires": { - "mdast-util-to-string": "^1.0.0" + "mdast-util-to-string": "1.1.0" } }, "mdast-util-to-hast": { @@ -36418,14 +14421,14 @@ "integrity": "sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ==", "dev": true, "requires": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "mdast-util-definitions": "^4.0.0", - "mdurl": "^1.0.0", - "unist-builder": "^2.0.0", - "unist-util-generated": "^1.0.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^2.0.0" + "@types/mdast": "3.0.3", + "@types/unist": "2.0.3", + "mdast-util-definitions": "4.0.0", + "mdurl": "1.0.1", + "unist-builder": "2.0.3", + "unist-util-generated": "1.1.6", + "unist-util-position": "3.1.0", + "unist-util-visit": "2.0.3" } }, "mdast-util-to-markdown": { @@ -36434,12 +14437,12 @@ "integrity": "sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==", "dev": true, "requires": { - "@types/unist": "^2.0.0", - "longest-streak": "^2.0.0", - "mdast-util-to-string": "^2.0.0", - "parse-entities": "^2.0.0", - "repeat-string": "^1.0.0", - "zwitch": "^1.0.0" + "@types/unist": "2.0.3", + "longest-streak": "2.0.4", + "mdast-util-to-string": "2.0.0", + "parse-entities": "2.0.0", + "repeat-string": "1.6.1", + "zwitch": "1.0.5" }, "dependencies": { "mdast-util-to-string": { @@ -36462,21 +14465,30 @@ "integrity": "sha512-csimbRIVkiqc+PpFeKDGQ/Ck2N4f9FYH3zzBMMJzcxoKL8m+cM0n94xXm0I9eaxHnKdY9n145SGTdyJC7i273g==", "dev": true, "requires": { - "@types/mdast": "^3.0.3", - "@types/unist": "^2.0.3", - "extend": "^3.0.2", - "github-slugger": "^1.2.1", - "mdast-util-to-string": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit": "^2.0.0" + "@types/mdast": "3.0.3", + "@types/unist": "2.0.3", + "extend": "3.0.2", + "github-slugger": "1.3.0", + "mdast-util-to-string": "2.0.0", + "unist-util-is": "4.1.0", + "unist-util-visit": "2.0.3" }, "dependencies": { - "github-slugger": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", - "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==", + "emoji-regex": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", + "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", "dev": true }, + "github-slugger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.3.0.tgz", + "integrity": "sha512-gwJScWVNhFYSRDvURk/8yhcFBee6aFjye2a7Lhb2bUyRulpIoek9p0I9Kt7PT67d/nUlZbFu8L9RLiA0woQN8Q==", + "dev": true, + "requires": { + "emoji-regex": "6.1.1" + } + }, "mdast-util-to-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", @@ -36496,30 +14508,81 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + } + } + }, "memoizee": { "version": "0.4.15", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", "dev": true, "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" + "d": "1.0.1", + "es5-ext": "0.10.53", + "es6-weak-map": "2.0.3", + "event-emitter": "0.3.5", + "is-promise": "2.2.2", + "lru-queue": "0.1.0", + "next-tick": "1.1.0", + "timers-ext": "0.1.7" + }, + "dependencies": { + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + } } }, "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" + "errno": "0.1.8", + "readable-stream": "2.3.7" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } } }, "meow": { @@ -36528,99 +14591,88 @@ "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", + "@types/minimist": "1.2.1", + "camelcase-keys": "6.2.2", + "decamelize-keys": "1.1.0", + "hard-rejection": "2.1.0", "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" + "normalize-package-data": "3.0.2", + "read-pkg-up": "7.0.1", + "redent": "3.0.0", + "trim-newlines": "3.0.1", + "type-fest": "0.18.1", + "yargs-parser": "20.2.9" }, "dependencies": { - "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" - } + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true }, - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "camelcase": "5.3.1", + "map-obj": "4.2.1", + "quick-lru": "4.0.1" } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "lru-cache": "6.0.0" } }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "yallist": "4.0.0" } }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } + "map-obj": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz", + "integrity": "sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==", + "dev": true }, - "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==", + "normalize-package-data": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz", + "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "hosted-git-info": "4.0.2", + "resolve": "1.20.0", + "semver": "7.3.5", + "validate-npm-package-license": "3.0.4" } }, - "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": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "@babel/code-frame": "7.14.5", + "error-ex": "1.3.2", + "json-parse-even-better-errors": "2.3.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==", + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true }, "read-pkg": { @@ -36629,10 +14681,10 @@ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "@types/normalize-package-data": "2.4.0", + "normalize-package-data": "2.5.0", + "parse-json": "5.2.0", + "type-fest": "0.6.0" }, "dependencies": { "hosted-git-info": { @@ -36647,10 +14699,10 @@ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "2.8.9", + "resolve": "1.20.0", + "semver": "5.7.1", + "validate-npm-package-license": "3.0.4" } }, "semver": { @@ -36673,9 +14725,9 @@ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" + "find-up": "4.1.0", + "read-pkg": "5.2.0", + "type-fest": "0.8.1" }, "dependencies": { "type-fest": { @@ -36692,7 +14744,7 @@ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "6.0.0" } }, "type-fest": { @@ -36701,10 +14753,10 @@ "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } @@ -36720,7 +14772,7 @@ "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", "dev": true, "requires": { - "source-map": "^0.6.1" + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -36748,8 +14800,25 @@ "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==", "dev": true, "requires": { - "debug": "^4.0.0", - "parse-entities": "^2.0.0" + "debug": "4.3.1", + "parse-entities": "2.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } } }, "micromark-extension-gfm": { @@ -36758,12 +14827,12 @@ "integrity": "sha512-oVN4zv5/tAIA+l3GbMi7lWeYpJ14oQyJ3uEim20ktYFAcfX1x3LNlFGGlmrZHt7u9YlKExmyJdDGaTt6cMSR/A==", "dev": true, "requires": { - "micromark": "~2.11.0", - "micromark-extension-gfm-autolink-literal": "~0.5.0", - "micromark-extension-gfm-strikethrough": "~0.6.5", - "micromark-extension-gfm-table": "~0.4.0", - "micromark-extension-gfm-tagfilter": "~0.3.0", - "micromark-extension-gfm-task-list-item": "~0.3.0" + "micromark": "2.11.4", + "micromark-extension-gfm-autolink-literal": "0.5.7", + "micromark-extension-gfm-strikethrough": "0.6.5", + "micromark-extension-gfm-table": "0.4.3", + "micromark-extension-gfm-tagfilter": "0.3.0", + "micromark-extension-gfm-task-list-item": "0.3.3" } }, "micromark-extension-gfm-autolink-literal": { @@ -36772,7 +14841,7 @@ "integrity": "sha512-ePiDGH0/lhcngCe8FtH4ARFoxKTUelMp4L7Gg2pujYD5CSMb9PbblnyL+AAMud/SNMyusbS2XDSiPIRcQoNFAw==", "dev": true, "requires": { - "micromark": "~2.11.3" + "micromark": "2.11.4" } }, "micromark-extension-gfm-strikethrough": { @@ -36781,7 +14850,7 @@ "integrity": "sha512-PpOKlgokpQRwUesRwWEp+fHjGGkZEejj83k9gU5iXCbDG+XBA92BqnRKYJdfqfkrRcZRgGuPuXb7DaK/DmxOhw==", "dev": true, "requires": { - "micromark": "~2.11.0" + "micromark": "2.11.4" } }, "micromark-extension-gfm-table": { @@ -36790,7 +14859,7 @@ "integrity": "sha512-hVGvESPq0fk6ALWtomcwmgLvH8ZSVpcPjzi0AjPclB9FsVRgMtGZkUcpE0zgjOCFAznKepF4z3hX8z6e3HODdA==", "dev": true, "requires": { - "micromark": "~2.11.0" + "micromark": "2.11.4" } }, "micromark-extension-gfm-tagfilter": { @@ -36805,123 +14874,53 @@ "integrity": "sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ==", "dev": true, "requires": { - "micromark": "~2.11.0" + "micromark": "2.11.4" } }, "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "3.0.2", + "picomatch": "2.3.0" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.12.0", + "brorand": "1.1.0" }, "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "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" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "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" - } - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } } } }, "mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" }, "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", "requires": { - "mime-db": "1.51.0" + "mime-db": "1.48.0" } }, "mimic-fn": { @@ -36942,19 +14941,31 @@ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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.7" + "brace-expansion": "1.1.11" } }, "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "minimist-options": { @@ -36963,15 +14974,15 @@ "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" + "arrify": "1.0.1", + "is-plain-obj": "1.1.0", + "kind-of": "6.0.3" }, "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true } } @@ -36982,8 +14993,19 @@ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } } }, "mkdirp": { @@ -37017,6 +15039,12 @@ "supports-color": "5.4.0" }, "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -37038,29 +15066,20 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "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" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, - "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.7" - } - }, "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", @@ -37076,19 +15095,13 @@ "minimist": "0.0.8" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "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==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -37105,22 +15118,22 @@ "integrity": "sha512-eiyIZj/A0dj1o4ywXWqicazUL3l0HP3TydUR6xF0X3xh3LGBMLqW8a9aFe6MuNH4mxNMk53QKBHM6LOPR8kSgw==", "dev": true, "requires": { - "browser-resolve": "^1.7.0", - "cached-path-relative": "^1.0.0", - "concat-stream": "~1.5.0", - "defined": "^1.0.0", - "detective": "^5.2.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "JSONStream": "^1.0.3", - "konan": "^2.1.1", - "readable-stream": "^2.0.2", - "resolve": "^1.1.3", - "standard-version": "^9.0.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" + "JSONStream": "1.3.5", + "browser-resolve": "1.11.3", + "cached-path-relative": "1.0.2", + "concat-stream": "1.5.2", + "defined": "1.0.0", + "detective": "5.2.0", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "konan": "2.1.1", + "readable-stream": "2.3.7", + "resolve": "1.20.0", + "standard-version": "9.3.0", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.5", + "xtend": "4.0.2" }, "dependencies": { "concat-stream": { @@ -37129,9 +15142,9 @@ "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, "requires": { - "inherits": "~2.0.1", - "readable-stream": "~2.0.0", - "typedarray": "~0.0.5" + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" }, "dependencies": { "readable-stream": { @@ -37140,28 +15153,54 @@ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" + "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" } } } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "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.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -37174,8 +15213,8 @@ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "readable-stream": "2.3.7", + "xtend": "4.0.2" } } } @@ -37186,47 +15225,25 @@ "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", "dev": true, "requires": { - "basic-auth": "~2.0.1", + "basic-auth": "2.0.1", "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" + "depd": "2.0.0", + "on-finished": "2.3.0", + "on-headers": "1.0.2" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, - "mrmime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", - "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==", - "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 + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "multipipe": { "version": "0.1.2", @@ -37243,7 +15260,7 @@ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "~1.1.9" + "readable-stream": "1.1.14" } }, "isarray": { @@ -37258,10 +15275,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "string_decoder": { @@ -37285,18 +15302,17 @@ "dev": true }, "nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", "dev": true, "optional": true }, "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "dev": true, - "optional": true + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "dev": true }, "nanomatch": { "version": "1.2.13", @@ -37304,25 +15320,17 @@ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.3", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "natural-compare": { @@ -37338,9 +15346,9 @@ "dev": true }, "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, "neo-async": { "version": "2.6.2", @@ -37349,9 +15357,9 @@ "dev": true }, "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, "nice-try": { @@ -37366,11 +15374,11 @@ "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", "dev": true, "requires": { - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^5.0.1", - "path-to-regexp": "^1.7.0" + "@sinonjs/formatio": "3.2.2", + "@sinonjs/text-encoding": "0.7.1", + "just-extend": "4.2.1", + "lolex": "5.1.2", + "path-to-regexp": "1.8.0" }, "dependencies": { "@sinonjs/formatio": { @@ -37379,8 +15387,8 @@ "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", "dev": true, "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" + "@sinonjs/commons": "1.8.3", + "@sinonjs/samsam": "3.3.3" } }, "isarray": { @@ -37395,7 +15403,7 @@ "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", "dev": true, "requires": { - "@sinonjs/commons": "^1.7.0" + "@sinonjs/commons": "1.8.3" } }, "path-to-regexp": { @@ -37410,18 +15418,91 @@ } }, "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "1.5.0", + "browserify-zlib": "0.2.0", + "buffer": "4.9.2", + "console-browserify": "1.2.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.2.0", + "events": "3.3.0", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.1", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.7", + "stream-browserify": "2.0.2", + "stream-http": "2.8.3", + "string_decoder": "1.3.0", + "timers-browserify": "2.0.12", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.11.1", + "vm-browserify": "1.1.2" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "1.5.1", + "ieee754": "1.2.1", + "isarray": "1.0.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + }, + "dependencies": { + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + } } }, "node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "version": "1.1.73", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", + "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", "dev": true }, "nopt": { @@ -37430,7 +15511,7 @@ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1" + "abbrev": "1.0.9" } }, "normalize-package-data": { @@ -37439,10 +15520,10 @@ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "2.8.9", + "resolve": "1.20.0", + "semver": "5.7.1", + "validate-npm-package-license": "3.0.4" }, "dependencies": { "semver": { @@ -37471,7 +15552,7 @@ "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", "dev": true, "requires": { - "once": "^1.3.2" + "once": "1.4.0" } }, "npm-run-path": { @@ -37480,7 +15561,7 @@ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "^2.0.0" + "path-key": "2.0.1" }, "dependencies": { "path-key": { @@ -37521,9 +15602,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { "define-property": { @@ -37532,50 +15613,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "is-descriptor": "0.1.6" } }, "kind-of": { @@ -37584,15 +15622,15 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } }, "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", "dev": true }, "object-is": { @@ -37601,8 +15639,8 @@ "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "call-bind": "1.0.2", + "define-properties": "1.1.3" } }, "object-keys": { @@ -37617,7 +15655,7 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "^3.0.0" + "isobject": "3.0.1" } }, "object.assign": { @@ -37626,10 +15664,10 @@ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" + "call-bind": "1.0.2", + "define-properties": "1.1.3", + "has-symbols": "1.0.2", + "object-keys": "1.1.1" } }, "object.defaults": { @@ -37638,10 +15676,10 @@ "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" } }, "object.map": { @@ -37650,8 +15688,29 @@ "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "for-own": "1.0.0", + "make-iterator": "1.0.1" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + } } }, "object.pick": { @@ -37660,7 +15719,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "object.reduce": { @@ -37669,19 +15728,19 @@ "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", "dev": true, "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "for-own": "1.0.0", + "make-iterator": "1.0.1" } }, "object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", + "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "1.0.2", + "define-properties": "1.1.3", + "es-abstract": "1.18.3" } }, "on-finished": { @@ -37704,7 +15763,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "onetime": { @@ -37713,7 +15772,7 @@ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { - "mimic-fn": "^2.1.0" + "mimic-fn": "2.1.0" } }, "opener": { @@ -37728,7 +15787,7 @@ "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", "dev": true, "requires": { - "is-wsl": "^1.1.0" + "is-wsl": "1.1.0" }, "dependencies": { "is-wsl": { @@ -37739,18 +15798,42 @@ } } }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.4.1", + "prelude-ls": "1.2.1", + "type-check": "0.4.0", + "word-wrap": "1.2.3" } }, "ora": { @@ -37759,15 +15842,15 @@ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "bl": "4.1.0", + "chalk": "4.1.1", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.0", + "is-interactive": "1.0.0", + "is-unicode-supported": "0.1.0", + "log-symbols": "4.1.0", + "strip-ansi": "6.0.0", + "wcwidth": "1.0.1" }, "dependencies": { "ansi-styles": { @@ -37776,17 +15859,17 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" } }, "color-convert": { @@ -37795,7 +15878,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -37804,15 +15887,11 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "supports-color": { "version": "7.2.0", @@ -37820,7 +15899,7 @@ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "4.0.0" } } } @@ -37831,13 +15910,39 @@ "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", "dev": true, "requires": { - "readable-stream": "^2.0.1" + "readable-stream": "2.3.7" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, "os-locale": { @@ -37846,7 +15951,7 @@ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "lcid": "^1.0.0" + "lcid": "1.0.0" } }, "os-tmpdir": { @@ -37867,34 +15972,34 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, - "p-iteration": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/p-iteration/-/p-iteration-1.1.8.tgz", - "integrity": "sha512-IMFBSDIYcPNnW7uWYGrBqmvTiq7W0uB0fJn6shQZs7dlF3OvrHOre+JT9ikSZ7gZS3vWqclVgoQSvToJrns7uQ==", - "dev": true - }, "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { - "p-try": "^1.0.0" + "p-try": "2.2.0" } }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "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": "^1.1.0" + "p-limit": "2.3.0" } }, "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "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 + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, "parent-module": { @@ -37903,7 +16008,20 @@ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "requires": { - "callsites": "^3.0.0" + "callsites": "3.1.0" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "5.4.1", + "browserify-aes": "1.2.0", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.1.2", + "safe-buffer": "5.1.2" } }, "parse-entities": { @@ -37912,12 +16030,12 @@ "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", "dev": true, "requires": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" + "character-entities": "1.2.4", + "character-entities-legacy": "1.1.4", + "character-reference-invalid": "1.1.4", + "is-alphanumerical": "1.0.4", + "is-decimal": "1.0.4", + "is-hexadecimal": "1.0.4" } }, "parse-filepath": { @@ -37926,19 +16044,53 @@ "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-github-repo-url": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", + "integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } } }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "error-ex": "1.3.2" } }, "parse-ms": { @@ -37965,22 +16117,41 @@ "integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==", "dev": true, "requires": { - "is-ssh": "^1.3.0", - "protocols": "^1.4.0", - "qs": "^6.9.4", - "query-string": "^6.13.8" + "is-ssh": "1.3.3", + "protocols": "1.4.8", + "qs": "6.10.1", + "query-string": "6.14.1" + }, + "dependencies": { + "qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "requires": { + "side-channel": "1.0.4" + } + } } }, "parse-url": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz", - "integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.5.tgz", + "integrity": "sha512-AwfVhXaQrNNI6UPUJq/GJN2qoY0L9gPgxhh9VbDP0bfBAJWaC/Zh8hjQ58YKTi4AagOT70fpadkYSKPo+eFb1w==", "dev": true, "requires": { - "is-ssh": "^1.3.0", - "normalize-url": "^6.1.0", - "parse-path": "^4.0.0", - "protocols": "^1.4.0" + "is-ssh": "1.3.3", + "normalize-url": "4.5.0", + "parse-path": "4.0.3", + "protocols": "1.4.8" + }, + "dependencies": { + "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 + } } }, "parseurl": { @@ -37994,6 +16165,12 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", @@ -38001,9 +16178,9 @@ "dev": true }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "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 }, "path-is-absolute": { @@ -38025,7 +16202,7 @@ "dev": true }, "path-parse": { - "version": "1.0.7", + "version": ">=1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true @@ -38036,7 +16213,7 @@ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { - "path-root-regex": "^0.1.0" + "path-root-regex": "0.1.2" } }, "path-root-regex": { @@ -38051,20 +16228,14 @@ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } + "graceful-fs": "4.2.6", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" } }, "pathval": { @@ -38079,9 +16250,28 @@ "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { - "through": "~2.3" + "through": "2.3.8" + } + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "requires": { + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" } }, + "pbkdf2-compat": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", + "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", + "dev": true + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -38094,22 +16284,16 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, "pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "pinkie": { @@ -38124,7 +16308,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "^2.0.0" + "pinkie": "2.0.4" } }, "pkg-dir": { @@ -38133,56 +16317,65 @@ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "requires": { - "find-up": "^4.0.0" + "find-up": "4.1.0" + } + }, + "pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "dev": true, + "requires": { + "find-up": "2.1.0" }, "dependencies": { "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "locate-path": "2.0.0" } }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "2.0.0", + "path-exists": "3.0.0" } }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "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": "^2.0.0" + "p-try": "1.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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "1.3.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==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "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==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true } } @@ -38193,10 +16386,10 @@ "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", "dev": true, "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" + "ansi-colors": "1.1.0", + "arr-diff": "4.0.0", + "arr-union": "3.1.0", + "extend-shallow": "3.0.2" }, "dependencies": { "ansi-colors": { @@ -38205,7 +16398,7 @@ "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "dev": true, "requires": { - "ansi-wrap": "^0.1.0" + "ansi-wrap": "0.1.0" } } } @@ -38223,32 +16416,112 @@ "dev": true }, "postcss": { - "version": "8.4.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.8.tgz", - "integrity": "sha512-2tXEqGxrjvAO6U+CJzDL2Fk2kPHTv1jQsYkSoMeOis2SsYaXRO2COxTdQp99cYvif9JTXaAk9lYGc3VhJt7JPQ==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.5.tgz", + "integrity": "sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==", + "dev": true, + "optional": true, + "requires": { + "colorette": "1.2.2", + "nanoid": "3.1.23", + "source-map-js": "0.6.2" + } + }, + "postcss-modules": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.1.3.tgz", + "integrity": "sha512-dBT39hrXe4OAVYJe/2ZuIZ9BzYhOe7t+IhedYeQ2OxKwDpAGlkEN/fR0fGnrbx4BvgbMReRX4hCubYK9cE/pJQ==", + "dev": true, + "optional": true, + "requires": { + "generic-names": "2.0.1", + "icss-replace-symbols": "1.1.0", + "lodash.camelcase": "4.3.0", + "postcss-modules-extract-imports": "3.0.0", + "postcss-modules-local-by-default": "4.0.0", + "postcss-modules-scope": "3.0.0", + "postcss-modules-values": "4.0.0", + "string-hash": "1.1.3" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "optional": true + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", "dev": true, "optional": true, "requires": { - "nanoid": "^3.3.1", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "icss-utils": "5.1.0", + "postcss-selector-parser": "6.0.6", + "postcss-value-parser": "4.1.0" } }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "optional": true, + "requires": { + "postcss-selector-parser": "6.0.6" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "optional": true, + "requires": { + "icss-utils": "5.1.0" + } + }, + "postcss-selector-parser": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", + "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", + "dev": true, + "requires": { + "cssesc": "3.0.0", + "util-deprecate": "1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true, + "optional": true + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, "pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", + "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", "dev": true, "requires": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "@jest/types": "27.0.2", + "ansi-regex": "5.0.0", + "ansi-styles": "5.2.0", + "react-is": "17.0.2" }, "dependencies": { "ansi-styles": { @@ -38271,19 +16544,19 @@ "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", "dev": true, "requires": { - "parse-ms": "^2.1.0" + "parse-ms": "2.1.0" } }, "printj": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", - "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", "dev": true }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", "dev": true }, "process-nextick-args": { @@ -38304,7 +16577,7 @@ "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", "dev": true, "requires": { - "xtend": "^4.0.0" + "xtend": "4.0.2" } }, "protocols": { @@ -38340,7 +16613,7 @@ "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", "dev": true, "requires": { - "event-stream": "=3.3.4" + "event-stream": "3.3.4" } }, "pseudomap": { @@ -38355,14 +16628,36 @@ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "4.12.0", + "browserify-rsa": "4.1.0", + "create-hash": "1.2.0", + "parse-asn1": "5.1.6", + "randombytes": "2.1.0", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.4", + "once": "1.4.0" } }, "pumpify": { @@ -38371,31 +16666,19 @@ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" + "duplexify": "3.7.1", + "inherits": "2.0.3", + "pump": "2.0.1" }, "dependencies": { - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, "pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.4", + "once": "1.4.0" } } } @@ -38407,23 +16690,23 @@ "dev": true }, "puppeteer-core": { - "version": "13.5.1", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.5.1.tgz", - "integrity": "sha512-dobVqWjV34ilyfQHR3BBnCYaekBYTi5MgegEYBRYd3s3uFy8jUpZEEWbaFjG9ETm+LGzR5Lmr0aF6LLuHtiuCg==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-9.1.1.tgz", + "integrity": "sha512-zbedbitVIGhmgz0nt7eIdLsnaoVZSlNJfBivqm2w67T8LR2bU1dvnruDZ8nQO0zn++Iet7zHbAOdnuS5+H2E7A==", "dev": true, "requires": { - "cross-fetch": "3.1.5", - "debug": "4.3.3", - "devtools-protocol": "0.0.969999", + "debug": "4.3.1", + "devtools-protocol": "0.0.869402", "extract-zip": "2.0.1", "https-proxy-agent": "5.0.0", + "node-fetch": "2.6.1", "pkg-dir": "4.2.0", "progress": "2.0.3", "proxy-from-env": "1.1.0", "rimraf": "3.0.2", "tar-fs": "2.1.1", "unbzip2-stream": "1.4.3", - "ws": "8.5.0" + "ws": "7.5.0" }, "dependencies": { "agent-base": { @@ -38432,13 +16715,22 @@ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "requires": { - "debug": "4" + "debug": "4.3.1" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" } }, "devtools-protocol": { - "version": "0.0.969999", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.969999.tgz", - "integrity": "sha512-6GfzuDWU0OFAuOvBokXpXPLxjOJ5DZ157Ue3sGQQM3LgAamb8m0R0ruSfN0DDu+XG5XJgT50i6zZ/0o8RglreQ==", + "version": "0.0.869402", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.869402.tgz", + "integrity": "sha512-VvlVYY+VDJe639yHs5PHISzdWTLL3Aw8rO4cvUtwvoxFd6FHbE4OpHHcde52M6096uYYazAmd4l0o5VuFRO2WA==", "dev": true }, "https-proxy-agent": { @@ -38447,16 +16739,24 @@ "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "dev": true, "requires": { - "agent-base": "6", - "debug": "4" + "agent-base": "6.0.2", + "debug": "4.3.1" } }, - "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "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 + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, - "requires": {} + "requires": { + "glob": "7.1.7" + } } } }, @@ -38473,9 +16773,9 @@ "dev": true }, "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, "query-selector-shadow-dom": { "version": "1.0.0", @@ -38489,10 +16789,10 @@ "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", "dev": true, "requires": { - "decode-uri-component": "^0.2.0", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" + "decode-uri-component": "0.2.0", + "filter-obj": "1.1.0", + "split-on-first": "1.1.0", + "strict-uri-encode": "2.0.0" } }, "querystring": { @@ -38501,3388 +16801,5173 @@ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.3", + "math-random": "1.0.4" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "2.1.0", + "safe-buffer": "5.1.2" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.5.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "string_decoder": "1.3.0", + "util-deprecate": "1.0.2" + } + }, + "readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "dev": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "2.3.0" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.20.0" + } + }, + "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": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "requires": { + "indent-string": "4.0.0", + "strip-indent": "3.0.0" + }, + "dependencies": { + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + } + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "requires": { + "@babel/runtime": "7.14.6" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, + "requires": { + "call-bind": "1.0.2", + "define-properties": "1.1.3" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "dev": true, + "requires": { + "regenerate": "1.4.2", + "regenerate-unicode-properties": "8.2.0", + "regjsgen": "0.5.2", + "regjsparser": "0.6.9", + "unicode-match-property-ecmascript": "1.0.4", + "unicode-match-property-value-ecmascript": "1.2.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "regjsparser": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", + "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remark": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/remark/-/remark-13.0.0.tgz", + "integrity": "sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA==", + "dev": true, + "requires": { + "remark-parse": "9.0.0", + "remark-stringify": "9.0.1", + "unified": "9.2.1" + } + }, + "remark-gfm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-1.0.0.tgz", + "integrity": "sha512-KfexHJCiqvrdBZVbQ6RopMZGwaXz6wFJEfByIuEwGf0arvITHjiKKZ1dpXujjH9KZdm1//XJQwgfnJ3lmXaDPA==", + "dev": true, + "requires": { + "mdast-util-gfm": "0.1.2", + "micromark-extension-gfm": "0.3.3" + } + }, + "remark-html": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-13.0.1.tgz", + "integrity": "sha512-K5KQCXWVz+harnyC+UVM/J9eJWCgjYRqFeZoZf2NgP0iFbuuw/RgMZv3MA34b/OEpGnstl3oiOUtZzD3tJ+CBw==", + "dev": true, + "requires": { + "hast-util-sanitize": "3.0.2", + "hast-util-to-html": "7.1.3", + "mdast-util-to-hast": "10.2.0" + } }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "remark-parse": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz", + "integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==", "dev": true, "requires": { - "safe-buffer": "^5.1.0" + "mdast-util-from-markdown": "0.8.5" } }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "remark-reference-links": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-5.0.0.tgz", + "integrity": "sha512-oSIo6lfDyG/1yYl2jPZNXmD9dgyPxp07mSd7snJagVMsDU6NRlD8i54MwHWUgMoOHTs8lIKPkwaUok/tbr5syQ==", + "dev": true, + "requires": { + "unist-util-visit": "2.0.3" + } }, - "raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "remark-stringify": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.1.tgz", + "integrity": "sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==", + "dev": true, "requires": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "mdast-util-to-markdown": "0.6.5" } }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true + "remark-toc": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-7.2.0.tgz", + "integrity": "sha512-ppHepvpbg7j5kPFmU5rzDC4k2GTcPDvWcxXyr/7BZzO1cBSPk0stKtEJdsgAyw2WHKPGxadcHIZRjb2/sHxjkg==", + "dev": true, + "requires": { + "@types/unist": "2.0.3", + "mdast-util-toc": "5.1.0" + } }, - "read-pkg": { + "remove-bom-buffer": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", "dev": true, "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "is-buffer": "1.1.6", + "is-utf8": "0.2.1" } }, - "read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", "dev": true, "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" + "remove-bom-buffer": "3.0.0", + "safe-buffer": "5.1.2", + "through2": "2.0.5" }, "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "p-try": "^2.0.0" + "safe-buffer": "5.1.2" } }, - "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==", + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "readable-stream": "2.3.7", + "xtend": "4.0.2" } - }, - "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 } } }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true }, - "readdir-glob": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", - "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "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": { - "picomatch": "^2.2.1" + "is-finite": "1.1.0" } }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", "dev": true, "requires": { - "resolve": "^1.1.6" + "homedir-polyfill": "1.0.3", + "is-absolute": "1.0.0", + "remove-trailing-separator": "1.1.0" } }, - "recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "replacestream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", + "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", "dev": true, "requires": { - "minimatch": "3.0.4" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1", + "readable-stream": "2.3.7" }, "dependencies": { - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" } } } }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "dev": true, "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" + "aws-sign2": "0.7.0", + "aws4": "1.11.0", + "caseless": "0.12.0", + "combined-stream": "1.0.8", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.3", + "har-validator": "5.1.5", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.31", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.5.0", + "tunnel-agent": "0.6.0", + "uuid": "3.4.0" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, - "regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "regenerate-unicode-properties": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", - "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "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 + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "regenerate": "^1.4.2" + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + } } }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true }, - "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { - "@babel/runtime": "^7.8.4" + "is-core-module": "2.4.0", + "path-parse": ">=1.0.7" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "resolve-alpn": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.1.2.tgz", + "integrity": "sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA==", + "dev": true + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" } }, - "regexp.prototype.flags": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", - "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "value-or-function": "3.0.0" } }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true - }, - "regexpu-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", - "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", + }, + "responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", "dev": true, "requires": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.0.1", - "regjsgen": "^0.6.0", - "regjsparser": "^0.8.2", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" + "lowercase-keys": "2.0.0" } }, - "regjsgen": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", - "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", - "dev": true - }, - "regjsparser": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", - "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "resq": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resq/-/resq-1.10.0.tgz", + "integrity": "sha512-hCUd0xMalqtPDz4jXIqs0M5Wnv/LZXN8h7unFOo4/nvExT9dDPbhwd3udRxLlp0HgBnHcV009UlduE9NZi7A6w==", "dev": true, "requires": { - "jsesc": "~0.5.0" + "fast-deep-equal": "2.0.1" }, "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true } } }, - "remark": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/remark/-/remark-13.0.0.tgz", - "integrity": "sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA==", + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "requires": { - "remark-parse": "^9.0.0", - "remark-stringify": "^9.0.0", - "unified": "^9.1.0" + "onetime": "5.1.2", + "signal-exit": "3.0.3" } }, - "remark-gfm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-1.0.0.tgz", - "integrity": "sha512-KfexHJCiqvrdBZVbQ6RopMZGwaXz6wFJEfByIuEwGf0arvITHjiKKZ1dpXujjH9KZdm1//XJQwgfnJ3lmXaDPA==", - "dev": true, - "requires": { - "mdast-util-gfm": "^0.1.0", - "micromark-extension-gfm": "^0.3.0" - } + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true }, - "remark-html": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-13.0.2.tgz", - "integrity": "sha512-LhSRQ+3RKdBqB/RGesFWkNNfkGqprDUCwjq54SylfFeNyZby5kqOG8Dn/vYsRoM8htab6EWxFXCY6XIZvMoRiQ==", + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "rgb2hex": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz", + "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "hast-util-sanitize": "^3.0.0", - "hast-util-to-html": "^7.0.0", - "mdast-util-to-hast": "^10.0.0" + "align-text": "0.1.4" } }, - "remark-parse": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz", - "integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==", + "rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", "dev": true, "requires": { - "mdast-util-from-markdown": "^0.8.0" + "glob": "7.1.7" } }, - "remark-reference-links": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-5.0.0.tgz", - "integrity": "sha512-oSIo6lfDyG/1yYl2jPZNXmD9dgyPxp07mSd7snJagVMsDU6NRlD8i54MwHWUgMoOHTs8lIKPkwaUok/tbr5syQ==", + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { - "unist-util-visit": "^2.0.0" + "hash-base": "3.1.0", + "inherits": "2.0.3" } }, - "remark-stringify": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.1.tgz", - "integrity": "sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==", + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", "dev": true, "requires": { - "mdast-util-to-markdown": "^0.6.0" + "rx-lite": "4.0.8" } }, - "remark-toc": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-7.2.0.tgz", - "integrity": "sha512-ppHepvpbg7j5kPFmU5rzDC4k2GTcPDvWcxXyr/7BZzO1cBSPk0stKtEJdsgAyw2WHKPGxadcHIZRjb2/sHxjkg==", + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, "requires": { - "@types/unist": "^2.0.3", - "mdast-util-toc": "^5.0.0" + "tslib": "1.14.1" } }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-json-parse": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", + "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - } + "ret": "0.1.15" } }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "dev": true + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", "dev": true, "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" + "@types/json-schema": "7.0.7", + "ajv": "6.12.6", + "ajv-keywords": "3.5.2" }, "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "fast-deep-equal": "3.1.3", + "fast-json-stable-stringify": "2.1.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.4.1" } } } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "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" - } - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", "dev": true, "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" + "sver-compat": "1.5.0" } }, - "replacestream": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", - "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", - "dev": true, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", "requires": { - "escape-string-regexp": "^1.0.3", - "object-assign": "^4.0.1", - "readable-stream": "^2.0.2" + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "2.3.0", + "range-parser": "1.2.1", + "statuses": "1.5.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==" + } } }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "serialize-error": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", "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.3", - "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.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "type-fest": "0.20.2" }, "dependencies": { - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true } } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "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 + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "2.1.0" + } }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" + "accepts": "1.3.7", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "1.0.3", + "http-errors": "1.6.3", + "mime-types": "2.1.31", + "parseurl": "1.3.3" }, "dependencies": { - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "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.5.0" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true } } }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "requires": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.3", + "send": "0.17.1" } }, - "resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "set-value": { + "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": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "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.1" + } + } } }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { - "value-or-function": "^3.0.0" + "inherits": "2.0.3", + "safe-buffer": "5.1.2" } }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "responselike": { + "shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", - "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "lowercase-keys": "^2.0.0" + "shebang-regex": "3.0.0" } }, - "resq": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/resq/-/resq-1.10.2.tgz", - "integrity": "sha512-HmgVS3j+FLrEDBTDYysPdPVF9/hioDMJ/otOiQDKqk77YfZeeLOj0qi34yObumcud1gBpk+wpBTEg4kMicD++A==", + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "shelljs": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1" - }, - "dependencies": { - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - } + "glob": "7.1.7", + "interpret": "1.4.0", + "rechoir": "0.6.2" } }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "call-bind": "1.0.2", + "get-intrinsic": "1.1.1", + "object-inspect": "1.10.3" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "rgb2hex": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz", - "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==", + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "sinon": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", + "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "dev": true, "requires": { - "glob": "^7.1.3" + "@sinonjs/formatio": "2.0.0", + "diff": "3.5.0", + "lodash.get": "4.4.2", + "lolex": "2.7.5", + "nise": "1.5.3", + "supports-color": "5.5.0", + "type-detect": "4.0.8" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + } } }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "requires": { - "rx-lite": "*" + "ansi-styles": "4.3.0", + "astral-regex": "2.0.0", + "is-fullwidth-code-point": "3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "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 + } } }, - "rxjs": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", - "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { - "tslib": "^2.1.0" + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.3", + "use": "3.1.1" }, "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "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.1" + } } } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-json-parse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", - "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "ret": "~0.1.10" + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.3" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.3" + } + }, + "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.3" + } + } } }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "dev": true - }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "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": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "kind-of": "3.2.2" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "is-buffer": "1.1.6" } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} } } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "socket.io": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.1.2.tgz", + "integrity": "sha512-JubKZnTQ4Z8G4IZWtaAZSiRP3I/inpy8c/Bsx2jrwGrTbKeVU5xd6qkKMHpChYeM3dWZSO0QACiGK+obhBNwYw==", "dev": true, "requires": { - "sver-compat": "^1.5.0" - } - }, - "send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "@types/cookie": "0.4.0", + "@types/cors": "2.8.10", + "@types/node": "15.12.4", + "accepts": "1.3.7", + "base64id": "2.0.0", + "debug": "4.3.1", + "engine.io": "4.1.1", + "socket.io-adapter": "2.1.0", + "socket.io-parser": "4.0.4" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "ms": "2.1.2" } }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, - "serialize-error": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", - "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", + "socket.io-adapter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.1.0.tgz", + "integrity": "sha512-+vDov/aTsLjViYTwS9fPy5pEtTkrbEKsw2M+oVSoFGw6OD1IpvlV1VPhUzNbofCQ8oyMbdYJqDtGdmHQK6TdPg==", + "dev": true + }, + "socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", "dev": true, "requires": { - "type-fest": "^0.20.2" + "@types/component-emitter": "1.2.10", + "component-emitter": "1.3.0", + "debug": "4.3.1" }, "dependencies": { - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 } } }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", + "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "dev": true, + "optional": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "dev": true, "requires": { - "randombytes": "^2.1.0" + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.1", + "urix": "0.1.0" } }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "buffer-from": "1.1.1", + "source-map": "0.6.1" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "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" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "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 } } }, - "serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true, + "optional": true + }, + "space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" + "spdx-expression-parse": "3.0.1", + "spdx-license-ids": "3.0.9" } }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "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" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } + "spdx-exceptions": "2.3.0", + "spdx-license-ids": "3.0.9" } }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "spdx-license-ids": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", "dev": true }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2.3.8" + } }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { - "shebang-regex": "^3.0.0" + "extend-shallow": "3.0.2" } }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "requires": { + "readable-stream": "3.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" } }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "dev": true }, - "sinon": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", - "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", + "stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", "dev": true, "requires": { - "@sinonjs/formatio": "^2.0.0", - "diff": "^3.1.0", - "lodash.get": "^4.4.2", - "lolex": "^2.2.0", - "nise": "^1.2.0", - "supports-color": "^5.1.0", - "type-detect": "^4.0.5" + "escape-string-regexp": "2.0.0" }, "dependencies": { - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true - }, - "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" - } } } }, - "sirv": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", - "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", - "dev": true, - "requires": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^1.0.0" - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "standard-version": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.0.tgz", + "integrity": "sha512-cYxxKXhYfI3S9+CA84HmrJa9B88H56V5FQ302iFF2TNwJukJCNoU8FgWt+11YtwKFXRkQQFpepC2QOF7aDq2Ow==", "dev": true, "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "chalk": "2.4.2", + "conventional-changelog": "3.1.24", + "conventional-changelog-config-spec": "2.1.0", + "conventional-changelog-conventionalcommits": "4.5.0", + "conventional-recommended-bump": "6.1.0", + "detect-indent": "6.1.0", + "detect-newline": "3.1.0", + "dotgitignore": "2.1.0", + "figures": "3.2.0", + "find-up": "5.0.0", + "fs-access": "1.0.1", + "git-semver-tags": "4.1.1", + "semver": "7.3.5", + "stringify-package": "1.0.1", + "yargs": "16.2.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "locate-path": "6.0.0", + "path-exists": "4.0.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==", + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "color-name": "~1.1.4" + "p-locate": "5.0.0" } }, - "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==", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "4.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "3.1.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "7.0.4", + "escalade": "3.1.1", + "get-caller-file": "2.0.5", + "require-directory": "2.1.1", + "string-width": "4.2.2", + "y18n": "5.0.8", + "yargs-parser": "20.2.9" + } } } }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "define-property": "0.2.5", + "object-copy": "0.1.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "stream-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", + "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", + "dev": true, + "requires": { + "readable-stream": "2.1.5" + }, + "dependencies": { + "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 }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "readable-stream": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "buffer-shims": "1.0.0", + "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" } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "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 + } + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.7" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "safe-buffer": "5.1.2" } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + } + } + }, + "stream-buffers": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", + "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==", + "dev": true + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "0.1.2" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "0.1.4", + "readable-stream": "2.3.7" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "safe-buffer": "5.1.2" } } } }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.7", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.2" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "safe-buffer": "5.1.2" } } } }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "streamroller": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", + "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", "dev": true, "requires": { - "kind-of": "^3.2.0" + "date-format": "2.1.0", + "debug": "4.3.1", + "fs-extra": "8.1.0" }, "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", "dev": true }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "4.2.6", + "jsonfile": "4.0.0", + "universalify": "0.1.2" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "graceful-fs": "4.2.6" } + }, + "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 + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true } } }, - "socket.io": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", - "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", + "dev": true + }, + "string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=", "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" - } + "optional": true }, - "socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", + "string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", "dev": true }, - "socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" + "emoji-regex": "8.0.0", + "is-fullwidth-code-point": "3.0.0", + "strip-ansi": "6.0.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, - "optional": true + "requires": { + "call-bind": "1.0.2", + "define-properties": "1.1.3" + } }, - "source-map-resolve": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", - "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0" + "call-bind": "1.0.2", + "define-properties": "1.1.3" } }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "safe-buffer": "5.2.1" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true } } }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "stringify-entities": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.1.0.tgz", + "integrity": "sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg==", + "dev": true, + "requires": { + "character-entities-html4": "1.1.4", + "character-entities-legacy": "1.1.4", + "xtend": "4.0.2" + } + }, + "stringify-package": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", + "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", "dev": true }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "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" + } }, - "space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", "dev": true }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "min-indent": "1.0.1" } }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", "dev": true, "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "minimist": "1.2.5" } }, - "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "suffix": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/suffix/-/suffix-0.1.1.tgz", + "integrity": "sha1-zFgjFkag7xEC95R47zqSSP2chC8=", "dev": true }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "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": { - "through": "2" + "has-flag": "3.0.0" } }, - "split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.3" + } + }, + "table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "requires": { + "ajv": "8.6.0", + "lodash.clonedeep": "4.5.0", + "lodash.truncate": "4.4.2", + "slice-ansi": "4.0.0", + "string-width": "4.2.2", + "strip-ansi": "6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz", + "integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==", + "dev": true, + "requires": { + "fast-deep-equal": "3.1.3", + "json-schema-traverse": "1.0.0", + "require-from-string": "2.0.2", + "uri-js": "4.4.1" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "tapable": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz", + "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==", "dev": true }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "requires": { + "chownr": "1.1.4", + "mkdirp-classic": "0.5.3", + "pump": "3.0.0", + "tar-stream": "2.2.0" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "4.1.0", + "end-of-stream": "1.4.4", + "fs-constants": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "3.6.0" + } + }, + "temp-fs": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/temp-fs/-/temp-fs-0.9.9.tgz", + "integrity": "sha1-gHFzBDeHByDpQxUy/igUNk+IA9c=", + "dev": true, + "requires": { + "rimraf": "2.5.4" + } + }, + "ternary-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-3.0.0.tgz", + "integrity": "sha512-oIzdi+UL/JdktkT+7KU5tSIQjj8pbShj3OASuvDEhm0NT5lppsm7aXWAmAq4/QMaBIyfuEcNLbAQA+HpaISobQ==", + "dev": true, + "requires": { + "duplexify": "4.1.1", + "fork-stream": "0.0.4", + "merge-stream": "2.0.0", + "through2": "3.0.2" + }, + "dependencies": { + "duplexify": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz", + "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.4", + "inherits": "2.0.3", + "readable-stream": "3.6.0", + "stream-shift": "1.0.1" + } + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "2.0.4", + "readable-stream": "3.6.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + } + } + } + } + }, + "terser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.4.0.tgz", + "integrity": "sha512-3dZunFLbCJis9TAF2VnX+VrQLctRUmt1p3W2kCsJuZE4ZgWqh//+1MZ62EanewrqKoUf4zIaDGZAvml4UDc0OQ==", "dev": true, "requires": { - "extend-shallow": "^3.0.0" + "commander": "2.20.3", + "source-map": "0.7.3", + "source-map-support": "0.5.19" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } } }, - "split2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", - "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } + "textextensions": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-3.3.0.tgz", + "integrity": "sha512-mk82dS8eRABNbeVJrEiN5/UMSCliINAuz8mkUwH4SwslkNP//gbEzlWNS5au0z5Dpx40SQxzqZevZkn+WYJ9Dw==", + "dev": true }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } + "readable-stream": "3.6.0" } }, - "standard-version": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.2.tgz", - "integrity": "sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ==", + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", "dev": true, "requires": { - "chalk": "^2.4.2", - "conventional-changelog": "3.1.24", - "conventional-changelog-config-spec": "2.1.0", - "conventional-changelog-conventionalcommits": "4.6.1", - "conventional-recommended-bump": "6.1.0", - "detect-indent": "^6.0.0", - "detect-newline": "^3.1.0", - "dotgitignore": "^2.1.0", - "figures": "^3.1.0", - "find-up": "^5.0.0", - "fs-access": "^1.0.1", - "git-semver-tags": "^4.0.0", - "semver": "^7.1.1", - "stringify-package": "^1.0.1", - "yargs": "^16.0.0" + "through2": "2.0.5", + "xtend": "4.0.2" }, "dependencies": { - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "p-limit": "^3.0.2" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "safe-buffer": "5.1.2" } }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "readable-stream": "2.3.7", + "xtend": "4.0.2" } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true } } }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "0.10.53", + "next-tick": "1.0.0" + } + }, + "tiny-hashes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tiny-hashes/-/tiny-hashes-1.0.1.tgz", + "integrity": "sha512-knIN5zj4fl7kW4EBU5sLP20DWUvi/rVouvJezV0UAym2DkQaqm365Nyc8F3QEiOvunNDMxR8UhcXd1d5g+Wg1g==" + }, + "tiny-lr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", + "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "body": "5.1.0", + "debug": "3.2.7", + "faye-websocket": "0.10.0", + "livereload-js": "2.4.0", + "object-assign": "4.1.1", + "qs": "6.7.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "ms": "2.1.3" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + } + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "1.0.0", + "is-negated-glob": "1.0.0" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-buffer": "1.1.6" } } } }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } }, - "stream-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", - "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "7.0.0" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", "dev": true, "requires": { - "readable-stream": "~2.1.0" + "through2": "2.0.5" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "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.1.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", - "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "buffer-shims": "^1.0.0", - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "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 + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "2.3.7", + "xtend": "4.0.2" + } } } }, - "stream-buffers": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", - "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==", - "dev": true + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "requires": { - "duplexer": "~0.1.1" + "psl": "1.8.0", + "punycode": "2.1.1" } }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, - "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, - "stream-shift": { + "trim-off-newlines": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", + "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", "dev": true }, - "streamroller": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.4.tgz", - "integrity": "sha512-GI9NzeD+D88UFuIlJkKNDH/IsuR+qIN7Qh8EsmhoRZr9bQoehTraRgwtLUkZbpcAw+hLPfHOypmppz8YyGK68w==", - "dev": true, - "requires": { - "date-format": "^4.0.4", - "debug": "^4.3.3", - "fs-extra": "^10.0.1" - } - }, - "strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", + "trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "dev": true }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@types/json5": "0.0.29", + "json5": "1.0.1", + "minimist": "1.2.5", + "strip-bom": "3.0.0" }, "dependencies": { - "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==", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "1.2.5" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true } } }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "safe-buffer": "5.1.2" } }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": 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.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "prelude-ls": "1.2.1" } }, - "stringify-entities": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.1.0.tgz", - "integrity": "sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg==", - "dev": true, + "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.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "requires": { - "character-entities-html4": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "xtend": "^4.0.0" + "media-typer": "0.3.0", + "mime-types": "2.1.31" } }, - "stringify-package": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", - "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "typescript-compare": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz", + "integrity": "sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA==", "requires": { - "ansi-regex": "^5.0.1" + "typescript-logic": "0.0.0" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "typescript-logic": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz", + "integrity": "sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q==" }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", - "dev": true + "typescript-tuple": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz", + "integrity": "sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==", + "requires": { + "typescript-compare": "0.0.2" + } }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "ua-parser-js": { + "version": "0.7.28", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.28.tgz", + "integrity": "sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==", "dev": true }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "uglify-js": { + "version": "3.13.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.9.tgz", + "integrity": "sha512-wZbyTQ1w6Y7fHdt8sJnHfSIuWeDgk6B5rCb4E/AM6QNNPbOMIZph21PW5dRB3h7Df0GszN+t7RuUH6sWK5bF0g==", "dev": true, - "requires": { - "min-indent": "^1.0.0" - } + "optional": true }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "dev": true }, - "subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", "dev": true, "requires": { - "minimist": "^1.1.0" + "source-map": "0.5.7", + "uglify-js": "2.8.29", + "webpack-sources": "1.4.3" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } } }, - "suffix": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/suffix/-/suffix-0.1.1.tgz", - "integrity": "sha1-zFgjFkag7xEC95R47zqSSP2chC8=", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "function-bind": "1.1.1", + "has-bigints": "1.0.1", + "has-symbols": "1.0.2", + "which-boxed-primitive": "1.0.2" } }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dev": true, "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" + "buffer": "5.7.1", + "through": "2.3.8" } }, - "table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", "dev": true, "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" + "arr-flatten": "1.1.0", + "arr-map": "2.0.2", + "bach": "1.2.0", + "collection-map": "1.0.0", + "es6-weak-map": "2.0.3", + "fast-levenshtein": "1.1.4", + "last-run": "1.1.1", + "object.defaults": "1.1.0", + "object.reduce": "1.0.1", + "undertaker-registry": "1.0.1" }, "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", "dev": true } } }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", "dev": true }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", "dev": true, "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" + "unicode-canonical-property-names-ecmascript": "1.0.4", + "unicode-property-aliases-ecmascript": "1.1.0" } }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true + }, + "unified": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.1.tgz", + "integrity": "sha512-juWjuI8Z4xFg8pJbnEZ41b5xjGUWGHqXALmBZ3FC3WX0PIx1CZBIIJ6mXbYMcf6Yw4Fi0rFUTA1cdz/BglbOhA==", "dev": true, "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "bail": "1.0.5", + "extend": "3.0.2", + "is-buffer": "2.0.5", + "is-plain-obj": "2.1.0", + "trough": "1.0.5", + "vfile": "4.2.1" }, "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true } } }, - "temp-fs": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/temp-fs/-/temp-fs-0.9.9.tgz", - "integrity": "sha1-gHFzBDeHByDpQxUy/igUNk+IA9c=", + "union-value": { + "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": { - "rimraf": "~2.5.2" - }, - "dependencies": { - "rimraf": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", - "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - } + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "2.0.1" } }, - "ternary-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-3.0.0.tgz", - "integrity": "sha512-oIzdi+UL/JdktkT+7KU5tSIQjj8pbShj3OASuvDEhm0NT5lppsm7aXWAmAq4/QMaBIyfuEcNLbAQA+HpaISobQ==", + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", "dev": true, "requires": { - "duplexify": "^4.1.1", - "fork-stream": "^0.0.4", - "merge-stream": "^2.0.0", - "through2": "^3.0.1" - }, - "dependencies": { - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - } + "json-stable-stringify-without-jsonify": "1.0.1", + "through2-filter": "3.0.0" } }, - "terser": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.0.tgz", - "integrity": "sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A==", + "unist-builder": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", + "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", + "dev": true + }, + "unist-util-generated": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", + "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", + "dev": true + }, + "unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "dev": true + }, + "unist-util-position": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", + "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", + "dev": true + }, + "unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", "dev": true, "requires": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } + "@types/unist": "2.0.3" } }, - "terser-webpack-plugin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", - "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", + "unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", "dev": true, "requires": { - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "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 - } + "@types/unist": "2.0.3", + "unist-util-is": "4.1.0", + "unist-util-visit-parents": "3.1.1" } }, - "text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dev": true, + "requires": { + "@types/unist": "2.0.3", + "unist-util-is": "4.1.0" + } }, - "textextensions": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-3.3.0.tgz", - "integrity": "sha512-mk82dS8eRABNbeVJrEiN5/UMSCliINAuz8mkUwH4SwslkNP//gbEzlWNS5au0z5Dpx40SQxzqZevZkn+WYJ9Dw==", + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "readable-stream": "3" + "has-value": "0.3.1", + "isobject": "3.0.1" }, "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true } } }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "unzipper": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.15.tgz", + "integrity": "sha512-2aaUvO4RAeHDvOCuEtth7jrHFaCKTSXPqUkXwADaLBzGbgZGzUDccoEdJ5lW+3RmfpOZYNx0Rw6F6PUzM6caIA==", "dev": true, "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" + "big-integer": "1.6.48", + "binary": "0.3.0", + "bluebird": "3.4.7", + "buffer-indexof-polyfill": "1.0.2", + "duplexer2": "0.1.4", + "fstream": "1.0.12", + "listenercount": "1.0.1", + "readable-stream": "2.3.7", + "setimmediate": "1.0.5" }, "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "safe-buffer": "5.1.2" } } } }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" + "punycode": "2.1.1" } }, - "tiny-hashes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tiny-hashes/-/tiny-hashes-1.0.1.tgz", - "integrity": "sha512-knIN5zj4fl7kW4EBU5sLP20DWUvi/rVouvJezV0UAym2DkQaqm365Nyc8F3QEiOvunNDMxR8UhcXd1d5g+Wg1g==" + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true }, - "tiny-lr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", - "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, "requires": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" + "punycode": "1.3.2", + "querystring": "0.2.0" }, "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true } } }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", + "dev": true + }, + "url-parse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", + "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", "dev": true, "requires": { - "os-tmpdir": "~1.0.2" + "querystringify": "2.2.0", + "requires-port": "1.0.0" } }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" + "inherits": "2.0.3" } }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "homedir-polyfill": "1.0.3" } }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "spdx-correct": "3.1.1", + "spdx-expression-parse": "3.0.1" } }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vfile": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", + "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", "dev": true, "requires": { - "is-number": "^7.0.0" + "@types/unist": "2.0.3", + "is-buffer": "2.0.5", + "unist-util-stringify-position": "2.0.3", + "vfile-message": "2.0.4" }, "dependencies": { - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", "dev": true } } }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", "dev": true, "requires": { - "through2": "^2.0.3" + "@types/unist": "2.0.3", + "unist-util-stringify-position": "2.0.3" + } + }, + "vfile-reporter": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-6.0.2.tgz", + "integrity": "sha512-GN2bH2gs4eLnw/4jPSgfBjo+XCuvnX9elHICJZjVD4+NM0nsUrMTvdjGY5Sc/XG69XVTgLwj7hknQVc6M9FukA==", + "dev": true, + "requires": { + "repeat-string": "1.6.1", + "string-width": "4.2.2", + "supports-color": "6.1.0", + "unist-util-stringify-position": "2.0.3", + "vfile-sort": "2.2.2", + "vfile-statistics": "1.1.4" }, "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "supports-color": { + "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": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "has-flag": "3.0.0" } } } }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + "vfile-sort": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.2.tgz", + "integrity": "sha512-tAyUqD2R1l/7Rn7ixdGkhXLD3zsg+XLAeUDUhXearjfIcpL1Hcsj5hHpCoy/gvfK/Ws61+e972fm0F7up7hfYA==", + "dev": true }, - "totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", + "vfile-statistics": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.4.tgz", + "integrity": "sha512-lXhElVO0Rq3frgPvFBwahmed3X03vjPF8OcjKMy8+F1xU/3Q3QU3tKEDp743SFtb74PdF0UWpxPvtOP0GCLheA==", "dev": true }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", "dev": true, "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "clone": "2.1.2", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.3", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.1" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + } } }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "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 - }, - "trough": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", - "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", - "dev": true + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "1.0.0", + "glob-stream": "6.1.0", + "graceful-fs": "4.2.6", + "is-valid-glob": "1.0.0", + "lazystream": "1.0.0", + "lead": "1.0.0", + "object.assign": "4.1.2", + "pumpify": "1.5.1", + "readable-stream": "2.3.7", + "remove-bom-buffer": "3.0.0", + "remove-bom-stream": "1.2.0", + "resolve-options": "1.1.0", + "through2": "2.0.5", + "to-through": "2.0.0", + "value-or-function": "3.0.0", + "vinyl": "2.2.1", + "vinyl-sourcemap": "1.1.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "2.3.7", + "xtend": "4.0.2" + } + } + } }, - "tsconfig-paths": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz", - "integrity": "sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw==", + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", "dev": true, "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" + "append-buffer": "1.0.2", + "convert-source-map": "1.8.0", + "graceful-fs": "4.2.6", + "normalize-path": "2.1.1", + "now-and-later": "2.0.1", + "remove-bom-buffer": "3.0.0", + "vinyl": "2.2.1" }, "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "minimist": "^1.2.0" + "remove-trailing-separator": "1.1.0" } } } }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", "dev": true, "requires": { - "safe-buffer": "^5.0.1" + "source-map": "0.5.7" } }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", "dev": true }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "vue-template-compiler": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz", + "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==", "dev": true, + "optional": true, "requires": { - "prelude-ls": "^1.2.1" + "de-indent": "1.0.2", + "he": "1.2.0" } }, - "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.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "walk": { + "version": "2.3.14", + "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", + "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", + "dev": true, "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "foreachasync": "3.0.0" } }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", "dev": true, - "peer": true - }, - "typescript-compare": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz", - "integrity": "sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA==", "requires": { - "typescript-logic": "^0.0.0" + "chokidar": "3.5.2", + "graceful-fs": "4.2.6", + "neo-async": "2.6.2", + "watchpack-chokidar2": "2.0.1" } }, - "typescript-logic": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz", - "integrity": "sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q==" - }, - "typescript-tuple": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz", - "integrity": "sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==", + "watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, "requires": { - "typescript-compare": "^0.0.2" + "chokidar": "2.1.8" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.4", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "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.1" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.3", + "braces": "2.3.2", + "fsevents": "1.2.13", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.1", + "normalize-path": "3.0.0", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1", + "upath": "1.2.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "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.1" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "1.5.0", + "nan": "2.14.2" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "1.13.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.3", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "4.2.6", + "micromatch": "3.1.10", + "readable-stream": "2.3.7" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + } } }, - "ua-parser-js": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", - "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", - "dev": true - }, - "uglify-js": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.2.tgz", - "integrity": "sha512-peeoTk3hSwYdoc9nrdiEJk+gx1ALCtTjdYuKSXMTDqq7n1W7dHPqWDdSi+BPL0ni2YMeHD7hKUSdbj3TZauY2A==", - "dev": true, - "optional": true - }, - "unbox-primitive": { + "wcwidth": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "dev": true, "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" + "defaults": "1.0.3" } }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "undertaker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", - "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "webdriver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-7.7.4.tgz", + "integrity": "sha512-bE6/A+OYb040GZ1MiuZebc8bOOYm797dmqEfmj6aoEQ4BMy1juiFlzCzeBzAlPrq33qPa8/CSYfH7rnkB3RRwg==", "dev": true, "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "fast-levenshtein": "^1.0.0", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" + "@types/node": "14.17.4", + "@wdio/config": "7.7.3", + "@wdio/logger": "7.7.0", + "@wdio/protocols": "7.7.4", + "@wdio/types": "7.7.3", + "@wdio/utils": "7.7.3", + "got": "11.8.2", + "lodash.merge": "4.6.2" }, "dependencies": { - "fast-levenshtein": { + "@types/node": { + "version": "14.17.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz", + "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==", + "dev": true + }, + "@wdio/logger": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.7.0.tgz", + "integrity": "sha512-XX/OkC8NlvsBdhKsb9j7ZbuQtF/Vuo0xf38PXdqYtVezOrYbDuba0hPG++g/IGNuAF34ZbSi+49cvz4u5w92kQ==", + "dev": true, + "requires": { + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.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/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", - "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } } } }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "webdriverio": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-7.7.4.tgz", + "integrity": "sha512-VSWRj2mmvA8WbideFAYb5BMWPkBCJ7gJHhYrUSibTrMHKreRtX++cw/oGxxowy9/pTHsAW6OxlnaDxFL5Gt08A==", + "dev": true, + "requires": { + "@types/aria-query": "4.2.1", + "@types/node": "14.17.4", + "@wdio/config": "7.7.3", + "@wdio/logger": "7.7.0", + "@wdio/protocols": "7.7.4", + "@wdio/repl": "7.7.3", + "@wdio/types": "7.7.3", + "@wdio/utils": "7.7.3", + "archiver": "5.3.0", + "aria-query": "4.2.2", + "atob": "2.1.2", + "css-shorthand-properties": "1.1.1", + "css-value": "0.0.1", + "devtools": "7.7.4", + "devtools-protocol": "0.0.892017", + "fs-extra": "10.0.0", + "get-port": "5.1.1", + "grapheme-splitter": "1.0.4", + "lodash.clonedeep": "4.5.0", + "lodash.isobject": "3.0.2", + "lodash.isplainobject": "4.0.6", + "lodash.zip": "4.2.0", + "minimatch": "3.0.4", + "puppeteer-core": "9.1.1", + "query-selector-shadow-dom": "1.0.0", + "resq": "1.10.0", + "rgb2hex": "0.2.5", + "serialize-error": "8.1.0", + "webdriver": "7.7.4" + }, + "dependencies": { + "@types/node": { + "version": "14.17.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz", + "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==", + "dev": true + }, + "@wdio/logger": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.7.0.tgz", + "integrity": "sha512-XX/OkC8NlvsBdhKsb9j7ZbuQtF/Vuo0xf38PXdqYtVezOrYbDuba0hPG++g/IGNuAF34ZbSi+49cvz4u5w92kQ==", + "dev": true, + "requires": { + "chalk": "4.1.1", + "loglevel": "1.7.1", + "loglevel-plugin-prefix": "0.8.4", + "strip-ansi": "6.0.0" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "4.3.0", + "supports-color": "7.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "4.0.0" + } + } } }, - "unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", - "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", - "dev": true - }, - "unified": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz", - "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==", - "dev": true, - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" + "webpack": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", + "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", + "dev": true, + "requires": { + "acorn": "5.7.4", + "acorn-dynamic-import": "2.0.2", + "ajv": "6.12.6", + "ajv-keywords": "3.5.2", + "async": "2.6.3", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.4.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.4.0", + "loader-utils": "1.4.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.5", + "node-libs-browser": "2.2.1", + "source-map": "0.5.7", + "supports-color": "4.5.0", + "tapable": "0.2.9", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.7.5", + "webpack-sources": "1.4.3", + "yargs": "8.0.2" }, "dependencies": { - "is-plain-obj": { + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "3.1.3", + "fast-json-stable-stringify": "2.1.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.4.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "async": { + "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.21" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "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.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "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.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.5", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.3", + "strip-eof": "1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "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 + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "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.1" + } + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.2.6", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "5.2.2", + "emojis-list": "3.0.0", + "json5": "1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "1.2.5" + } + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "1.2.5" + } + }, + "os-locale": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "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" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.3.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true - } - } - }, - "union-value": { - "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" - }, - "dependencies": { - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true - } - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "unist-builder": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", - "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", - "dev": true - }, - "unist-util-generated": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", - "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", - "dev": true - }, - "unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", - "dev": true - }, - "unist-util-position": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", - "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", - "dev": true - }, - "unist-util-stringify-position": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", - "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", - "dev": true, - "requires": { - "@types/unist": "^2.0.2" - } - }, - "unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" - } - }, - "unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.5.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "isarray": "1.0.0" + "ansi-regex": "3.0.0" } } } }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "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.1.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "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.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", "dev": true + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.3", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.2", + "yargs-parser": "7.0.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + } } } }, - "unzipper": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.15.tgz", - "integrity": "sha512-2aaUvO4RAeHDvOCuEtth7jrHFaCKTSXPqUkXwADaLBzGbgZGzUDccoEdJ5lW+3RmfpOZYNx0Rw6F6PUzM6caIA==", - "dev": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "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.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "webpack-bundle-analyzer": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz", + "integrity": "sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA==", "dev": true, "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "acorn": "7.4.1", + "acorn-walk": "7.2.0", + "bfj": "6.1.2", + "chalk": "2.4.2", + "commander": "2.20.3", + "ejs": "2.7.4", + "express": "4.17.1", + "filesize": "3.6.1", + "gzip-size": "5.1.1", + "lodash": "4.17.21", + "mkdirp": "0.5.5", + "opener": "1.5.2", + "ws": "6.2.2" }, "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "ejs": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", + "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==", "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "1.2.5" + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "requires": { + "async-limiter": "1.0.1" + } } } }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.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 - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "webpack-core": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", + "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", "dev": true, "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "source-list-map": "0.1.8", + "source-map": "0.4.4" + }, + "dependencies": { + "source-list-map": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", + "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } } }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "webpack-dev-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "loud-rejection": "1.6.0", + "memory-fs": "0.4.1", + "mime": "2.5.2", + "path-is-absolute": "1.0.1", + "range-parser": "1.2.1", + "url-join": "2.0.5", + "webpack-log": "1.2.0" }, "dependencies": { - "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=", + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", "dev": true } } }, - "vfile": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", - "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "webpack-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", + "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", "dev": true, "requires": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^2.0.0", - "vfile-message": "^2.0.0" + "chalk": "2.4.2", + "log-symbols": "2.2.0", + "loglevelnext": "1.0.5", + "uuid": "3.4.0" + }, + "dependencies": { + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "2.4.2" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, - "vfile-message": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", - "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", "dev": true, "requires": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" + "source-list-map": "2.0.1", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, - "vfile-reporter": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-6.0.2.tgz", - "integrity": "sha512-GN2bH2gs4eLnw/4jPSgfBjo+XCuvnX9elHICJZjVD4+NM0nsUrMTvdjGY5Sc/XG69XVTgLwj7hknQVc6M9FukA==", + "webpack-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", + "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", "dev": true, "requires": { - "repeat-string": "^1.5.0", - "string-width": "^4.0.0", - "supports-color": "^6.0.0", - "unist-util-stringify-position": "^2.0.0", - "vfile-sort": "^2.1.2", - "vfile-statistics": "^1.1.0" + "gulp-util": "3.0.8", + "lodash.clone": "4.5.0", + "lodash.some": "4.6.0", + "memory-fs": "0.3.0", + "through": "2.3.8", + "vinyl": "1.2.0", + "webpack": "1.15.0" }, "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.4" + } + }, + "browserify-aes": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", + "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "0.2.9" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "1.5.1", + "ieee754": "1.2.1", + "isarray": "1.0.0" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.3", + "fsevents": "1.2.13", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "crypto-browserify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", + "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", + "dev": true, + "requires": { + "browserify-aes": "0.4.0", + "pbkdf2-compat": "2.0.1", + "ripemd160": "0.2.0", + "sha.js": "2.2.6" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "enhanced-resolve": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", + "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", + "dev": true, + "requires": { + "graceful-fs": "4.2.6", + "memory-fs": "0.2.0", + "tapable": "0.1.10" + }, + "dependencies": { + "memory-fs": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", + "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", + "dev": true + } + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "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.1" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "1.5.0", + "nan": "2.14.2" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "interpret": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", + "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "kind-of": "6.0.3" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } - } - } - }, - "vfile-sort": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.2.tgz", - "integrity": "sha512-tAyUqD2R1l/7Rn7ixdGkhXLD3zsg+XLAeUDUhXearjfIcpL1Hcsj5hHpCoy/gvfK/Ws61+e972fm0F7up7hfYA==", - "dev": true - }, - "vfile-statistics": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.4.tgz", - "integrity": "sha512-lXhElVO0Rq3frgPvFBwahmed3X03vjPF8OcjKMy8+F1xU/3Q3QU3tKEDp743SFtb74PdF0UWpxPvtOP0GCLheA==", - "dev": true - }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "dependencies": { - "replace-ext": { + }, + "is-binary-path": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.13.1" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.3" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "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.3" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", "dev": true - } - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "is-extglob": "1.0.0" } - } - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + }, + "memory-fs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", + "dev": true, + "requires": { + "errno": "0.1.8", + "readable-stream": "2.3.7" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "1.2.5" + } + }, + "node-libs-browser": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", + "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", + "dev": true, + "requires": { + "assert": "1.5.0", + "browserify-zlib": "0.1.4", + "buffer": "4.9.2", + "console-browserify": "1.2.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.3.0", + "domain-browser": "1.2.0", + "events": "1.1.1", + "https-browserify": "0.0.1", + "os-browserify": "0.2.1", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.7", + "stream-browserify": "2.0.2", + "stream-http": "2.8.3", + "string_decoder": "0.10.31", + "timers-browserify": "2.0.12", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.4", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "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 + } + } + }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "^0.5.1" - } - }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", - "dev": true - }, - "vue-template-compiler": { - "version": "2.6.14", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz", - "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==", - "dev": true, - "optional": true, - "requires": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "walk": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.15.tgz", - "integrity": "sha512-4eRTBZljBfIISK1Vnt69Gvr2w/wc3U6Vtrw7qiN5iqYJPH7LElcYh/iU4XWhdCy2dZqv1ToMyYlybDylfG/5Vg==", - "dev": true, - "requires": { - "foreachasync": "^3.0.0" - } - }, - "watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "webdriver": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-7.16.16.tgz", - "integrity": "sha512-x8UoG9k/P8KDrfSh1pOyNevt9tns3zexoMxp9cKnyA/7HYSErhZYTLGlgxscAXLtQG41cMH/Ba/oBmOx7Hgd8w==", - "dev": true, - "requires": { - "@types/node": "^17.0.4", - "@wdio/config": "7.16.16", - "@wdio/logger": "7.16.0", - "@wdio/protocols": "7.16.7", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "got": "^11.0.2", - "ky": "^0.29.0", - "lodash.merge": "^4.6.1" - } - }, - "webdriverio": { - "version": "7.16.16", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-7.16.16.tgz", - "integrity": "sha512-caPaEWyuD3Qoa7YkW4xCCQA4v9Pa9wmhFGPvNZh3ERtjMCNi8L/XXOdkekWNZmFh3tY0kFguBj7+fAwSY7HAGw==", - "dev": true, - "requires": { - "@types/aria-query": "^5.0.0", - "@types/node": "^17.0.4", - "@wdio/config": "7.16.16", - "@wdio/logger": "7.16.0", - "@wdio/protocols": "7.16.7", - "@wdio/repl": "7.16.14", - "@wdio/types": "7.16.14", - "@wdio/utils": "7.16.14", - "archiver": "^5.0.0", - "aria-query": "^5.0.0", - "css-shorthand-properties": "^1.1.1", - "css-value": "^0.0.1", - "devtools": "7.16.16", - "devtools-protocol": "^0.0.973690", - "fs-extra": "^10.0.0", - "get-port": "^5.1.1", - "grapheme-splitter": "^1.0.2", - "lodash.clonedeep": "^4.5.0", - "lodash.isobject": "^3.0.2", - "lodash.isplainobject": "^4.0.6", - "lodash.zip": "^4.2.0", - "minimatch": "^5.0.0", - "puppeteer-core": "^13.1.3", - "query-selector-shadow-dom": "^1.0.0", - "resq": "^1.9.1", - "rgb2hex": "0.2.5", - "serialize-error": "^8.0.0", - "webdriver": "7.16.16" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" + "remove-trailing-separator": "1.1.0" } }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "os-browserify": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", + "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "brace-expansion": "^2.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } - } - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "webpack": { - "version": "5.70.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", - "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.2", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "4.2.6", + "micromatch": "3.1.10", + "readable-stream": "2.3.7" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.4", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "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.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "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.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "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.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.3", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "ripemd160": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", + "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", + "dev": true + }, + "sha.js": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", + "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, - "requires": {} + "requires": { + "safe-buffer": "5.1.2" + } }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "has-flag": "1.0.0" } }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "tapable": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "dev": true + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, - "requires": {} + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "uglify-js": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", + "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", "dev": true, "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "async": "0.2.10", + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } } - } - } - }, - "webpack-bundle-analyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", - "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", - "dev": true, - "requires": { - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "chalk": "^4.1.0", - "commander": "^7.2.0", - "gzip-size": "^6.0.0", - "lodash": "^4.17.20", - "opener": "^1.5.2", - "sirv": "^1.0.7", - "ws": "^7.3.1" - }, - "dependencies": { - "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "color-convert": "^2.0.1" + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" } }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "indexof": "0.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==", + "watchpack": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", "dev": true, "requires": { - "color-name": "~1.1.4" + "async": "0.9.2", + "chokidar": "1.7.0", + "graceful-fs": "4.2.6" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } } }, - "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 + "webpack": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", + "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", + "dev": true, + "requires": { + "acorn": "3.3.0", + "async": "1.5.2", + "clone": "1.0.4", + "enhanced-resolve": "0.9.1", + "interpret": "0.6.6", + "loader-utils": "0.2.17", + "memory-fs": "0.3.0", + "mkdirp": "0.5.5", + "node-libs-browser": "0.7.0", + "optimist": "0.6.1", + "supports-color": "3.2.3", + "tapable": "0.1.10", + "uglify-js": "2.7.5", + "watchpack": "0.2.9", + "webpack-core": "0.6.9" + } }, - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", "dev": true }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { - "has-flag": "^4.0.0" + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" } - }, - "ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "requires": {} } } }, - "webpack-merge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", - "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", - "dev": true, - "requires": { - "lodash": "^4.17.15" - } - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - }, - "webpack-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-7.0.0.tgz", - "integrity": "sha512-XoAQTHyCaYMo6TS7Atv1HYhtmBgKiVLONJbzLBl2V3eibXQ2IT/MCRM841RW/r3vToKD5ivrTJFWgd/ghoxoRg==", - "dev": true, - "requires": { - "fancy-log": "^1.3.3", - "lodash.clone": "^4.3.2", - "lodash.some": "^4.2.2", - "memory-fs": "^0.5.0", - "plugin-error": "^1.0.1", - "supports-color": "^8.1.1", - "through": "^2.3.8", - "vinyl": "^2.2.1" - } - }, "websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", "dev": true, "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "http-parser-js": "0.5.3", + "safe-buffer": "5.1.2", + "websocket-extensions": "0.1.4" } }, "websocket-extensions": { @@ -41891,23 +21976,13 @@ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } }, "which-boxed-primitive": { @@ -41916,11 +21991,11 @@ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-bigint": "1.0.2", + "is-boolean-object": "1.1.1", + "is-number-object": "1.0.5", + "is-string": "1.0.6", + "is-symbol": "1.0.4" } }, "which-collection": { @@ -41929,10 +22004,10 @@ "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", "dev": true, "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "is-map": "2.0.2", + "is-set": "2.0.2", + "is-weakmap": "2.0.1", + "is-weakset": "2.0.1" } }, "which-module": { @@ -41942,19 +22017,68 @@ "dev": true }, "which-typed-array": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", - "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", + "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", + "dev": true, + "requires": { + "available-typed-arrays": "1.0.4", + "call-bind": "1.0.2", + "es-abstract": "1.18.3", + "foreach": "2.0.5", + "function-bind": "1.1.1", + "has-symbols": "1.0.2", + "is-typed-array": "1.1.5" + } + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } } }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -41968,9 +22092,9 @@ "dev": true }, "workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.4.tgz", + "integrity": "sha512-jGWPzsUqzkow8HoAvqaPWTUPCrlPJaJ5tY8Iz7n1uCz3tTp6s3CDG0FF1NsX42WNlkRSW6Mr+CDZGnNoSsKa7g==", "dev": true }, "wrap-ansi": { @@ -41979,9 +22103,9 @@ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "4.3.0", + "string-width": "4.2.2", + "strip-ansi": "6.0.0" }, "dependencies": { "ansi-styles": { @@ -41990,7 +22114,7 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "2.0.1" } }, "color-convert": { @@ -41999,7 +22123,7 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.4" } }, "color-name": { @@ -42022,7 +22146,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "^0.5.1" + "mkdirp": "0.5.5" }, "dependencies": { "mkdirp": { @@ -42031,17 +22155,16 @@ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "^1.2.5" + "minimist": "1.2.5" } } } }, "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "dev": true, - "requires": {} + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.0.tgz", + "integrity": "sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw==", + "dev": true }, "xtend": { "version": "4.0.2", @@ -42056,9 +22179,9 @@ "dev": true }, "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, "yargs": { @@ -42068,9 +22191,9 @@ "dev": true }, "yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true }, "yargs-unparser": { @@ -42079,28 +22202,16 @@ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" + "camelcase": "6.2.0", + "decamelize": "4.0.0", + "flat": "5.0.2", + "is-plain-obj": "2.1.0" }, "dependencies": { "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "dev": true } } @@ -42111,9 +22222,9 @@ "integrity": "sha1-V/RQULgu/VcYKzlzxUqgXLXSUjA=", "dev": true, "requires": { - "cac": "^3.0.3", - "chalk": "^1.1.3", - "cross-spawn": "^4.0.2" + "cac": "3.0.4", + "chalk": "1.1.3", + "cross-spawn": "4.0.2" }, "dependencies": { "ansi-regex": { @@ -42134,31 +22245,11 @@ "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" - } - }, - "cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "strip-ansi": { @@ -42167,7 +22258,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "supports-color": { @@ -42175,21 +22266,6 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true } } }, @@ -42199,8 +22275,8 @@ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "dev": true, "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "buffer-crc32": "0.2.13", + "fd-slicer": "1.1.0" } }, "yocto-queue": { @@ -42215,22 +22291,9 @@ "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", "dev": true, "requires": { - "archiver-utils": "^2.1.0", - "compress-commons": "^4.1.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "archiver-utils": "2.1.0", + "compress-commons": "4.1.1", + "readable-stream": "3.6.0" } }, "zwitch": { diff --git a/package.json b/package.json index f2d282c77aa..72c529eab4a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "6.24.0-pre", + "version": "5.11.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { @@ -11,16 +11,6 @@ "type": "git", "url": "https://github.com/prebid/Prebid.js.git" }, - "sideEffects": [ - "src/prebid.js", - "modules/*.js", - "modules/*/index.js" - ], - "browserslist": [ - "> 0.25%", - "not IE 11", - "not op_mini all" - ], "keywords": [ "advertising", "auction", @@ -34,21 +24,18 @@ "node": ">=8.9.0" }, "devDependencies": { - "@babel/core": "^7.16.7", - "@babel/eslint-parser": "^7.16.5", - "@babel/preset-env": "^7.16.8", + "@babel/core": "^7.8.4", + "@babel/preset-env": "^7.8.4", "@jsdevtools/coverage-istanbul-loader": "^3.0.3", - "@wdio/browserstack-service": "^7.16.0", + "@wdio/browserstack-service": "^6.1.4", "@wdio/cli": "^7.5.2", "@wdio/concise-reporter": "^7.5.2", "@wdio/local-runner": "^7.5.2", "@wdio/mocha-framework": "^7.5.2", - "@wdio/spec-reporter": "^7.19.0", + "@wdio/spec-reporter": "^7.5.2", "@wdio/sync": "^7.5.2", - "ajv": "6.12.3", - "assert": "^2.0.0", + "ajv": "5.5.2", "babel-loader": "^8.0.5", - "babel-register": "^6.26.0", "body-parser": "^1.19.0", "chai": "^4.2.0", "coveralls": "^3.1.0", @@ -99,7 +86,7 @@ "karma-sinon": "^1.0.5", "karma-sourcemap-loader": "^0.3.7", "karma-spec-reporter": "^0.0.32", - "karma-webpack": "^5.0.0", + "karma-webpack": "^3.0.5", "lodash": "^4.17.21", "mocha": "^5.0.0", "morgan": "^1.10.0", @@ -107,12 +94,11 @@ "resolve-from": "^5.0.0", "sinon": "^4.1.3", "through2": "^4.0.2", - "url": "^0.11.0", "url-parse": "^1.0.5", "webdriverio": "^7.6.1", - "webpack": "^5.70.0", - "webpack-bundle-analyzer": "^4.5.0", - "webpack-stream": "^7.0.0", + "webpack": "^3.0.0", + "webpack-bundle-analyzer": "^3.8.0", + "webpack-stream": "^3.2.0", "yargs": "^1.3.1" }, "dependencies": { @@ -126,9 +112,6 @@ "express": "^4.15.4", "fun-hooks": "^0.9.9", "just-clone": "^1.0.2", - "live-connect-js": "2.3.1" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "live-connect-js": "2.0.0" } } diff --git a/plugins/RequireEnsureWithoutJsonp.js b/plugins/RequireEnsureWithoutJsonp.js new file mode 100644 index 00000000000..c15af360e56 --- /dev/null +++ b/plugins/RequireEnsureWithoutJsonp.js @@ -0,0 +1,23 @@ +/** + * RequireEnsureWithoutJsonp + * + * This plugin redefines the behavior of require.ensure that is used by webpack to load chunks. Usually require.ensure + * includes code that allows the asynchronous loading of webpack chunks through jsonp requests AND includes a manifest + * of all the build chunks so that they can be requested by name (e.g. require.ensure('./module.js'). Since that + * functionality is not required and we plan on loading all of our chunks manually (either by concatenating all the + * files together or including as individual scripts) we don't want the overhead of including that loading code or the + * file manifest. In this plugin, that code is replaced with an error message if a module is requested that hasn't been + * loaded manually. + * + * @constructor + */ +function RequireEnsureWithoutJsonp() {} +RequireEnsureWithoutJsonp.prototype.apply = function(compiler) { + compiler.plugin('compilation', function(compilation) { + compilation.mainTemplate.plugin('require-ensure', function(_, chunk, hash) { + return ''; + }); + }); +}; + +module.exports = RequireEnsureWithoutJsonp; diff --git a/plugins/pbjsGlobals.js b/plugins/pbjsGlobals.js index 79dafd1e8b2..bf3c9033ee6 100644 --- a/plugins/pbjsGlobals.js +++ b/plugins/pbjsGlobals.js @@ -1,13 +1,11 @@ let t = require('@babel/core').types; let prebid = require('../package.json'); -const path = require('path'); module.exports = function(api, options) { - const pbGlobal = options.globalVarName || prebid.globalVarName; let replace = { '$prebid.version$': prebid.version, - '$$PREBID_GLOBAL$$': pbGlobal, + '$$PREBID_GLOBAL$$': options.globalVarName || prebid.globalVarName, '$$REPO_AND_VERSION$$': `${prebid.repository.url.split('/')[3]}_prebid_${prebid.version}` }; @@ -15,33 +13,8 @@ module.exports = function(api, options) { '$$REPO_AND_VERSION$$' ]; - const PREBID_ROOT = path.resolve(__dirname, '..'); - - function getModuleName(filename) { - const modPath = path.parse(path.relative(PREBID_ROOT, filename)); - if (modPath.ext.toLowerCase() !== '.js') { - return null; - } - if (modPath.dir === 'modules') { - // modules/moduleName.js -> moduleName - return modPath.name; - } - if (modPath.name.toLowerCase() === 'index' && path.dirname(modPath.dir) === 'modules') { - // modules/moduleName/index.js -> moduleName - return path.basename(modPath.dir); - } - return null; - } - return { visitor: { - Program(path, state) { - const modName = getModuleName(state.filename); - if (modName != null) { - // append "registration" of module file to $$PREBID_GLOBAL$$.installedModules - path.node.body.push(...api.parse(`window.${pbGlobal}.installedModules.push('${modName}');`, {filename: state.filename}).program.body); - } - }, StringLiteral(path) { Object.keys(replace).forEach(name => { if (path.node.value.includes(name)) { diff --git a/src/AnalyticsAdapter.js b/src/AnalyticsAdapter.js index 6bed0d4cd6c..97513b80cc7 100644 --- a/src/AnalyticsAdapter.js +++ b/src/AnalyticsAdapter.js @@ -1,8 +1,8 @@ import CONSTANTS from './constants.json'; import { ajax } from './ajax.js'; -import { logMessage, _each } from './utils.js'; const events = require('./events.js'); +const utils = require('./utils.js'); const { EVENTS: { @@ -20,8 +20,7 @@ const { AD_RENDER_FAILED, AD_RENDER_SUCCEEDED, AUCTION_DEBUG, - ADD_AD_UNITS, - BILLABLE_EVENT + ADD_AD_UNITS } } = CONSTANTS; @@ -118,29 +117,28 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } [AD_RENDER_SUCCEEDED]: args => this.enqueue({ eventType: AD_RENDER_SUCCEEDED, args }), [AUCTION_DEBUG]: args => this.enqueue({ eventType: AUCTION_DEBUG, args }), [ADD_AD_UNITS]: args => this.enqueue({ eventType: ADD_AD_UNITS, args }), - [BILLABLE_EVENT]: args => this.enqueue({ eventType: BILLABLE_EVENT, args }), [AUCTION_INIT]: args => { args.config = typeof config === 'object' ? config.options || {} : {}; // enableAnaltyics configuration object this.enqueue({ eventType: AUCTION_INIT, args }); } }; - _each(_handlers, (handler, event) => { + utils._each(_handlers, (handler, event) => { events.on(event, handler); }); } else { - logMessage(`Analytics adapter for "${global}" disabled by sampling`); + utils.logMessage(`Analytics adapter for "${global}" disabled by sampling`); } // finally set this function to return log message, prevents multiple adapter listeners this._oldEnable = this.enableAnalytics; this.enableAnalytics = function _enable() { - return logMessage(`Analytics adapter for "${global}" already enabled, unnecessary call to \`enableAnalytics\`.`); + return utils.logMessage(`Analytics adapter for "${global}" already enabled, unnecessary call to \`enableAnalytics\`.`); }; } function _disable() { - _each(_handlers, (handler, event) => { + utils._each(_handlers, (handler, event) => { events.off(event, handler); }); this.enableAnalytics = this._oldEnable ? this._oldEnable : _enable; @@ -160,6 +158,6 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } _enableCheck = false; } - logMessage(`event count sent to ${global}: ${_eventCount}`); + utils.logMessage(`event count sent to ${global}: ${_eventCount}`); } } diff --git a/src/Renderer.js b/src/Renderer.js index f26a5a377c0..c997658b30b 100644 --- a/src/Renderer.js +++ b/src/Renderer.js @@ -1,8 +1,6 @@ import { loadExternalScript } from './adloader.js'; -import { - logError, logWarn, logMessage, deepAccess -} from './utils.js'; -import {find} from './polyfill.js'; +import * as utils from './utils.js'; +import find from 'core-js-pure/features/array/find.js'; const moduleCode = 'outstream'; /** @@ -27,7 +25,7 @@ export function Renderer(options) { this.cmd = []; this.push = func => { if (typeof func !== 'function') { - logError('Commands given to Renderer.push must be wrapped in a function'); + utils.logError('Commands given to Renderer.push must be wrapped in a function'); return; } this.loaded ? func.call() : this.cmd.push(func); @@ -46,16 +44,16 @@ export function Renderer(options) { if (this._render) { this._render.apply(this, renderArgs) } else { - logWarn(`No render function was provided, please use .setRender on the renderer`); + utils.logWarn(`No render function was provided, please use .setRender on the renderer`); } } if (!isRendererPreferredFromAdUnit(adUnitCode)) { // we expect to load a renderer url once only so cache the request to load script this.cmd.unshift(runRender) // should render run first ? - loadExternalScript(url, moduleCode, this.callback, this.documentContext); + loadExternalScript(url, moduleCode, this.callback); } else { - logWarn(`External Js not loaded by Renderer since renderer url and callback is already defined on adUnit ${adUnitCode}`); + utils.logWarn(`External Js not loaded by Renderer since renderer url and callback is already defined on adUnit ${adUnitCode}`); runRender() } }.bind(this) // bind the function to this object to avoid 'this' errors @@ -82,7 +80,7 @@ Renderer.prototype.handleVideoEvent = function({ id, eventName }) { this.handlers[eventName](); } - logMessage(`Prebid Renderer event for id ${id} type ${eventName}`); + utils.logMessage(`Prebid Renderer event for id ${id} type ${eventName}`); }; /* @@ -94,7 +92,7 @@ Renderer.prototype.process = function() { try { this.cmd.shift().call(); } catch (error) { - logError('Error processing Renderer command: ', error); + utils.logError('Error processing Renderer command: ', error); } } }; @@ -112,18 +110,9 @@ export function isRendererRequired(renderer) { * Render the bid returned by the adapter * @param {Object} renderer Renderer object installed by adapter * @param {Object} bid Bid response - * @param {Document} doc context document of bid */ -export function executeRenderer(renderer, bid, doc) { - let docContext = null; - if (renderer.config && renderer.config.documentResolver) { - docContext = renderer.config.documentResolver(bid, document, doc);// a user provided callback, which should return a Document, and expect the parameters; bid, sourceDocument, renderDocument - } - if (!docContext) { - docContext = document; - } - renderer.documentContext = docContext; - renderer.render(bid, renderer.documentContext); +export function executeRenderer(renderer, bid) { + renderer.render(bid); } function isRendererPreferredFromAdUnit(adUnitCode) { @@ -137,11 +126,11 @@ function isRendererPreferredFromAdUnit(adUnitCode) { } // renderer defined at adUnit level - const adUnitRenderer = deepAccess(adUnit, 'renderer'); + const adUnitRenderer = utils.deepAccess(adUnit, 'renderer'); const hasValidAdUnitRenderer = !!(adUnitRenderer && adUnitRenderer.url && adUnitRenderer.render); // renderer defined at adUnit.mediaTypes level - const mediaTypeRenderer = deepAccess(adUnit, 'mediaTypes.video.renderer'); + const mediaTypeRenderer = utils.deepAccess(adUnit, 'mediaTypes.video.renderer'); const hasValidMediaTypeRenderer = !!(mediaTypeRenderer && mediaTypeRenderer.url && mediaTypeRenderer.render) return !!( diff --git a/src/adRendering.js b/src/adRendering.js deleted file mode 100644 index a645ec77244..00000000000 --- a/src/adRendering.js +++ /dev/null @@ -1,38 +0,0 @@ -import {logError} from './utils.js'; -import * as events from './events.js'; -import CONSTANTS from './constants.json'; - -const {AD_RENDER_FAILED, AD_RENDER_SUCCEEDED} = CONSTANTS.EVENTS; - -/** - * Emit the AD_RENDER_FAILED event. - * - * @param reason one of the values in CONSTANTS.AD_RENDER_FAILED_REASON - * @param message failure description - * @param bid? bid response object that failed to render - * @param id? adId that failed to render - */ -export function emitAdRenderFail({ reason, message, bid, id }) { - const data = { reason, message }; - if (bid) data.bid = bid; - if (id) data.adId = id; - - logError(message); - events.emit(AD_RENDER_FAILED, data); -} - -/** - * Emit the AD_RENDER_SUCCEEDED event. - * - * @param doc document object that was used to `.write` the ad. Should be `null` if unavailable (e.g. for documents in - * a cross-origin frame). - * @param bid bid response object for the ad that was rendered - * @param id adId that was rendered. - */ -export function emitAdRenderSucceeded({ doc, bid, id }) { - const data = { doc }; - if (bid) data.bid = bid; - if (id) data.adId = id; - - events.emit(AD_RENDER_SUCCEEDED, data); -} diff --git a/src/adapterManager.js b/src/adapterManager.js index 93eeba51cde..5f8f2e5721c 100644 --- a/src/adapterManager.js +++ b/src/adapterManager.js @@ -1,44 +1,21 @@ /** @module adaptermanger */ -import { - _each, - bind, - deepAccess, - deepClone, - flatten, - generateUUID, - getBidderCodes, - getDefinedParams, - getUniqueIdentifierStr, - getUserConfiguredParams, - groupBy, - isArray, - isValidMediaTypes, - logError, - logInfo, - logMessage, - logWarn, - shuffle, - timestamp, -} from './utils.js'; -import {processAdUnitsForLabels} from './sizeMapping.js'; -import { decorateAdUnitsWithNativeParams, nativeAdapters } from './native.js'; +import { flatten, getBidderCodes, getDefinedParams, shuffle, timestamp, getBidderRequest, bind } from './utils.js'; +import { getLabels, resolveStatus } from './sizeMapping.js'; +import { processNativeAdUnitParams, nativeAdapters } from './native.js'; import { newBidder } from './adapters/bidderFactory.js'; import { ajaxBuilder } from './ajax.js'; import { config, RANDOM } from './config.js'; import { hook } from './hook.js'; -import {includes, find} from './polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import find from 'core-js-pure/features/array/find.js'; import { adunitCounter } from './adUnits.js'; import { getRefererInfo } from './refererDetection.js'; -import {GdprConsentHandler, UspConsentHandler} from './consentHandler.js'; - -export const PARTITIONS = { - CLIENT: 'client', - SERVER: 'server' -} +var utils = require('./utils.js'); var CONSTANTS = require('./constants.json'); var events = require('./events.js'); +let s2sTestingModule; // store s2sTesting module if it's loaded let adapterManager = {}; @@ -48,7 +25,7 @@ let _aliasRegistry = adapterManager.aliasRegistry = {}; let _s2sConfigs = []; config.getConfig('s2sConfig', config => { if (config && config.s2sConfig) { - _s2sConfigs = isArray(config.s2sConfig) ? config.s2sConfig : [config.s2sConfig]; + _s2sConfigs = Array.isArray(config.s2sConfig) ? config.s2sConfig : [config.s2sConfig]; } }); @@ -61,78 +38,101 @@ var _analyticsRegistry = {}; * @property {Array} activeLabels the labels specified as being active by requestBids */ -function getBids({bidderCode, auctionId, bidderRequestId, adUnits, src}) { +function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels, src}) { return adUnits.reduce((result, adUnit) => { - result.push(adUnit.bids.filter(bid => bid.bidder === bidderCode) - .reduce((bids, bid) => { - bid = Object.assign({}, bid, getDefinedParams(adUnit, [ - 'nativeParams', - 'ortb2Imp', - 'mediaType', - 'renderer', - 'storedAuctionResponse' - ])); - - const mediaTypes = bid.mediaTypes == null ? adUnit.mediaTypes : bid.mediaTypes - - if (isValidMediaTypes(mediaTypes)) { - bid = Object.assign({}, bid, { - mediaTypes - }); - } else { - logError( - `mediaTypes is not correctly configured for adunit ${adUnit.code}` - ); - } - - bids.push(Object.assign({}, bid, { - adUnitCode: adUnit.code, - transactionId: adUnit.transactionId, - sizes: deepAccess(mediaTypes, 'banner.sizes') || deepAccess(mediaTypes, 'video.playerSize') || [], - bidId: bid.bid_id || getUniqueIdentifierStr(), - bidderRequestId, - auctionId, - src, - bidRequestsCount: adunitCounter.getRequestsCounter(adUnit.code), - bidderRequestsCount: adunitCounter.getBidderRequestsCounter(adUnit.code, bid.bidder), - bidderWinsCount: adunitCounter.getBidderWinsCounter(adUnit.code, bid.bidder), - })); - return bids; - }, []) + let { + active, + mediaTypes: filteredMediaTypes, + filterResults + } = resolveStatus( + getLabels(adUnit, labels), + adUnit.mediaTypes, + adUnit.sizes ); + + if (!active) { + utils.logInfo(`Size mapping disabled adUnit "${adUnit.code}"`); + } else if (filterResults) { + utils.logInfo(`Size mapping filtered adUnit "${adUnit.code}" banner sizes from `, filterResults.before, 'to ', filterResults.after); + } + + if (active) { + result.push(adUnit.bids.filter(bid => bid.bidder === bidderCode) + .reduce((bids, bid) => { + const nativeParams = + adUnit.nativeParams || utils.deepAccess(adUnit, 'mediaTypes.native'); + if (nativeParams) { + bid = Object.assign({}, bid, { + nativeParams: processNativeAdUnitParams(nativeParams), + }); + } + + bid = Object.assign({}, bid, getDefinedParams(adUnit, [ + 'ortb2Imp', + 'mediaType', + 'renderer', + 'storedAuctionResponse' + ])); + + let { + active, + mediaTypes, + filterResults + } = resolveStatus(getLabels(bid, labels), filteredMediaTypes); + + if (!active) { + utils.logInfo(`Size mapping deactivated adUnit "${adUnit.code}" bidder "${bid.bidder}"`); + } else if (filterResults) { + utils.logInfo(`Size mapping filtered adUnit "${adUnit.code}" bidder "${bid.bidder}" banner sizes from `, filterResults.before, 'to ', filterResults.after); + } + + if (utils.isValidMediaTypes(mediaTypes)) { + bid = Object.assign({}, bid, { + mediaTypes + }); + } else { + utils.logError( + `mediaTypes is not correctly configured for adunit ${adUnit.code}` + ); + } + + if (active) { + bids.push(Object.assign({}, bid, { + adUnitCode: adUnit.code, + transactionId: adUnit.transactionId, + sizes: utils.deepAccess(mediaTypes, 'banner.sizes') || utils.deepAccess(mediaTypes, 'video.playerSize') || [], + bidId: bid.bid_id || utils.getUniqueIdentifierStr(), + bidderRequestId, + auctionId, + src, + bidRequestsCount: adunitCounter.getRequestsCounter(adUnit.code), + bidderRequestsCount: adunitCounter.getBidderRequestsCounter(adUnit.code, bid.bidder), + bidderWinsCount: adunitCounter.getBidderWinsCounter(adUnit.code, bid.bidder), + })); + } + return bids; + }, []) + ); + } return result; }, []).reduce(flatten, []).filter(val => val !== ''); } const hookedGetBids = hook('sync', getBids, 'getBids'); -/** - * Filter an adUnit's bids for building client and/or server requests - * - * @param bids an array of bids as defined in an adUnit - * @param s2sConfig null if the adUnit is being routed to a client adapter; otherwise the s2s adapter's config - * @returns the subset of `bids` that are pertinent for the given `s2sConfig` - */ -export function _filterBidsForAdUnit(bids, s2sConfig, {getS2SBidders = getS2SBidderSet} = {}) { - if (s2sConfig == null) { - return bids; - } else { - const serverBidders = getS2SBidders(s2sConfig); - return bids.filter((bid) => serverBidders.has(bid.bidder)) - } -} -export const filterBidsForAdUnit = hook('sync', _filterBidsForAdUnit, 'filterBidsForAdUnit'); - function getAdUnitCopyForPrebidServer(adUnits, s2sConfig) { - let adUnitsCopy = deepClone(adUnits); + let adaptersServerSide = s2sConfig.bidders; + let adUnitsCopy = utils.deepClone(adUnits); adUnitsCopy.forEach((adUnit) => { // filter out client side bids - adUnit.bids = filterBidsForAdUnit(adUnit.bids, s2sConfig) - .map((bid) => { - bid.bid_id = getUniqueIdentifierStr(); - return bid; - }); + adUnit.bids = adUnit.bids.filter((bid) => { + return includes(adaptersServerSide, bid.bidder) && + (!doingS2STesting(s2sConfig) || bid.finalSource !== s2sTestingModule.CLIENT); + }).map((bid) => { + bid.bid_id = utils.getUniqueIdentifierStr(); + return bid; + }); }); // don't send empty requests @@ -143,9 +143,12 @@ function getAdUnitCopyForPrebidServer(adUnits, s2sConfig) { } function getAdUnitCopyForClientAdapters(adUnits) { - let adUnitsClientCopy = deepClone(adUnits); + let adUnitsClientCopy = utils.deepClone(adUnits); + // filter out s2s bids adUnitsClientCopy.forEach((adUnit) => { - adUnit.bids = filterBidsForAdUnit(adUnit.bids, null); + adUnit.bids = adUnit.bids.filter((bid) => { + return !clientTestAdapters.length || bid.finalSource !== s2sTestingModule.SERVER; + }) }); // don't send empty requests @@ -156,8 +159,25 @@ function getAdUnitCopyForClientAdapters(adUnits) { return adUnitsClientCopy; } -export let gdprDataHandler = new GdprConsentHandler(); -export let uspDataHandler = new UspConsentHandler(); +export let gdprDataHandler = { + consentData: null, + setConsentData: function(consentInfo) { + gdprDataHandler.consentData = consentInfo; + }, + getConsentData: function() { + return gdprDataHandler.consentData; + } +}; + +export let uspDataHandler = { + consentData: null, + setConsentData: function(consentInfo) { + uspDataHandler.consentData = consentInfo; + }, + getConsentData: function() { + return uspDataHandler.consentData; + } +}; export let coppaDataHandler = { getCoppa: function() { @@ -165,80 +185,89 @@ export let coppaDataHandler = { } }; -/** - * Filter and/or modify media types for ad units based on the given labels. - * - * This should return adUnits that are active for the given labels, modified to have their `mediaTypes` - * conform to size mapping configuration. If different bids for the same adUnit should use different `mediaTypes`, - * they should be exposed under `adUnit.bids[].mediaTypes`. - */ -export const setupAdUnitMediaTypes = hook('sync', (adUnits, labels) => { - return processAdUnitsForLabels(adUnits, labels); -}, 'setupAdUnitMediaTypes') - -/** - * @param {{}|Array<{}>} s2sConfigs - * @returns {Set} a set of all the bidder codes that should be routed through the S2S adapter(s) - * as defined in `s2sConfigs` - */ -export function getS2SBidderSet(s2sConfigs) { - if (!isArray(s2sConfigs)) s2sConfigs = [s2sConfigs]; - // `null` represents the "no bid bidder" - when an ad unit is meant only for S2S adapters, like stored impressions - const serverBidders = new Set([null]); - s2sConfigs.filter((s2s) => s2s && s2s.enabled) - .flatMap((s2s) => s2s.bidders) - .forEach((bidder) => serverBidders.add(bidder)); - return serverBidders; -} +// export for testing +export let clientTestAdapters = []; +export const allS2SBidders = []; -/** - * @returns {{[PARTITIONS.CLIENT]: Array, [PARTITIONS.SERVER]: Array}} - * All the bidder codes in the given `adUnits`, divided in two arrays - - * those that should be routed to client, and server adapters (according to the configuration in `s2sConfigs`). - */ -export function _partitionBidders (adUnits, s2sConfigs, {getS2SBidders = getS2SBidderSet} = {}) { - const serverBidders = getS2SBidders(s2sConfigs); - return getBidderCodes(adUnits).reduce((memo, bidder) => { - const partition = serverBidders.has(bidder) ? PARTITIONS.SERVER : PARTITIONS.CLIENT; - memo[partition].push(bidder); - return memo; - }, {[PARTITIONS.CLIENT]: [], [PARTITIONS.SERVER]: []}) +export function getAllS2SBidders() { + adapterManager.s2STestingEnabled = false; + _s2sConfigs.forEach(s2sConfig => { + if (s2sConfig && s2sConfig.enabled) { + if (s2sConfig.bidders && s2sConfig.bidders.length) { + allS2SBidders.push(...s2sConfig.bidders); + } + } + }) } -export const partitionBidders = hook('sync', _partitionBidders, 'partitionBidders'); - adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, auctionId, cbTimeout, labels) { /** * emit and pass adunits for external modification * @see {@link https://github.com/prebid/Prebid.js/issues/4149|Issue} */ events.emit(CONSTANTS.EVENTS.BEFORE_REQUEST_BIDS, adUnits); - decorateAdUnitsWithNativeParams(adUnits); - adUnits = setupAdUnitMediaTypes(adUnits, labels); - - let {[PARTITIONS.CLIENT]: clientBidders, [PARTITIONS.SERVER]: serverBidders} = partitionBidders(adUnits, _s2sConfigs); + let bidderCodes = getBidderCodes(adUnits); if (config.getConfig('bidderSequence') === RANDOM) { - clientBidders = shuffle(clientBidders); + bidderCodes = shuffle(bidderCodes); } const refererInfo = getRefererInfo(); + let clientBidderCodes = bidderCodes; + let bidRequests = []; + if (allS2SBidders.length === 0) { + getAllS2SBidders(); + } + _s2sConfigs.forEach(s2sConfig => { if (s2sConfig && s2sConfig.enabled) { - let adUnitsS2SCopy = getAdUnitCopyForPrebidServer(adUnits, s2sConfig); + if (doingS2STesting(s2sConfig)) { + s2sTestingModule.calculateBidSources(s2sConfig); + const bidderMap = s2sTestingModule.getSourceBidderMap(adUnits, allS2SBidders); + // get all adapters doing client testing + bidderMap[s2sTestingModule.CLIENT].forEach(bidder => { + if (!includes(clientTestAdapters, bidder)) { + clientTestAdapters.push(bidder); + } + }) + } + } + }) + + // don't call these client side (unless client request is needed for testing) + clientBidderCodes = bidderCodes.filter(bidderCode => { + return !includes(allS2SBidders, bidderCode) || includes(clientTestAdapters, bidderCode) + }); + + // these are called on the s2s adapter + let adaptersServerSide = allS2SBidders; + + const adUnitsContainServerRequests = (adUnits, s2sConfig) => Boolean( + find(adUnits, adUnit => find(adUnit.bids, bid => ( + bid.bidSource || + (s2sConfig.bidderControl && s2sConfig.bidderControl[bid.bidder]) + ) && bid.finalSource === s2sTestingModule.SERVER)) + ); - // uniquePbsTid is so we know which server to send which bids to during the callBids function - let uniquePbsTid = generateUUID(); - serverBidders.forEach(bidderCode => { - const bidderRequestId = getUniqueIdentifierStr(); + _s2sConfigs.forEach(s2sConfig => { + if (s2sConfig && s2sConfig.enabled) { + if ((isTestingServerOnly(s2sConfig) && adUnitsContainServerRequests(adUnits, s2sConfig))) { + utils.logWarn('testServerOnly: True. All client requests will be suppressed.'); + clientBidderCodes.length = 0; + } + + let adUnitsS2SCopy = getAdUnitCopyForPrebidServer(adUnits, s2sConfig); + let tid = utils.generateUUID(); + adaptersServerSide.forEach(bidderCode => { + const bidderRequestId = utils.getUniqueIdentifierStr(); const bidderRequest = { bidderCode, auctionId, bidderRequestId, - uniquePbsTid, - bids: hookedGetBids({bidderCode, auctionId, bidderRequestId, 'adUnits': deepClone(adUnitsS2SCopy), src: CONSTANTS.S2S.SRC}), + tid, + bids: hookedGetBids({bidderCode, auctionId, bidderRequestId, 'adUnits': utils.deepClone(adUnitsS2SCopy), labels, src: CONSTANTS.S2S.SRC}), auctionStart: auctionStart, timeout: s2sConfig.timeout, src: CONSTANTS.S2S.SRC, @@ -268,20 +297,20 @@ adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, a // client adapters let adUnitsClientCopy = getAdUnitCopyForClientAdapters(adUnits); - clientBidders.forEach(bidderCode => { - const bidderRequestId = getUniqueIdentifierStr(); + clientBidderCodes.forEach(bidderCode => { + const bidderRequestId = utils.getUniqueIdentifierStr(); const bidderRequest = { bidderCode, auctionId, bidderRequestId, - bids: hookedGetBids({bidderCode, auctionId, bidderRequestId, 'adUnits': deepClone(adUnitsClientCopy), labels, src: 'client'}), + bids: hookedGetBids({bidderCode, auctionId, bidderRequestId, 'adUnits': utils.deepClone(adUnitsClientCopy), labels, src: 'client'}), auctionStart: auctionStart, timeout: cbTimeout, refererInfo }; const adapter = _bidderRegistry[bidderCode]; if (!adapter) { - logError(`Trying to make a request for bidder that does not exist: ${bidderCode}`); + utils.logError(`Trying to make a request for bidder that does not exist: ${bidderCode}`); } if (adapter && bidderRequest.bids && bidderRequest.bids.length !== 0) { @@ -305,7 +334,7 @@ adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, a adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbacks, requestBidsTimeout, onTimelyResponse) => { if (!bidRequests.length) { - logWarn('callBids executed with no bidRequests. Were they filtered by labels or sizing?'); + utils.logWarn('callBids executed with no bidRequests. Were they filtered by labels or sizing?'); return; } @@ -318,7 +347,7 @@ adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, request serverBidRequests.forEach(serverBidRequest => { var index = -1; for (var i = 0; i < uniqueServerBidRequests.length; ++i) { - if (serverBidRequest.uniquePbsTid === uniqueServerBidRequests[i].uniquePbsTid) { + if (serverBidRequest.tid === uniqueServerBidRequests[i].tid) { index = i; break; } @@ -328,12 +357,9 @@ adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, request } }); - let counter = 0; - - // $.source.tid MUST be a unique UUID and also THE SAME between all PBS Requests for a given Auction - const sourceTid = generateUUID(); + let counter = 0 _s2sConfigs.forEach((s2sConfig) => { - if (s2sConfig && uniqueServerBidRequests[counter] && getS2SBidderSet(s2sConfig).has(uniqueServerBidRequests[counter].bidderCode)) { + if (s2sConfig && uniqueServerBidRequests[counter] && includes(s2sConfig.bidders, uniqueServerBidRequests[counter].bidderCode)) { // s2s should get the same client side timeout as other client side requests. const s2sAjax = ajaxBuilder(requestBidsTimeout, requestCallbacks ? { request: requestCallbacks.request.bind(null, 's2s'), @@ -341,39 +367,46 @@ adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, request } : undefined); let adaptersServerSide = s2sConfig.bidders; const s2sAdapter = _bidderRegistry[s2sConfig.adapter]; - let uniquePbsTid = uniqueServerBidRequests[counter].uniquePbsTid; + let tid = uniqueServerBidRequests[counter].tid; let adUnitsS2SCopy = uniqueServerBidRequests[counter].adUnitsS2SCopy; - let uniqueServerRequests = serverBidRequests.filter(serverBidRequest => serverBidRequest.uniquePbsTid === uniquePbsTid); + let uniqueServerRequests = serverBidRequests.filter(serverBidRequest => serverBidRequest.tid === tid) if (s2sAdapter) { - let s2sBidRequest = {tid: sourceTid, 'ad_units': adUnitsS2SCopy, s2sConfig}; + let s2sBidRequest = {tid, 'ad_units': adUnitsS2SCopy, s2sConfig}; if (s2sBidRequest.ad_units.length) { let doneCbs = uniqueServerRequests.map(bidRequest => { bidRequest.start = timestamp(); return doneCb.bind(bidRequest); }); - const bidders = getBidderCodes(s2sBidRequest.ad_units).filter((bidder) => adaptersServerSide.includes(bidder)); - logMessage(`CALLING S2S HEADER BIDDERS ==== ${bidders.length > 0 ? bidders.join(', ') : 'No bidder specified, using "ortb2Imp" definition(s) only'}`); + // only log adapters that actually have adUnit bids + let allBidders = s2sBidRequest.ad_units.reduce((adapters, adUnit) => { + return adapters.concat((adUnit.bids || []).reduce((adapters, bid) => adapters.concat(bid.bidder), [])); + }, []); + utils.logMessage(`CALLING S2S HEADER BIDDERS ==== ${adaptersServerSide.filter(adapter => includes(allBidders, adapter)).join(',')}`); // fire BID_REQUESTED event for each s2s bidRequest uniqueServerRequests.forEach(bidRequest => { - // add the new sourceTid - events.emit(CONSTANTS.EVENTS.BID_REQUESTED, {...bidRequest, tid: sourceTid}); + events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidRequest); }); // make bid requests s2sAdapter.callBids( s2sBidRequest, serverBidRequests, - addBidResponse, + (adUnitCode, bid) => { + let bidderRequest = getBidderRequest(serverBidRequests, bid.bidderCode, adUnitCode); + if (bidderRequest) { + addBidResponse.call(bidderRequest, adUnitCode, bid) + } + }, () => doneCbs.forEach(done => done()), s2sAjax ); } } else { - logError('missing ' + s2sConfig.adapter); + utils.logError('missing ' + s2sConfig.adapter); } counter++ } @@ -385,7 +418,7 @@ adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, request // TODO : Do we check for bid in pool from here and skip calling adapter again ? const adapter = _bidderRegistry[bidRequest.bidderCode]; config.runWithBidder(bidRequest.bidderCode, () => { - logMessage(`CALLING BIDDER`); + utils.logMessage(`CALLING BIDDER`); events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidRequest); }); let ajax = ajaxBuilder(requestBidsTimeout, requestCallbacks ? { @@ -400,7 +433,7 @@ adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, request adapter.callBids, adapter, bidRequest, - addBidResponse, + addBidResponse.bind(bidRequest), adapterDone, ajax, onTimelyResponse, @@ -408,12 +441,20 @@ adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, request ) ); } catch (e) { - logError(`${bidRequest.bidderCode} Bid Adapter emitted an uncaught error when parsing their bidRequest`, {e, bidRequest}); + utils.logError(`${bidRequest.bidderCode} Bid Adapter emitted an uncaught error when parsing their bidRequest`, {e, bidRequest}); adapterDone(); } }); }; +function doingS2STesting(s2sConfig) { + return s2sConfig && s2sConfig.enabled && s2sConfig.testing && s2sTestingModule; +} + +function isTestingServerOnly(s2sConfig) { + return Boolean(doingS2STesting(s2sConfig) && s2sConfig.testServerOnly); +}; + function getSupportedMediaTypes(bidderCode) { let supportedMediaTypes = []; if (includes(adapterManager.videoAdapters, bidderCode)) supportedMediaTypes.push('video'); @@ -435,10 +476,10 @@ adapterManager.registerBidAdapter = function (bidAdapter, bidderCode, {supported nativeAdapters.push(bidderCode); } } else { - logError('Bidder adaptor error for bidder code: ' + bidderCode + 'bidder must implement a callBids() function'); + utils.logError('Bidder adaptor error for bidder code: ' + bidderCode + 'bidder must implement a callBids() function'); } } else { - logError('bidAdapter or bidderCode not specified'); + utils.logError('bidAdapter or bidderCode not specified'); } }; @@ -461,7 +502,7 @@ adapterManager.aliasBidAdapter = function (bidderCode, alias, options) { } }); nonS2SAlias.forEach(bidderCode => { - logError('bidderCode "' + bidderCode + '" is not an existing bidder.', 'adapterManager.aliasBidAdapter'); + utils.logError('bidderCode "' + bidderCode + '" is not an existing bidder.', 'adapterManager.aliasBidAdapter'); }) } else { try { @@ -483,11 +524,11 @@ adapterManager.aliasBidAdapter = function (bidderCode, alias, options) { supportedMediaTypes }); } catch (e) { - logError(bidderCode + ' bidder does not currently support aliasing.', 'adapterManager.aliasBidAdapter'); + utils.logError(bidderCode + ' bidder does not currently support aliasing.', 'adapterManager.aliasBidAdapter'); } } } else { - logMessage('alias name "' + alias + '" has been already specified.'); + utils.logMessage('alias name "' + alias + '" has been already specified.'); } }; @@ -497,25 +538,26 @@ adapterManager.registerAnalyticsAdapter = function ({adapter, code, gvlid}) { adapter.code = code; _analyticsRegistry[code] = { adapter, gvlid }; } else { - logError(`Prebid Error: Analytics adaptor error for analytics "${code}" + utils.logError(`Prebid Error: Analytics adaptor error for analytics "${code}" analytics adapter must implement an enableAnalytics() function`); } } else { - logError('Prebid Error: analyticsAdapter or analyticsCode not specified'); + utils.logError('Prebid Error: analyticsAdapter or analyticsCode not specified'); } }; adapterManager.enableAnalytics = function (config) { - if (!isArray(config)) { + if (!utils.isArray(config)) { config = [config]; } - _each(config, adapterConfig => { - const entry = _analyticsRegistry[adapterConfig.provider]; - if (entry && entry.adapter) { - entry.adapter.enableAnalytics(adapterConfig); + utils._each(config, adapterConfig => { + var adapter = _analyticsRegistry[adapterConfig.provider].adapter; + if (adapter) { + adapter.enableAnalytics(adapterConfig); } else { - logError(`Prebid Error: no analytics adapter found in registry for '${adapterConfig.provider}'.`); + utils.logError(`Prebid Error: no analytics adapter found in registry for + ${adapterConfig.provider}.`); } }); } @@ -528,27 +570,33 @@ adapterManager.getAnalyticsAdapter = function(code) { return _analyticsRegistry[code]; } +// the s2sTesting module is injected when it's loaded rather than being imported +// importing it causes the packager to include it even when it's not explicitly included in the build +export function setS2STestingModule(module) { + s2sTestingModule = module; +} + function tryCallBidderMethod(bidder, method, param) { try { const adapter = _bidderRegistry[bidder]; const spec = adapter.getSpec(); if (spec && spec[method] && typeof spec[method] === 'function') { - logInfo(`Invoking ${bidder}.${method}`); + utils.logInfo(`Invoking ${bidder}.${method}`); config.runWithBidder(bidder, bind.call(spec[method], spec, param)); } } catch (e) { - logWarn(`Error calling ${method} of ${bidder}`); + utils.logWarn(`Error calling ${method} of ${bidder}`); } } adapterManager.callTimedOutBidders = function(adUnits, timedOutBidders, cbTimeout) { timedOutBidders = timedOutBidders.map((timedOutBidder) => { // Adding user configured params & timeout to timeout event data - timedOutBidder.params = getUserConfiguredParams(adUnits, timedOutBidder.adUnitCode, timedOutBidder.bidder); + timedOutBidder.params = utils.getUserConfiguredParams(adUnits, timedOutBidder.adUnitCode, timedOutBidder.bidder); timedOutBidder.timeout = cbTimeout; return timedOutBidder; }); - timedOutBidders = groupBy(timedOutBidders, 'bidder'); + timedOutBidders = utils.groupBy(timedOutBidders, 'bidder'); Object.keys(timedOutBidders).forEach((bidder) => { tryCallBidderMethod(bidder, 'onTimeout', timedOutBidders[bidder]); @@ -557,7 +605,7 @@ adapterManager.callTimedOutBidders = function(adUnits, timedOutBidders, cbTimeou adapterManager.callBidWonBidder = function(bidder, bid, adUnits) { // Adding user configured params to bidWon event data - bid.params = getUserConfiguredParams(adUnits, bid.adUnitCode, bid.bidder); + bid.params = utils.getUserConfiguredParams(adUnits, bid.adUnitCode, bid.bidder); adunitCounter.incrementBidderWinsCounter(bid.adUnitCode, bid.bidder); tryCallBidderMethod(bidder, 'onBidWon', bid); }; @@ -570,9 +618,4 @@ adapterManager.callBidViewableBidder = function(bidder, bid) { tryCallBidderMethod(bidder, 'onBidViewable', bid); }; -adapterManager.callBidderError = function(bidder, error, bidderRequest) { - const param = { error, bidderRequest }; - tryCallBidderMethod(bidder, 'onBidderError', param); -}; - export default adapterManager; diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 382c93b0d25..c71c4ee355b 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -6,15 +6,13 @@ import { userSync } from '../userSync.js'; import { nativeBidIsValid } from '../native.js'; import { isValidVideoBid } from '../video.js'; import CONSTANTS from '../constants.json'; -import * as events from '../events.js'; -import {includes} from '../polyfill.js'; +import events from '../events.js'; +import includes from 'core-js-pure/features/array/includes.js'; import { ajax } from '../ajax.js'; -import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, flatten, uniques, timestamp, deepAccess, isArray, isPlainObject } from '../utils.js'; +import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest, flatten, uniques, timestamp, deepAccess, isArray, isPlainObject } from '../utils.js'; import { ADPOD } from '../mediaTypes.js'; import { getHook, hook } from '../hook.js'; import { getCoreStorageManager } from '../storageManager.js'; -import {auctionManager} from '../auctionManager.js'; -import { bidderSettings } from '../bidderSettings.js'; export const storage = getCoreStorageManager('bidderFactory'); @@ -38,7 +36,6 @@ export const storage = getCoreStorageManager('bidderFactory'); * }); * * @see BidderSpec for the full API and more thorough descriptions. - * */ /** @@ -133,7 +130,7 @@ export const storage = getCoreStorageManager('bidderFactory'); */ // common params for all mediaTypes -const COMMON_BID_RESPONSE_KEYS = ['cpm', 'ttl', 'creativeId', 'netRevenue', 'currency']; +const COMMON_BID_RESPONSE_KEYS = ['requestId', 'cpm', 'ttl', 'creativeId', 'netRevenue', 'currency']; const DEFAULT_REFRESHIN_DAYS = 1; @@ -190,7 +187,7 @@ export function newBidder(spec) { const adUnitCodesHandled = {}; function addBidWithCode(adUnitCode, bid) { adUnitCodesHandled[adUnitCode] = true; - if (isValid(adUnitCode, bid)) { + if (isValid(adUnitCode, bid, [bidderRequest])) { addBidResponse(adUnitCode, bid); } } @@ -220,52 +217,132 @@ export function newBidder(spec) { } }); - processBidderRequests(spec, validBidRequests, bidderRequest, ajax, configEnabledCallback, { - onRequest: requestObject => events.emit(CONSTANTS.EVENTS.BEFORE_BIDDER_HTTP, bidderRequest, requestObject), - onResponse: (resp) => { - onTimelyResponse(spec.code); - responses.push(resp) - }, - // If the server responds with an error, there's not much we can do beside logging. - onError: (errorMessage, error) => { + let requests = spec.buildRequests(validBidRequests, bidderRequest); + if (!requests || requests.length === 0) { + afterAllResponses(); + return; + } + if (!Array.isArray(requests)) { + requests = [requests]; + } + + // Callbacks don't compose as nicely as Promises. We should call done() once _all_ the + // Server requests have returned and been processed. Since `ajax` accepts a single callback, + // we need to rig up a function which only executes after all the requests have been responded. + const onResponse = delayExecution(configEnabledCallback(afterAllResponses), requests.length) + requests.forEach(processRequest); + + function formatGetParameters(data) { + if (data) { + return `?${typeof data === 'object' ? parseQueryStringParameters(data) : data}`; + } + + return ''; + } + + function processRequest(request) { + switch (request.method) { + case 'GET': + ajax( + `${request.url}${formatGetParameters(request.data)}`, + { + success: configEnabledCallback(onSuccess), + error: onFailure + }, + undefined, + Object.assign({ + method: 'GET', + withCredentials: true + }, request.options) + ); + break; + case 'POST': + ajax( + request.url, + { + success: configEnabledCallback(onSuccess), + error: onFailure + }, + typeof request.data === 'string' ? request.data : JSON.stringify(request.data), + Object.assign({ + method: 'POST', + contentType: 'text/plain', + withCredentials: true + }, request.options) + ); + break; + default: + logWarn(`Skipping invalid request from ${spec.code}. Request type ${request.type} must be GET or POST`); + onResponse(); + } + + // If the server responds successfully, use the adapter code to unpack the Bids from it. + // If the adapter code fails, no bids should be added. After all the bids have been added, make + // sure to call the `onResponse` function so that we're one step closer to calling done(). + function onSuccess(response, responseObj) { onTimelyResponse(spec.code); - adapterManager.callBidderError(spec.code, error, bidderRequest) - events.emit(CONSTANTS.EVENTS.BIDDER_ERROR, { error, bidderRequest }); - logError(`Server call for ${spec.code} failed: ${errorMessage} ${error.status}. Continuing without bids.`); - }, - onBid: (bid) => { - const bidRequest = bidRequestMap[bid.requestId]; - if (bidRequest) { - bid.adapterCode = bidRequest.bidder; - if (isInvalidAlternateBidder(bid.bidderCode, bidRequest.bidder)) { - logWarn(`${bid.bidderCode} is not a registered partner or known bidder of ${bidRequest.bidder}, hence continuing without bid. If you wish to support this bidder, please mark allowAlternateBidderCodes as true in bidderSettings.`); - return; + + try { + response = JSON.parse(response); + } catch (e) { /* response might not be JSON... that's ok. */ } + + // Make response headers available for #1742. These are lazy-loaded because most adapters won't need them. + response = { + body: response, + headers: headerParser(responseObj) + }; + responses.push(response); + + let bids; + try { + bids = spec.interpretResponse(response, request); + } catch (err) { + logError(`Bidder ${spec.code} failed to interpret the server's response. Continuing without bids`, null, err); + onResponse(); + return; + } + + if (bids) { + if (isArray(bids)) { + bids.forEach(addBidUsingRequestMap); + } else { + addBidUsingRequestMap(bids); + } + } + onResponse(bids); + + function addBidUsingRequestMap(bid) { + const bidRequest = bidRequestMap[bid.requestId]; + if (bidRequest) { + // creating a copy of original values as cpm and currency are modified later + bid.originalCpm = bid.cpm; + bid.originalCurrency = bid.currency; + bid.meta = bid.meta || Object.assign({}, bid[bidRequest.bidder]); + const prebidBid = Object.assign(createBid(CONSTANTS.STATUS.GOOD, bidRequest), bid); + addBidWithCode(bidRequest.adUnitCode, prebidBid); + } else { + logWarn(`Bidder ${spec.code} made bid for unknown request ID: ${bid.requestId}. Ignoring.`); } - // creating a copy of original values as cpm and currency are modified later - bid.originalCpm = bid.cpm; - bid.originalCurrency = bid.currency; - bid.meta = bid.meta || Object.assign({}, bid[bidRequest.bidder]); - const prebidBid = Object.assign(createBid(CONSTANTS.STATUS.GOOD, bidRequest), bid); - addBidWithCode(bidRequest.adUnitCode, prebidBid); - } else { - logWarn(`Bidder ${spec.code} made bid for unknown request ID: ${bid.requestId}. Ignoring.`); } - }, - onCompletion: afterAllResponses, - }); - } - }); - function isInvalidAlternateBidder(responseBidder, requestBidder) { - let allowAlternateBidderCodes = bidderSettings.get(requestBidder, 'allowAlternateBidderCodes'); - let alternateBiddersList = bidderSettings.get(requestBidder, 'allowedAlternateBidderCodes'); - if (!!responseBidder && !!requestBidder && requestBidder !== responseBidder) { - if ((allowAlternateBidderCodes !== undefined && !allowAlternateBidderCodes) || (isArray(alternateBiddersList) && (alternateBiddersList[0] !== '*' && !alternateBiddersList.includes(responseBidder)))) { - return true; + function headerParser(xmlHttpResponse) { + return { + get: responseObj.getResponseHeader.bind(responseObj) + }; + } + } + + // If the server responds with an error, there's not much we can do. Log it, and make sure to + // call onResponse() so that we're one step closer to calling done(). + function onFailure(err) { + onTimelyResponse(spec.code); + + logError(`Server call for ${spec.code} failed: ${err}. Continuing without bids.`); + onResponse(); + } } } - return false; - } + }); function registerSyncs(responses, gdprConsent, uspConsent) { registerSyncInner(spec, responses, gdprConsent, uspConsent); @@ -280,125 +357,6 @@ export function newBidder(spec) { } } -/** - * Run a set of bid requests - that entails converting them to HTTP requests, sending - * them over the network, and parsing the responses. - * - * @param spec bid adapter spec - * @param bids bid requests to run - * @param bidderRequest the bid request object that `bids` is connected to - * @param ajax ajax method to use - * @param wrapCallback {function(callback)} a function used to wrap every callback (for the purpose of `config.currentBidder`) - * @param onRequest {function({})} invoked once for each HTTP request built by the adapter - with the raw request - * @param onResponse {function({})} invoked once on each successful HTTP response - with the raw response - * @param onError {function(String, {})} invoked once for each HTTP error - with status code and response - * @param onBid {function({})} invoked once for each bid in the response - with the bid as returned by interpretResponse - * @param onCompletion {function()} invoked once when all bid requests have been processed - */ -export const processBidderRequests = hook('sync', function (spec, bids, bidderRequest, ajax, wrapCallback, {onRequest, onResponse, onError, onBid, onCompletion}) { - let requests = spec.buildRequests(bids, bidderRequest); - if (!requests || requests.length === 0) { - onCompletion(); - return; - } - if (!Array.isArray(requests)) { - requests = [requests]; - } - - const requestDone = delayExecution(onCompletion, requests.length); - - requests.forEach((request) => { - // If the server responds successfully, use the adapter code to unpack the Bids from it. - // If the adapter code fails, no bids should be added. After all the bids have been added, - // make sure to call the `requestDone` function so that we're one step closer to calling onCompletion(). - const onSuccess = wrapCallback(function(response, responseObj) { - try { - response = JSON.parse(response); - } catch (e) { /* response might not be JSON... that's ok. */ } - - // Make response headers available for #1742. These are lazy-loaded because most adapters won't need them. - response = { - body: response, - headers: headerParser(responseObj) - }; - onResponse(response); - - let bids; - try { - bids = spec.interpretResponse(response, request); - } catch (err) { - logError(`Bidder ${spec.code} failed to interpret the server's response. Continuing without bids`, null, err); - requestDone(); - return; - } - - if (bids) { - if (isArray(bids)) { - bids.forEach(onBid); - } else { - onBid(bids); - } - } - requestDone(); - - function headerParser(xmlHttpResponse) { - return { - get: responseObj.getResponseHeader.bind(responseObj) - }; - } - }); - - const onFailure = wrapCallback(function (errorMessage, error) { - onError(errorMessage, error); - requestDone(); - }); - - onRequest(request); - switch (request.method) { - case 'GET': - ajax( - `${request.url}${formatGetParameters(request.data)}`, - { - success: onSuccess, - error: onFailure - }, - undefined, - Object.assign({ - method: 'GET', - withCredentials: true - }, request.options) - ); - break; - case 'POST': - ajax( - request.url, - { - success: onSuccess, - error: onFailure - }, - typeof request.data === 'string' ? request.data : JSON.stringify(request.data), - Object.assign({ - method: 'POST', - contentType: 'text/plain', - withCredentials: true - }, request.options) - ); - break; - default: - logWarn(`Skipping invalid request from ${spec.code}. Request type ${request.type} must be GET or POST`); - requestDone(); - } - - function formatGetParameters(data) { - if (data) { - return `?${typeof data === 'object' ? parseQueryStringParameters(data) : data}`; - } - - return ''; - } - }) -}, 'processBidderRequests') - export const registerSyncInner = hook('async', function(spec, responses, gdprConsent, uspConsent) { const aliasSyncEnabled = config.getConfig('userSync.aliasSyncEnabled'); if (spec.getUserSyncs && (aliasSyncEnabled || !adapterManager.aliasRegistry[spec.code])) { @@ -491,17 +449,16 @@ export function getIabSubCategory(bidderCode, category) { } // check that the bid has a width and height set -function validBidSize(adUnitCode, bid, {index = auctionManager.index} = {}) { +function validBidSize(adUnitCode, bid, bidRequests) { if ((bid.width || parseInt(bid.width, 10) === 0) && (bid.height || parseInt(bid.height, 10) === 0)) { bid.width = parseInt(bid.width, 10); bid.height = parseInt(bid.height, 10); return true; } - const bidRequest = index.getBidRequest(bid); - const mediaTypes = index.getMediaTypes(bid); + const adUnit = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); - const sizes = (bidRequest && bidRequest.sizes) || (mediaTypes && mediaTypes.banner && mediaTypes.banner.sizes); + const sizes = adUnit && adUnit.bids && adUnit.bids[0] && adUnit.bids[0].sizes; const parsedSizes = parseSizesInput(sizes); // if a banner impression has one valid size, we assign that size to any bid @@ -517,7 +474,7 @@ function validBidSize(adUnitCode, bid, {index = auctionManager.index} = {}) { } // Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored. -export function isValid(adUnitCode, bid, {index = auctionManager.index} = {}) { +export function isValid(adUnitCode, bid, bidRequests) { function hasValidKeys() { let bidKeys = Object.keys(bid); return COMMON_BID_RESPONSE_KEYS.every(key => includes(bidKeys, key) && !includes([undefined, null], bid[key])); @@ -542,15 +499,15 @@ export function isValid(adUnitCode, bid, {index = auctionManager.index} = {}) { return false; } - if (bid.mediaType === 'native' && !nativeBidIsValid(bid, {index})) { + if (bid.mediaType === 'native' && !nativeBidIsValid(bid, bidRequests)) { logError(errorMessage('Native bid missing some required properties.')); return false; } - if (bid.mediaType === 'video' && !isValidVideoBid(bid, {index})) { + if (bid.mediaType === 'video' && !isValidVideoBid(bid, bidRequests)) { logError(errorMessage(`Video bid does not have required vastUrl or renderer property`)); return false; } - if (bid.mediaType === 'banner' && !validBidSize(adUnitCode, bid, {index})) { + if (bid.mediaType === 'banner' && !validBidSize(adUnitCode, bid, bidRequests)) { logError(errorMessage(`Banner bids require a width and height`)); return false; } diff --git a/src/adloader.js b/src/adloader.js index db128c6d7ba..5460cc79410 100644 --- a/src/adloader.js +++ b/src/adloader.js @@ -1,16 +1,14 @@ -import {includes} from './polyfill.js'; -import { logError, logWarn, insertElement } from './utils.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import * as utils from './utils.js'; -const _requestCache = new WeakMap(); +const _requestCache = {}; // The below list contains modules or vendors whom Prebid allows to load external JS. const _approvedLoadExternalJSList = [ 'adloox', 'criteo', 'outstream', 'adagio', - 'browsi', - 'brandmetrics', - 'justtag' + 'browsi' ] /** @@ -18,72 +16,57 @@ const _approvedLoadExternalJSList = [ * Each unique URL will be loaded at most 1 time. * @param {string} url the url to load * @param {string} moduleCode bidderCode or module code of the module requesting this resource - * @param {function} [callback] callback function to be called after the script is loaded - * @param {Document} [doc] the context document, in which the script will be loaded, defaults to loaded document + * @param {function} [callback] callback function to be called after the script is loaded. */ -export function loadExternalScript(url, moduleCode, callback, doc) { +export function loadExternalScript(url, moduleCode, callback) { if (!moduleCode || !url) { - logError('cannot load external script without url and moduleCode'); + utils.logError('cannot load external script without url and moduleCode'); return; } if (!includes(_approvedLoadExternalJSList, moduleCode)) { - logError(`${moduleCode} not whitelisted for loading external JavaScript`); + utils.logError(`${moduleCode} not whitelisted for loading external JavaScript`); return; } - if (!doc) { - doc = document; // provide a "valid" key for the WeakMap - } // only load each asset once - const storedCachedObject = getCacheObject(doc, url); - if (storedCachedObject) { + if (_requestCache[url]) { if (callback && typeof callback === 'function') { - if (storedCachedObject.loaded) { + if (_requestCache[url].loaded) { // invokeCallbacks immediately callback(); } else { // queue the callback - storedCachedObject.callbacks.push(callback); + _requestCache[url].callbacks.push(callback); } } - return storedCachedObject.tag; + return _requestCache[url].tag; } - const cachedDocObj = _requestCache.get(doc) || {}; - const cacheObject = { + _requestCache[url] = { loaded: false, tag: null, callbacks: [] }; - cachedDocObj[url] = cacheObject; - _requestCache.set(doc, cachedDocObj); - if (callback && typeof callback === 'function') { - cacheObject.callbacks.push(callback); + _requestCache[url].callbacks.push(callback); } - logWarn(`module ${moduleCode} is loading external JavaScript`); + utils.logWarn(`module ${moduleCode} is loading external JavaScript`); return requestResource(url, function () { - cacheObject.loaded = true; + _requestCache[url].loaded = true; try { - for (let i = 0; i < cacheObject.callbacks.length; i++) { - cacheObject.callbacks[i](); + for (let i = 0; i < _requestCache[url].callbacks.length; i++) { + _requestCache[url].callbacks[i](); } } catch (e) { - logError('Error executing callback', 'adloader.js:loadExternalScript', e); + utils.logError('Error executing callback', 'adloader.js:loadExternalScript', e); } - }, doc); + }); - function requestResource(tagSrc, callback, doc) { - if (!doc) { - doc = document; - } - var jptScript = doc.createElement('script'); + function requestResource(tagSrc, callback) { + var jptScript = document.createElement('script'); jptScript.type = 'text/javascript'; jptScript.async = true; - const cacheObject = getCacheObject(doc, url); - if (cacheObject) { - cacheObject.tag = jptScript; - } + _requestCache[url].tag = jptScript; if (jptScript.readyState) { jptScript.onreadystatechange = function () { @@ -101,15 +84,8 @@ export function loadExternalScript(url, moduleCode, callback, doc) { jptScript.src = tagSrc; // add the new script tag to the page - insertElement(jptScript, doc); + utils.insertElement(jptScript); return jptScript; } - function getCacheObject(doc, url) { - const cachedDocObj = _requestCache.get(doc); - if (cachedDocObj && cachedDocObj[url]) { - return cachedDocObj[url]; - } - return null; // return new cache object? - } }; diff --git a/src/ajax.js b/src/ajax.js index 5e926f3210d..a6317e7963d 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -1,5 +1,6 @@ import { config } from './config.js'; -import { logMessage, logError, parseUrl, buildUrl, _each } from './utils.js'; + +var utils = require('./utils.js'); const XHR_DONE = 4; @@ -24,10 +25,10 @@ export function ajaxBuilder(timeout = 3000, {request, done} = {}) { let callbacks = typeof callback === 'object' && callback !== null ? callback : { success: function() { - logMessage('xhr success'); + utils.logMessage('xhr success'); }, error: function(e) { - logError('xhr error', null, e); + utils.logError('xhr error', null, e); } }; @@ -54,14 +55,14 @@ export function ajaxBuilder(timeout = 3000, {request, done} = {}) { // Disabled timeout temporarily to avoid xhr failed requests. https://github.com/prebid/Prebid.js/issues/2648 if (!config.getConfig('disableAjaxTimeout')) { x.ontimeout = function () { - logError(' xhr timeout after ', x.timeout, 'ms'); + utils.logError(' xhr timeout after ', x.timeout, 'ms'); }; } if (method === 'GET' && data) { - let urlInfo = parseUrl(url, options); + let urlInfo = utils.parseUrl(url, options); Object.assign(urlInfo.search, data); - url = buildUrl(urlInfo); + url = utils.buildUrl(urlInfo); } x.open(method, url, true); @@ -74,7 +75,7 @@ export function ajaxBuilder(timeout = 3000, {request, done} = {}) { if (options.withCredentials) { x.withCredentials = true; } - _each(options.customHeaders, (value, header) => { + utils._each(options.customHeaders, (value, header) => { x.setRequestHeader(header, value); }); if (options.preflight) { @@ -92,7 +93,7 @@ export function ajaxBuilder(timeout = 3000, {request, done} = {}) { x.send(); } } catch (error) { - logError('xhr construction', error); + utils.logError('xhr construction', error); typeof callback === 'object' && callback !== null && callback.error(error); } } diff --git a/src/auction.js b/src/auction.js index c55334bcd3d..a6f0342e582 100644 --- a/src/auction.js +++ b/src/auction.js @@ -57,10 +57,7 @@ * @property {function(): void} callBids - sends requests to all adapters for bids */ -import { - flatten, timestamp, adUnitsFilter, deepAccess, getValue, parseUrl, generateUUID, - logMessage, bind, logError, logInfo, logWarn, isEmpty, _each, isFn, isEmptyStr -} from './utils.js'; +import {flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest, getValue, parseUrl} from './utils.js'; import { getPriceBucketString } from './cpmBucketManager.js'; import { getNativeTargeting } from './native.js'; import { getCacheUrl, store } from './videoCache.js'; @@ -68,14 +65,13 @@ import { Renderer } from './Renderer.js'; import { config } from './config.js'; import { userSync } from './userSync.js'; import { hook } from './hook.js'; -import {find, includes} from './polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; import { OUTSTREAM } from './video.js'; import { VIDEO } from './mediaTypes.js'; -import {auctionManager} from './auctionManager.js'; -import {bidderSettings} from './bidderSettings.js'; const { syncUsers } = userSync; - +const utils = require('./utils.js'); const adapterManager = require('./adapterManager.js').default; const events = require('./events.js'); const CONSTANTS = require('./constants.json'); @@ -116,7 +112,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a let _noBids = []; let _auctionStart; let _auctionEnd; - let _auctionId = auctionId || generateUUID(); + let _auctionId = auctionId || utils.generateUUID(); let _auctionStatus; let _callback = callback; let _timer; @@ -161,7 +157,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a if (_auctionEnd === undefined) { let timedOutBidders = []; if (timedOut) { - logMessage(`Auction ${_auctionId} timedOut`); + utils.logMessage(`Auction ${_auctionId} timedOut`); timedOutBidders = getTimedOutBids(_bidderRequests, _timelyBidders); if (timedOutBidders.length) { events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders); @@ -177,13 +173,13 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a if (_callback != null) { const adUnitCodes = _adUnitCodes; const bids = _bidsReceived - .filter(bind.call(adUnitsFilter, this, adUnitCodes)) + .filter(utils.bind.call(adUnitsFilter, this, adUnitCodes)) .reduce(groupByPlacement, {}); _callback.apply($$PREBID_GLOBAL$$, [bids, timedOut, _auctionId]); _callback = null; } } catch (e) { - logError('Error executing bidsBackHandler', null, e); + utils.logError('Error executing bidsBackHandler', null, e); } finally { // Calling timed out bidders if (timedOutBidders.length) { @@ -203,7 +199,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a function auctionDone() { config.resetBidder(); // when all bidders have called done callback atleast once it means auction is complete - logInfo(`Bids Received for Auction with id: ${_auctionId}`, _bidsReceived); + utils.logInfo(`Bids Received for Auction with id: ${_auctionId}`, _bidsReceived); _auctionStatus = AUCTION_COMPLETED; executeCallback(false, true); } @@ -217,10 +213,10 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a _auctionStart = Date.now(); let bidRequests = adapterManager.makeBidRequests(_adUnits, _auctionStart, _auctionId, _timeout, _labels); - logInfo(`Bids Requested for Auction with id: ${_auctionId}`, bidRequests); + utils.logInfo(`Bids Requested for Auction with id: ${_auctionId}`, bidRequests); if (bidRequests.length < 1) { - logWarn('No valid bid requests returned for auction'); + utils.logWarn('No valid bid requests returned for auction'); auctionDone(); } else { addBidderRequests.call({ @@ -250,7 +246,12 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a events.emit(CONSTANTS.EVENTS.AUCTION_INIT, getProperties()); let callbacks = auctionCallbacks(auctionDone, this); - adapterManager.callBids(_adUnits, bidRequests, callbacks.addBidResponse, callbacks.adapterDone, { + adapterManager.callBids(_adUnits, bidRequests, function(...args) { + addBidResponse.apply({ + dispatch: callbacks.addBidResponse, + bidderRequest: this + }, args) + }, callbacks.adapterDone, { request(source, origin) { increment(outstandingRequests, origin); increment(requests, source); @@ -278,7 +279,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a }; if (!runIfOriginHasCapacity(call)) { - logWarn('queueing auction due to limited endpoint capacity'); + utils.logWarn('queueing auction due to limited endpoint capacity'); queuedCalls.push(call); } @@ -340,7 +341,6 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a addWinningBid, setBidTargeting, getWinningBids: () => _winningBids, - getAuctionStart: () => _auctionStart, getTimeout: () => _timeout, getAuctionId: () => _auctionId, getAuctionStatus: () => _auctionStatus, @@ -348,13 +348,12 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a getAdUnitCodes: () => _adUnitCodes, getBidRequests: () => _bidderRequests, getBidsReceived: () => _bidsReceived, - getNoBids: () => _noBids, - + getNoBids: () => _noBids } } -export const addBidResponse = hook('sync', function(adUnitCode, bid) { - this.dispatch.call(null, adUnitCode, bid); +export const addBidResponse = hook('async', function(adUnitCode, bid) { + this.dispatch.call(this.bidderRequest, adUnitCode, bid); }, 'addBidResponse'); export const addBidderRequests = hook('sync', function(bidderRequests) { @@ -367,37 +366,11 @@ export const bidsBackCallback = hook('async', function (adUnits, callback) { } }, 'bidsBackCallback'); -export function auctionCallbacks(auctionDone, auctionInstance, {index = auctionManager.index} = {}) { +export function auctionCallbacks(auctionDone, auctionInstance) { let outstandingBidsAdded = 0; let allAdapterCalledDone = false; let bidderRequestsDone = new Set(); let bidResponseMap = {}; - const ready = {}; - - function waitFor(requestId, result) { - if (ready[requestId] == null) { - ready[requestId] = Promise.resolve(); - } - ready[requestId] = ready[requestId].then(() => Promise.resolve(result).catch(() => {})) - } - - function guard(bidderRequest, fn) { - let timeout = bidderRequest.timeout; - if (timeout == null || timeout > auctionInstance.getTimeout()) { - timeout = auctionInstance.getTimeout(); - } - const timeRemaining = auctionInstance.getAuctionStart() + timeout - Date.now(); - const wait = ready[bidderRequest.bidderRequestId]; - const orphanWait = ready['']; // also wait for "orphan" responses that are not associated with any request - if ((wait != null || orphanWait != null) && timeRemaining > 0) { - Promise.race([ - new Promise((resolve) => setTimeout(resolve, timeRemaining)), - Promise.resolve(orphanWait).then(() => wait) - ]).then(fn); - } else { - fn(); - } - } function afterBidAdded() { outstandingBidsAdded--; @@ -406,16 +379,18 @@ export function auctionCallbacks(auctionDone, auctionInstance, {index = auctionM } } - function handleBidResponse(adUnitCode, bid) { + function addBidResponse(adUnitCode, bid) { + let bidderRequest = this; + bidResponseMap[bid.requestId] = true; outstandingBidsAdded++; let auctionId = auctionInstance.getAuctionId(); - let bidResponse = getPreparedBidForAuction({adUnitCode, bid, auctionId}); + let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}); if (bidResponse.mediaType === 'video') { - tryAddVideoBid(auctionInstance, bidResponse, afterBidAdded); + tryAddVideoBid(auctionInstance, bidResponse, bidderRequest, afterBidAdded); } else { addBidToAuction(auctionInstance, bidResponse); afterBidAdded(); @@ -429,7 +404,7 @@ export function auctionCallbacks(auctionDone, auctionInstance, {index = auctionM bidderRequestsDone.add(bidderRequest); - if (auctionOptionsConfig && !isEmpty(auctionOptionsConfig)) { + if (auctionOptionsConfig && !utils.isEmpty(auctionOptionsConfig)) { const secondaryBidders = auctionOptionsConfig.secondaryBidders; if (secondaryBidders && !bidderRequests.every(bidder => includes(secondaryBidders, bidder.bidderCode))) { bidderRequests = bidderRequests.filter(request => !includes(secondaryBidders, request.bidderCode)); @@ -451,15 +426,8 @@ export function auctionCallbacks(auctionDone, auctionInstance, {index = auctionM } return { - addBidResponse: function (adUnit, bid) { - const bidderRequest = index.getBidderRequest(bid); - waitFor((bidderRequest && bidderRequest.bidderRequestId) || '', addBidResponse.call({ - dispatch: handleBidResponse, - }, adUnit, bid)); - }, - adapterDone: function () { - guard(this, adapterDone.bind(this)) - } + addBidResponse, + adapterDone } } @@ -471,7 +439,9 @@ export function doCallbacksIfTimedout(auctionInstance, bidResponse) { // Add a bid to the auction. export function addBidToAuction(auctionInstance, bidResponse) { - setupBidTargeting(bidResponse); + let bidderRequests = auctionInstance.getBidRequests(); + let bidderRequest = find(bidderRequests, bidderRequest => bidderRequest.bidderCode === bidResponse.bidderCode); + setupBidTargeting(bidResponse, bidderRequest); events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bidResponse); auctionInstance.addBidReceived(bidResponse); @@ -480,22 +450,20 @@ export function addBidToAuction(auctionInstance, bidResponse) { } // Video bids may fail if the cache is down, or there's trouble on the network. -function tryAddVideoBid(auctionInstance, bidResponse, afterBidAdded, {index = auctionManager.index} = {}) { +function tryAddVideoBid(auctionInstance, bidResponse, bidRequests, afterBidAdded) { let addBid = true; - const videoMediaType = deepAccess( - index.getMediaTypes({ - requestId: bidResponse.originalRequestId || bidResponse.requestId, - transactionId: bidResponse.transactionId - }), 'video'); + const bidderRequest = getBidRequest(bidResponse.originalRequestId || bidResponse.requestId, [bidRequests]); + const videoMediaType = + bidderRequest && deepAccess(bidderRequest, 'mediaTypes.video'); const context = videoMediaType && deepAccess(videoMediaType, 'context'); if (config.getConfig('cache.url') && context !== OUTSTREAM) { if (!bidResponse.videoCacheKey || config.getConfig('cache.ignoreBidderCacheKey')) { addBid = false; - callPrebidCache(auctionInstance, bidResponse, afterBidAdded, videoMediaType); + callPrebidCache(auctionInstance, bidResponse, afterBidAdded, bidderRequest); } else if (!bidResponse.vastUrl) { - logError('videoCacheKey specified but not required vastUrl for video bid'); + utils.logError('videoCacheKey specified but not required vastUrl for video bid'); addBid = false; } } @@ -505,15 +473,15 @@ function tryAddVideoBid(auctionInstance, bidResponse, afterBidAdded, {index = au } } -export const callPrebidCache = hook('async', function(auctionInstance, bidResponse, afterBidAdded, videoMediaType) { +export const callPrebidCache = hook('async', function(auctionInstance, bidResponse, afterBidAdded, bidderRequest) { store([bidResponse], function (error, cacheIds) { if (error) { - logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); + utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); doCallbacksIfTimedout(auctionInstance, bidResponse); } else { if (cacheIds[0].uuid === '') { - logWarn(`Supplied video cache key was already in use by Prebid Cache; caching attempt was rejected. Video bid must be discarded.`); + utils.logWarn(`Supplied video cache key was already in use by Prebid Cache; caching attempt was rejected. Video bid must be discarded.`); doCallbacksIfTimedout(auctionInstance, bidResponse); } else { @@ -526,14 +494,13 @@ export const callPrebidCache = hook('async', function(auctionInstance, bidRespon afterBidAdded(); } } - }); + }, bidderRequest); }, 'callPrebidCache'); // Postprocess the bids so that all the universal properties exist, no matter which bidder they came from. // This should be called before addBidToAuction(). -function getPreparedBidForAuction({adUnitCode, bid, auctionId}, {index = auctionManager.index} = {}) { - const bidderRequest = index.getBidderRequest(bid); - const start = (bidderRequest && bidderRequest.start) || bid.requestTimestamp; +function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) { + const start = bidderRequest.start; let bidObject = Object.assign({}, bid, { auctionId, @@ -553,12 +520,14 @@ function getPreparedBidForAuction({adUnitCode, bid, auctionId}, {index = auction events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bidObject); // a publisher-defined renderer can be used to render bids - const adUnitRenderer = index.getAdUnit(bidObject).renderer; + const bidReq = bidderRequest.bids && find(bidderRequest.bids, bid => bid.adUnitCode == adUnitCode && bid.bidId == bidObject.requestId); + const adUnitRenderer = bidReq && bidReq.renderer; // a publisher can also define a renderer for a mediaType const bidObjectMediaType = bidObject.mediaType; - const mediaTypes = index.getMediaTypes(bidObject) - const bidMediaType = mediaTypes && mediaTypes[bidObjectMediaType]; + const bidMediaType = bidReq && + bidReq.mediaTypes && + bidReq.mediaTypes[bidObjectMediaType]; var mediaTypeRenderer = bidMediaType && bidMediaType.renderer; @@ -572,13 +541,12 @@ function getPreparedBidForAuction({adUnitCode, bid, auctionId}, {index = auction } if (renderer) { - // be aware, an adapter could already have installed the bidder, in which case this overwrite's the existing adapter - bidObject.renderer = Renderer.install({ url: renderer.url, config: renderer.options });// rename options to config, to make it consistent? + bidObject.renderer = Renderer.install({ url: renderer.url }); bidObject.renderer.setRender(renderer.render); } // Use the config value 'mediaTypeGranularity' if it has been defined for mediaType, else use 'customPriceBucket' - const mediaTypeGranularity = getMediaTypeGranularity(bid.mediaType, mediaTypes, config.getConfig('mediaTypePriceGranularity')); + const mediaTypeGranularity = getMediaTypeGranularity(bid.mediaType, bidReq, config.getConfig('mediaTypePriceGranularity')); const priceStringsObj = getPriceBucketString( bidObject.cpm, (typeof mediaTypeGranularity === 'object') ? mediaTypeGranularity : config.getConfig('customPriceBucket'), @@ -594,11 +562,11 @@ function getPreparedBidForAuction({adUnitCode, bid, auctionId}, {index = auction return bidObject; } -function setupBidTargeting(bidObject) { +function setupBidTargeting(bidObject, bidderRequest) { let keyValues; - const cpmCheck = (bidderSettings.get(bidObject.bidderCode, 'allowZeroCpmBids') === true) ? bidObject.cpm >= 0 : bidObject.cpm > 0; - if (bidObject.bidderCode && (cpmCheck || bidObject.dealId)) { - keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject); + if (bidObject.bidderCode && (bidObject.cpm > 0 || bidObject.dealId)) { + let bidReq = find(bidderRequest.bids, bid => bid.adUnitCode === bidObject.adUnitCode); + keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject, bidReq); } // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs @@ -607,14 +575,14 @@ function setupBidTargeting(bidObject) { /** * @param {MediaType} mediaType - * @param mediaTypes media types map from adUnit + * @param {Bid} [bidReq] * @param {MediaTypePriceGranularity} [mediaTypePriceGranularity] * @returns {(Object|string|undefined)} */ -export function getMediaTypeGranularity(mediaType, mediaTypes, mediaTypePriceGranularity) { +export function getMediaTypeGranularity(mediaType, bidReq, mediaTypePriceGranularity) { if (mediaType && mediaTypePriceGranularity) { if (mediaType === VIDEO) { - const context = deepAccess(mediaTypes, `${VIDEO}.context`, 'instream'); + const context = deepAccess(bidReq, `mediaTypes.${VIDEO}.context`, 'instream'); if (mediaTypePriceGranularity[`${VIDEO}-${context}`]) { return mediaTypePriceGranularity[`${VIDEO}-${context}`]; } @@ -625,14 +593,14 @@ export function getMediaTypeGranularity(mediaType, mediaTypes, mediaTypePriceGra /** * This function returns the price granularity defined. It can be either publisher defined or default value - * @param bid bid response object - * @param index + * @param {string} mediaType + * @param {BidRequest} bidReq * @returns {string} granularity */ -export const getPriceGranularity = (bid, {index = auctionManager.index} = {}) => { +export const getPriceGranularity = (mediaType, bidReq) => { // Use the config value 'mediaTypeGranularity' if it has been set for mediaType, else use 'priceGranularity' - const mediaTypeGranularity = getMediaTypeGranularity(bid.mediaType, index.getMediaTypes(bid), config.getConfig('mediaTypePriceGranularity')); - const granularity = (typeof bid.mediaType === 'string' && mediaTypeGranularity) ? ((typeof mediaTypeGranularity === 'string') ? mediaTypeGranularity : 'custom') : config.getConfig('priceGranularity'); + const mediaTypeGranularity = getMediaTypeGranularity(mediaType, bidReq, config.getConfig('mediaTypePriceGranularity')); + const granularity = (typeof mediaType === 'string' && mediaTypeGranularity) ? ((typeof mediaTypeGranularity === 'string') ? mediaTypeGranularity : 'custom') : config.getConfig('priceGranularity'); return granularity; } @@ -643,18 +611,17 @@ export const getPriceGranularity = (bid, {index = auctionManager.index} = {}) => */ export const getPriceByGranularity = (granularity) => { return (bid) => { - const bidGranularity = granularity || getPriceGranularity(bid); - if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { + if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { return bid.pbAg; - } else if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { return bid.pbDg; - } else if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { return bid.pbLg; - } else if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { return bid.pbMg; - } else if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { return bid.pbHg; - } else if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { return bid.pbCg; } } @@ -670,51 +637,48 @@ export const getAdvertiserDomain = () => { } } -// factory for key value objs -function createKeyVal(key, value) { - return { - key, - val: (typeof value === 'function') - ? function (bidResponse, bidReq) { - return value(bidResponse, bidReq); - } - : function (bidResponse) { - return getValue(bidResponse, value); - } - }; -} - -function defaultAdserverTargeting() { - const TARGETING_KEYS = CONSTANTS.TARGETING_KEYS; - return [ - createKeyVal(TARGETING_KEYS.BIDDER, 'bidderCode'), - createKeyVal(TARGETING_KEYS.AD_ID, 'adId'), - createKeyVal(TARGETING_KEYS.PRICE_BUCKET, getPriceByGranularity()), - createKeyVal(TARGETING_KEYS.SIZE, 'size'), - createKeyVal(TARGETING_KEYS.DEAL, 'dealId'), - createKeyVal(TARGETING_KEYS.SOURCE, 'source'), - createKeyVal(TARGETING_KEYS.FORMAT, 'mediaType'), - createKeyVal(TARGETING_KEYS.ADOMAIN, getAdvertiserDomain()), - ] -} - /** * @param {string} mediaType * @param {string} bidderCode * @param {BidRequest} bidReq * @returns {*} */ -export function getStandardBidderSettings(mediaType, bidderCode) { +export function getStandardBidderSettings(mediaType, bidderCode, bidReq) { + // factory for key value objs + function createKeyVal(key, value) { + return { + key, + val: (typeof value === 'function') + ? function (bidResponse) { + return value(bidResponse); + } + : function (bidResponse) { + return getValue(bidResponse, value); + } + }; + } const TARGETING_KEYS = CONSTANTS.TARGETING_KEYS; - const standardSettings = Object.assign({}, bidderSettings.settingsFor(null)); + const granularity = getPriceGranularity(mediaType, bidReq); - if (!standardSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { - standardSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = defaultAdserverTargeting(); + let bidderSettings = $$PREBID_GLOBAL$$.bidderSettings; + if (!bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) { + bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {}; + } + if (!bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { + bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = [ + createKeyVal(TARGETING_KEYS.BIDDER, 'bidderCode'), + createKeyVal(TARGETING_KEYS.AD_ID, 'adId'), + createKeyVal(TARGETING_KEYS.PRICE_BUCKET, getPriceByGranularity(granularity)), + createKeyVal(TARGETING_KEYS.SIZE, 'size'), + createKeyVal(TARGETING_KEYS.DEAL, 'dealId'), + createKeyVal(TARGETING_KEYS.SOURCE, 'source'), + createKeyVal(TARGETING_KEYS.FORMAT, 'mediaType'), + createKeyVal(TARGETING_KEYS.ADOMAIN, getAdvertiserDomain()), + ] } if (mediaType === 'video') { - const adserverTargeting = standardSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].slice(); - standardSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = adserverTargeting; + const adserverTargeting = bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]; // Adding hb_uuid + hb_cache_id [TARGETING_KEYS.UUID, TARGETING_KEYS.CACHE_ID].forEach(targetingKeyVal => { @@ -724,63 +688,66 @@ export function getStandardBidderSettings(mediaType, bidderCode) { }); // Adding hb_cache_host - if (config.getConfig('cache.url') && (!bidderCode || bidderSettings.get(bidderCode, 'sendStandardTargeting') !== false)) { + if (config.getConfig('cache.url') && (!bidderCode || utils.deepAccess(bidderSettings, `${bidderCode}.sendStandardTargeting`) !== false)) { const urlInfo = parseUrl(config.getConfig('cache.url')); if (typeof find(adserverTargeting, targetingKeyVal => targetingKeyVal.key === TARGETING_KEYS.CACHE_HOST) === 'undefined') { adserverTargeting.push(createKeyVal(TARGETING_KEYS.CACHE_HOST, function(bidResponse) { - return deepAccess(bidResponse, `adserverTargeting.${TARGETING_KEYS.CACHE_HOST}`) + return utils.deepAccess(bidResponse, `adserverTargeting.${TARGETING_KEYS.CACHE_HOST}`) ? bidResponse.adserverTargeting[TARGETING_KEYS.CACHE_HOST] : urlInfo.hostname; })); } } } - return standardSettings; + return bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; } -export function getKeyValueTargetingPairs(bidderCode, custBidObj, {index = auctionManager.index} = {}) { +export function getKeyValueTargetingPairs(bidderCode, custBidObj, bidReq) { if (!custBidObj) { return {}; } - const bidRequest = index.getBidRequest(custBidObj); + var keyValues = {}; + var bidderSettings = $$PREBID_GLOBAL$$.bidderSettings; // 1) set the keys from "standard" setting or from prebid defaults - // initialize default if not set - const standardSettings = getStandardBidderSettings(custBidObj.mediaType, bidderCode); - setKeys(keyValues, standardSettings, custBidObj, bidRequest); - - // 2) set keys from specific bidder setting override if they exist - if (bidderCode && bidderSettings.getOwn(bidderCode, CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING)) { - setKeys(keyValues, bidderSettings.ownSettingsFor(bidderCode), custBidObj, bidRequest); - custBidObj.sendStandardTargeting = bidderSettings.get(bidderCode, 'sendStandardTargeting'); + if (bidderSettings) { + // initialize default if not set + const standardSettings = getStandardBidderSettings(custBidObj.mediaType, bidderCode, bidReq); + setKeys(keyValues, standardSettings, custBidObj); + + // 2) set keys from specific bidder setting override if they exist + if (bidderCode && bidderSettings[bidderCode] && bidderSettings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { + setKeys(keyValues, bidderSettings[bidderCode], custBidObj); + custBidObj.sendStandardTargeting = bidderSettings[bidderCode].sendStandardTargeting; + } } // set native key value targeting if (custBidObj['native']) { - keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj)); + keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj, bidReq)); } return keyValues; } -function setKeys(keyValues, bidderSettings, custBidObj, bidReq) { +function setKeys(keyValues, bidderSettings, custBidObj) { var targeting = bidderSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]; custBidObj.size = custBidObj.getSize(); - _each(targeting, function (kvPair) { + utils._each(targeting, function (kvPair) { var key = kvPair.key; var value = kvPair.val; if (keyValues[key]) { - logWarn('The key: ' + key + ' is being overwritten'); + utils.logWarn('The key: ' + key + ' is getting ovewritten'); } - if (isFn(value)) { + if (utils.isFn(value)) { try { - value = value(custBidObj, bidReq); + value = value(custBidObj); } catch (e) { - logError('bidmanager', 'ERROR', e); + utils.logError('bidmanager', 'ERROR', e); } } @@ -788,12 +755,12 @@ function setKeys(keyValues, bidderSettings, custBidObj, bidReq) { ((typeof bidderSettings.suppressEmptyKeys !== 'undefined' && bidderSettings.suppressEmptyKeys === true) || key === CONSTANTS.TARGETING_KEYS.DEAL) && // hb_deal is suppressed automatically if not set ( - isEmptyStr(value) || + utils.isEmptyStr(value) || value === null || value === undefined ) ) { - logInfo("suppressing empty key '" + key + "' from adserver targeting"); + utils.logInfo("suppressing empty key '" + key + "' from adserver targeting"); } else { keyValues[key] = value; } @@ -805,13 +772,19 @@ function setKeys(keyValues, bidderSettings, custBidObj, bidReq) { export function adjustBids(bid) { let code = bid.bidderCode; let bidPriceAdjusted = bid.cpm; - const bidCpmAdjustment = bidderSettings.get(code || null, 'bidCpmAdjustment'); - - if (bidCpmAdjustment && typeof bidCpmAdjustment === 'function') { - try { - bidPriceAdjusted = bidCpmAdjustment(bid.cpm, Object.assign({}, bid)); - } catch (e) { - logError('Error during bid adjustment', 'bidmanager.js', e); + let bidCpmAdjustment; + if ($$PREBID_GLOBAL$$.bidderSettings) { + if (code && $$PREBID_GLOBAL$$.bidderSettings[code] && typeof $$PREBID_GLOBAL$$.bidderSettings[code].bidCpmAdjustment === 'function') { + bidCpmAdjustment = $$PREBID_GLOBAL$$.bidderSettings[code].bidCpmAdjustment; + } else if ($$PREBID_GLOBAL$$.bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] && typeof $$PREBID_GLOBAL$$.bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD].bidCpmAdjustment === 'function') { + bidCpmAdjustment = $$PREBID_GLOBAL$$.bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD].bidCpmAdjustment; + } + if (bidCpmAdjustment) { + try { + bidPriceAdjusted = bidCpmAdjustment(bid.cpm, Object.assign({}, bid)); + } catch (e) { + utils.logError('Error during bid adjustment', 'bidmanager.js', e); + } } } @@ -848,7 +821,13 @@ function groupByPlacement(bidsByPlacement, bid) { function getTimedOutBids(bidderRequests, timelyBidders) { const timedOutBids = bidderRequests .map(bid => (bid.bids || []).filter(bid => !timelyBidders.has(bid.bidder))) - .reduce(flatten, []); + .reduce(flatten, []) + .map(bid => ({ + bidId: bid.bidId, + bidder: bid.bidder, + adUnitCode: bid.adUnitCode, + auctionId: bid.auctionId, + })); return timedOutBids; } diff --git a/src/auctionIndex.js b/src/auctionIndex.js deleted file mode 100644 index bdd2b42f9c6..00000000000 --- a/src/auctionIndex.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Retrieves request-related bid data. - * All methods are designed to work with Bid (response) objects returned by bid adapters. - */ -export function AuctionIndex(getAuctions) { - Object.assign(this, { - /** - * @param auctionId - * @returns {*} Auction instance for `auctionId` - */ - getAuction({auctionId}) { - if (auctionId != null) { - return getAuctions() - .find(auction => auction.getAuctionId() === auctionId); - } - }, - /** - * NOTE: you should prefer {@link #getMediaTypes} for looking up bid media types. - * @param transactionId - * @returns adUnit object for `transactionId` - */ - getAdUnit({transactionId}) { - if (transactionId != null) { - return getAuctions() - .flatMap(a => a.getAdUnits()) - .find(au => au.transactionId === transactionId); - } - }, - /** - * @param transactionId - * @param requestId? - * @returns {*} mediaTypes object from bidRequest (through requestId) falling back to the adUnit (through transactionId). - * - * The bidRequest is given precedence because its mediaTypes can differ from the adUnit's (if bidder-specific labels are in use). - * Bids that have no associated request do not have labels either, and use the adUnit's mediaTypes. - */ - getMediaTypes({transactionId, requestId}) { - if (requestId != null) { - const req = this.getBidRequest({requestId}); - if (req != null && (transactionId == null || req.transactionId === transactionId)) { - return req.mediaTypes; - } - } else if (transactionId != null) { - const au = this.getAdUnit({transactionId}); - if (au != null) { - return au.mediaTypes; - } - } - }, - /** - * @param requestId? - * @param bidderRequestId? - * @returns {*} bidderRequest that matches both requestId and bidderRequestId (if either or both are provided). - * - * NOTE: Bid responses are not guaranteed to have a corresponding request. - */ - getBidderRequest({requestId, bidderRequestId}) { - if (requestId != null || bidderRequestId != null) { - let bers = getAuctions().flatMap(a => a.getBidRequests()); - if (bidderRequestId != null) { - bers = bers.filter(ber => ber.bidderRequestId === bidderRequestId); - } - if (requestId == null) { - return bers[0]; - } else { - return bers.find(ber => ber.bids && ber.bids.find(br => br.bidId === requestId) != null) - } - } - }, - /** - * @param requestId - * @returns {*} bidRequest object for requestId - * - * NOTE: Bid responses are not guaranteed to have a corresponding request. - */ - getBidRequest({requestId}) { - if (requestId != null) { - return getAuctions() - .flatMap(a => a.getBidRequests()) - .flatMap(ber => ber.bids) - .find(br => br && br.bidId === requestId); - } - } - }); -} diff --git a/src/auctionManager.js b/src/auctionManager.js index 31f82bb0a89..bbafd7426d5 100644 --- a/src/auctionManager.js +++ b/src/auctionManager.js @@ -21,8 +21,7 @@ import { uniques, flatten, logWarn } from './utils.js'; import { newAuction, getStandardBidderSettings, AUCTION_COMPLETED } from './auction.js'; -import {find} from './polyfill.js'; -import {AuctionIndex} from './auctionIndex.js'; +import find from 'core-js-pure/features/array/find.js'; const CONSTANTS = require('./constants.json'); @@ -124,8 +123,6 @@ export function newAuctionManager() { _auctions.push(auction); } - auctionManager.index = new AuctionIndex(() => _auctions); - return auctionManager; } diff --git a/src/bidderSettings.js b/src/bidderSettings.js deleted file mode 100644 index 343d35a89d2..00000000000 --- a/src/bidderSettings.js +++ /dev/null @@ -1,69 +0,0 @@ -import {deepAccess, mergeDeep} from './utils.js'; -import {getGlobal} from './prebidGlobal.js'; - -const CONSTANTS = require('./constants.json'); - -export class ScopedSettings { - constructor(getSettings, defaultScope) { - this.getSettings = getSettings; - this.defaultScope = defaultScope; - } - - /** - * Get setting value at `path` under the given scope, falling back to the default scope if needed. - * If `scope` is `null`, get the setting's default value. - * @param scope {String|null} - * @param path {String} - * @returns {*} - */ - get(scope, path) { - let value = this.getOwn(scope, path); - if (typeof value === 'undefined') { - value = this.getOwn(null, path); - } - return value; - } - - /** - * Get the setting value at `path` *without* falling back to the default value. - * @param scope {String} - * @param path {String} - * @returns {*} - */ - getOwn(scope, path) { - scope = this.#resolveScope(scope); - return deepAccess(this.getSettings(), `${scope}.${path}`) - } - - /** - * @returns {string[]} all existing scopes except the default one. - */ - getScopes() { - return Object.keys(this.getSettings()).filter((scope) => scope !== this.defaultScope); - } - - /** - * @returns all settings in the given scope, merged with the settings for the default scope. - */ - settingsFor(scope) { - return mergeDeep({}, this.ownSettingsFor(null), this.ownSettingsFor(scope)); - } - - /** - * @returns all settings in the given scope, *without* any of the default settings. - */ - ownSettingsFor(scope) { - scope = this.#resolveScope(scope); - return this.getSettings()[scope] || {}; - } - - #resolveScope(scope) { - if (scope == null) { - return this.defaultScope; - } else { - return scope; - } - } -} - -export const bidderSettings = new ScopedSettings(() => getGlobal().bidderSettings || {}, CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD); diff --git a/src/bidfactory.js b/src/bidfactory.js index 95d69cf0adb..8701184c799 100644 --- a/src/bidfactory.js +++ b/src/bidfactory.js @@ -1,4 +1,4 @@ -import { getUniqueIdentifierStr } from './utils.js'; +var utils = require('./utils.js'); /** Required paramaters @@ -14,18 +14,16 @@ import { getUniqueIdentifierStr } from './utils.js'; dealId, priceKeyString; */ -function Bid(statusCode, {src = 'client', bidder = '', bidId, transactionId, auctionId} = {}) { - var _bidSrc = src; +function Bid(statusCode, bidRequest) { + var _bidSrc = (bidRequest && bidRequest.src) || 'client'; var _statusCode = statusCode || 0; - this.bidderCode = bidder; + this.bidderCode = (bidRequest && bidRequest.bidder) || ''; this.width = 0; this.height = 0; this.statusMessage = _getStatus(); - this.adId = getUniqueIdentifierStr(); - this.requestId = bidId; - this.transactionId = transactionId; - this.auctionId = auctionId; + this.adId = utils.getUniqueIdentifierStr(); + this.requestId = bidRequest && bidRequest.bidId; this.mediaType = 'banner'; this.source = _bidSrc; @@ -50,19 +48,9 @@ function Bid(statusCode, {src = 'client', bidder = '', bidId, transactionId, auc this.getSize = function () { return this.width + 'x' + this.height; }; - - this.getIdentifiers = function () { - return { - src: this.source, - bidder: this.bidderCode, - bidId: this.requestId, - transactionId: this.transactionId, - auctionId: this.auctionId - } - } } // Bid factory function. -export function createBid(statusCode, identifiers) { - return new Bid(statusCode, identifiers); +export function createBid(statusCode, bidRequest) { + return new Bid(statusCode, bidRequest); } diff --git a/src/config.js b/src/config.js index 3fadebd9d07..00cf1efd854 100644 --- a/src/config.js +++ b/src/config.js @@ -1,6 +1,6 @@ /* * Module for getting and setting Prebid configuration. -*/ + */ /** * @typedef {Object} MediaTypePriceGranularity @@ -13,15 +13,16 @@ */ import { isValidPriceConfig } from './cpmBucketManager.js'; -import {find, includes, arrayFrom as from} from './polyfill.js'; -import { - mergeDeep, deepClone, getParameterByName, isPlainObject, logMessage, logWarn, logError, - isArray, isStr, isBoolean, deepAccess, bind -} from './utils.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import Set from 'core-js-pure/features/set'; +import { mergeDeep } from './utils.js'; +const from = require('core-js-pure/features/array/from.js'); +const utils = require('./utils.js'); const CONSTANTS = require('./constants.json'); -const DEFAULT_DEBUG = getParameterByName(CONSTANTS.DEBUG_MODE).toUpperCase() === 'TRUE'; +const DEFAULT_DEBUG = utils.getParameterByName(CONSTANTS.DEBUG_MODE).toUpperCase() === 'TRUE'; const DEFAULT_BIDDER_TIMEOUT = 3000; const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; const DEFAULT_ENABLE_SEND_ALL_BIDS = true; @@ -102,10 +103,10 @@ export function newConfig() { if (validatePriceGranularity(val)) { if (typeof val === 'string') { this._priceGranularity = (hasGranularity(val)) ? val : GRANULARITY_OPTIONS.MEDIUM; - } else if (isPlainObject(val)) { + } else if (utils.isPlainObject(val)) { this._customPriceBucket = val; this._priceGranularity = GRANULARITY_OPTIONS.CUSTOM; - logMessage('Using custom price granularity'); + utils.logMessage('Using custom price granularity'); } } }, @@ -132,12 +133,12 @@ export function newConfig() { if (validatePriceGranularity(val[item])) { if (typeof val === 'string') { aggregate[item] = (hasGranularity(val[item])) ? val[item] : this._priceGranularity; - } else if (isPlainObject(val)) { + } else if (utils.isPlainObject(val)) { aggregate[item] = val[item]; - logMessage(`Using custom price granularity for ${item}`); + utils.logMessage(`Using custom price granularity for ${item}`); } } else { - logWarn(`Invalid price granularity for media type: ${item}`); + utils.logWarn(`Invalid price granularity for media type: ${item}`); } return aggregate; }, {}); @@ -179,7 +180,7 @@ export function newConfig() { if (VALID_ORDERS[val]) { this._bidderSequence = val; } else { - logWarn(`Invalid order: ${val}. Bidder Sequence was not set.`); + utils.logWarn(`Invalid order: ${val}. Bidder Sequence was not set.`); } }, @@ -241,16 +242,16 @@ export function newConfig() { function validatePriceGranularity(val) { if (!val) { - logError('Prebid Error: no value passed to `setPriceGranularity()`'); + utils.logError('Prebid Error: no value passed to `setPriceGranularity()`'); return false; } if (typeof val === 'string') { if (!hasGranularity(val)) { - logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using `medium` as default.'); + utils.logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using `medium` as default.'); } - } else if (isPlainObject(val)) { + } else if (utils.isPlainObject(val)) { if (!isValidPriceConfig(val)) { - logError('Invalid custom price value passed to `setPriceGranularity()`'); + utils.logError('Invalid custom price value passed to `setPriceGranularity()`'); return false; } } @@ -258,27 +259,27 @@ export function newConfig() { } function validateauctionOptions(val) { - if (!isPlainObject(val)) { - logWarn('Auction Options must be an object') + if (!utils.isPlainObject(val)) { + utils.logWarn('Auction Options must be an object') return false } for (let k of Object.keys(val)) { if (k !== 'secondaryBidders' && k !== 'suppressStaleRender') { - logWarn(`Auction Options given an incorrect param: ${k}`) + utils.logWarn(`Auction Options given an incorrect param: ${k}`) return false } if (k === 'secondaryBidders') { - if (!isArray(val[k])) { - logWarn(`Auction Options ${k} must be of type Array`); + if (!utils.isArray(val[k])) { + utils.logWarn(`Auction Options ${k} must be of type Array`); return false - } else if (!val[k].every(isStr)) { - logWarn(`Auction Options ${k} must be only string`); + } else if (!val[k].every(utils.isStr)) { + utils.logWarn(`Auction Options ${k} must be only string`); return false } } else if (k === 'suppressStaleRender') { - if (!isBoolean(val[k])) { - logWarn(`Auction Options ${k} must be of type boolean`); + if (!utils.isBoolean(val[k])) { + utils.logWarn(`Auction Options ${k} must be of type boolean`); return false; } } @@ -292,7 +293,7 @@ export function newConfig() { * @private */ function _getConfig() { - if (currBidder && bidderConfig && isPlainObject(bidderConfig[currBidder])) { + if (currBidder && bidderConfig && utils.isPlainObject(bidderConfig[currBidder])) { let currBidderConfig = bidderConfig[currBidder]; const configTopicSet = new Set(Object.keys(config).concat(Object.keys(currBidderConfig))); @@ -302,7 +303,7 @@ export function newConfig() { } else if (typeof config[topic] === 'undefined') { memo[topic] = currBidderConfig[topic]; } else { - if (isPlainObject(currBidderConfig[topic])) { + if (utils.isPlainObject(currBidderConfig[topic])) { memo[topic] = mergeDeep({}, config[topic], currBidderConfig[topic]); } else { memo[topic] = currBidderConfig[topic]; @@ -314,26 +315,6 @@ export function newConfig() { return Object.assign({}, config); } - /* - * Returns the configuration object if called without parameters, - * or single configuration property if given a string matching a configuration - * property name. Allows deep access e.g. getConfig('currency.adServerCurrency') - * - * If called with callback parameter, or a string and a callback parameter, - * subscribes to configuration updates. See `subscribe` function for usage. - * - * The object returned is a deepClone of the `config` property. - */ - function readConfig(...args) { - if (args.length <= 1 && typeof args[0] !== 'function') { - const option = args[0]; - const configClone = deepClone(_getConfig()); - return option ? deepAccess(configClone, option) : configClone; - } - - return subscribe(...args); - } - /* * Returns configuration object if called without parameters, * or single configuration property if given a string matching a configuration @@ -345,7 +326,7 @@ export function newConfig() { function getConfig(...args) { if (args.length <= 1 && typeof args[0] !== 'function') { const option = args[0]; - return option ? deepAccess(_getConfig(), option) : _getConfig(); + return option ? utils.deepAccess(_getConfig(), option) : _getConfig(); } return subscribe(...args); @@ -370,9 +351,9 @@ export function newConfig() { let prop = (type === 'site') ? 'context' : type; duplicate[prop] = (prop === 'context' || prop === 'user') ? Object.keys(obj[type]).filter(key => key !== 'data').reduce((result, key) => { if (key === 'ext') { - mergeDeep(result, obj[type][key]); + utils.mergeDeep(result, obj[type][key]); } else { - mergeDeep(result, {[key]: obj[type][key]}); + utils.mergeDeep(result, {[key]: obj[type][key]}); } return result; @@ -390,14 +371,14 @@ export function newConfig() { let duplicate = {}; - if (deepAccess(obj, 'ext.data')) { + if (utils.deepAccess(obj, 'ext.data')) { Object.keys(obj.ext.data).forEach((key) => { if (key === 'pbadslot') { - mergeDeep(duplicate, {context: {pbAdSlot: obj.ext.data[key]}}); + utils.mergeDeep(duplicate, {context: {pbAdSlot: obj.ext.data[key]}}); } else if (key === 'adserver') { - mergeDeep(duplicate, {context: {adServer: obj.ext.data[key]}}); + utils.mergeDeep(duplicate, {context: {adServer: obj.ext.data[key]}}); } else { - mergeDeep(duplicate, {context: {data: {[key]: obj.ext.data[key]}}}); + utils.mergeDeep(duplicate, {context: {data: {[key]: obj.ext.data[key]}}}); } }); } @@ -415,9 +396,9 @@ export function newConfig() { let prop = (type === 'context') ? 'site' : type; duplicate[prop] = (prop === 'site' || prop === 'user') ? Object.keys(opt[type]).reduce((result, key) => { if (key === 'data') { - mergeDeep(result, {ext: {data: opt[type][key]}}); + utils.mergeDeep(result, {ext: {data: opt[type][key]}}); } else { - mergeDeep(result, {[key]: opt[type][key]}); + utils.mergeDeep(result, {[key]: opt[type][key]}); } return result; @@ -437,14 +418,14 @@ export function newConfig() { Object.keys(opt).filter(prop => prop === 'context').forEach((type) => { Object.keys(opt[type]).forEach((key) => { if (key === 'data') { - mergeDeep(duplicate, {ext: {data: opt[type][key]}}); + utils.mergeDeep(duplicate, {ext: {data: opt[type][key]}}); } else { if (typeof opt[type][key] === 'object' && !Array.isArray(opt[type][key])) { Object.keys(opt[type][key]).forEach(data => { - mergeDeep(duplicate, {ext: {data: {[key.toLowerCase()]: {[data.toLowerCase()]: opt[type][key][data]}}}}); + utils.mergeDeep(duplicate, {ext: {data: {[key.toLowerCase()]: {[data.toLowerCase()]: opt[type][key][data]}}}}); }); } else { - mergeDeep(duplicate, {ext: {data: {[key.toLowerCase()]: opt[type][key]}}}); + utils.mergeDeep(duplicate, {ext: {data: {[key.toLowerCase()]: opt[type][key]}}}); } } }); @@ -461,7 +442,7 @@ export function newConfig() { arr.forEach((adunit) => { if (adunit.fpd) { - (adunit['ortb2Imp']) ? mergeDeep(adunit['ortb2Imp'], convertImpFpd(adunit.fpd)) : adunit['ortb2Imp'] = convertImpFpd(adunit.fpd); + (adunit['ortb2Imp']) ? utils.mergeDeep(adunit['ortb2Imp'], convertImpFpd(adunit.fpd)) : adunit['ortb2Imp'] = convertImpFpd(adunit.fpd); convert.push((({ fpd, ...duplicate }) => duplicate)(adunit)); } else { convert.push(adunit); @@ -476,8 +457,8 @@ export function newConfig() { * listeners that were added by the `subscribe` function */ function setConfig(options) { - if (!isPlainObject(options)) { - logError('setConfig options must be an object'); + if (!utils.isPlainObject(options)) { + utils.logError('setConfig options must be an object'); return; } @@ -488,7 +469,7 @@ export function newConfig() { let prop = (topic === 'fpd') ? 'ortb2' : topic; let option = (topic === 'fpd') ? convertFpd(options[topic]) : options[topic]; - if (isPlainObject(defaults[prop]) && isPlainObject(option)) { + if (utils.isPlainObject(defaults[prop]) && utils.isPlainObject(option)) { option = Object.assign({}, defaults[prop], option); } @@ -503,8 +484,8 @@ export function newConfig() { * @param {object} options */ function setDefaults(options) { - if (!isPlainObject(defaults)) { - logError('defaults must be an object'); + if (!utils.isPlainObject(defaults)) { + utils.logError('defaults must be an object'); return; } @@ -545,7 +526,7 @@ export function newConfig() { } if (typeof callback !== 'function') { - logError('listener must be a function'); + utils.logError('listener must be a function'); return; } @@ -577,7 +558,7 @@ export function newConfig() { .forEach(listener => listener.callback(options)); } - function setBidderConfig(config, mergeFlag = false) { + function setBidderConfig(config) { try { check(config); config.bidders.forEach(bidder => { @@ -588,51 +569,29 @@ export function newConfig() { let prop = (topic === 'fpd') ? 'ortb2' : topic; let option = (topic === 'fpd') ? convertFpd(config.config[topic]) : config.config[topic]; - if (isPlainObject(option)) { - const func = mergeFlag ? mergeDeep : Object.assign; - bidderConfig[bidder][prop] = func({}, bidderConfig[bidder][prop] || {}, option); + if (utils.isPlainObject(option)) { + bidderConfig[bidder][prop] = Object.assign({}, bidderConfig[bidder][prop] || {}, option); } else { bidderConfig[bidder][prop] = option; } }); }); } catch (e) { - logError(e); + utils.logError(e); } - function check(obj) { - if (!isPlainObject(obj)) { + if (!utils.isPlainObject(obj)) { throw 'setBidderConfig bidder options must be an object'; } if (!(Array.isArray(obj.bidders) && obj.bidders.length)) { throw 'setBidderConfig bidder options must contain a bidders list with at least 1 bidder'; } - if (!isPlainObject(obj.config)) { + if (!utils.isPlainObject(obj.config)) { throw 'setBidderConfig bidder options must contain a config object'; } } } - function mergeConfig(obj) { - if (!isPlainObject(obj)) { - logError('mergeConfig input must be an object'); - return; - } - - const mergedConfig = Object.keys(obj).reduce((accum, key) => { - const prevConf = _getConfig(key)[key] || {}; - accum[key] = mergeDeep(prevConf, obj[key]); - return accum; - }, {}); - - setConfig({ ...mergedConfig }); - return mergedConfig; - } - - function mergeBidderConfig(obj) { - return setBidderConfig(obj, true); - } - /** * Internal functions for core to execute some synchronous code while having an active bidder set. */ @@ -648,9 +607,9 @@ export function newConfig() { return function(cb) { return function(...args) { if (typeof cb === 'function') { - return runWithBidder(bidder, bind.call(cb, this, ...args)) + return runWithBidder(bidder, utils.bind.call(cb, this, ...args)) } else { - logWarn('config.callbackWithBidder callback is not a function'); + utils.logWarn('config.callbackWithBidder callback is not a function'); } } } @@ -670,16 +629,13 @@ export function newConfig() { getCurrentBidder, resetBidder, getConfig, - readConfig, setConfig, - mergeConfig, setDefaults, resetConfig, runWithBidder, callbackWithBidder, setBidderConfig, getBidderConfig, - mergeBidderConfig, convertAdUnitFpd, getLegacyFpd, getLegacyImpFpd diff --git a/src/consentHandler.js b/src/consentHandler.js deleted file mode 100644 index a56d06c8c90..00000000000 --- a/src/consentHandler.js +++ /dev/null @@ -1,101 +0,0 @@ -import {isStr, timestamp} from './utils.js'; - -export class ConsentHandler { - #enabled; - #data; - #promise; - #resolve; - #ready; - generatedTime; - - constructor() { - this.reset(); - } - - /** - * reset this handler (mainly for tests) - */ - reset() { - this.#promise = new Promise((resolve) => { - this.#resolve = (data) => { - this.#ready = true; - this.#data = data; - resolve(data); - }; - }); - this.#enabled = false; - this.#data = null; - this.#ready = false; - this.generatedTime = null; - } - - /** - * Enable this consent handler. This should be called by the relevant consent management module - * on initialization. - */ - enable() { - this.#enabled = true; - } - - /** - * @returns {boolean} true if the related consent management module is enabled. - */ - get enabled() { - return this.#enabled; - } - - /** - * @returns {boolean} true if consent data has been resolved (it may be `null` if the resolution failed). - */ - get ready() { - return this.#ready; - } - - /** - * @returns a promise than resolves to the consent data, or null if no consent data is available - */ - get promise() { - if (this.#ready) { - return Promise.resolve(this.#data); - } - if (!this.#enabled) { - this.#resolve(null); - } - return this.#promise; - } - - setConsentData(data, time = timestamp()) { - this.generatedTime = time; - this.#resolve(data); - } - - getConsentData() { - return this.#data; - } -} - -export class UspConsentHandler extends ConsentHandler { - getConsentMeta() { - const consentData = this.getConsentData(); - if (consentData && this.generatedTime) { - return { - usp: consentData, - generatedAt: this.generatedTime - }; - } - } -} - -export class GdprConsentHandler extends ConsentHandler { - getConsentMeta() { - const consentData = this.getConsentData(); - if (consentData && consentData.vendorData && this.generatedTime) { - return { - gdprApplies: consentData.gdprApplies, - consentStringSize: (isStr(consentData.vendorData.tcString)) ? consentData.vendorData.tcString.length : 0, - generatedAt: this.generatedTime, - apiVersion: consentData.apiVersion - } - } - } -} diff --git a/src/constants.json b/src/constants.json index 94696184e31..77d87e056d9 100644 --- a/src/constants.json +++ b/src/constants.json @@ -32,10 +32,8 @@ "NO_BID": "noBid", "BID_WON": "bidWon", "BIDDER_DONE": "bidderDone", - "BIDDER_ERROR": "bidderError", "SET_TARGETING": "setTargeting", "BEFORE_REQUEST_BIDS": "beforeRequestBids", - "BEFORE_BIDDER_HTTP": "beforeBidderHttp", "REQUEST_BIDS": "requestBids", "ADD_AD_UNITS": "addAdUnits", "AD_RENDER_FAILED": "adRenderFailed", @@ -43,8 +41,7 @@ "TCF2_ENFORCEMENT": "tcf2Enforcement", "AUCTION_DEBUG": "auctionDebug", "BID_VIEWABLE": "bidViewable", - "STALE_RENDER": "staleRender", - "BILLABLE_EVENT": "billableEvent" + "STALE_RENDER": "staleRender" }, "AD_RENDER_FAILED_REASON" : { "PREVENT_WRITING_ON_MAIN_DOCUMENT": "preventWritingOnMainDocument", diff --git a/src/cpmBucketManager.js b/src/cpmBucketManager.js index bd003ddb86d..a6b76cc38e2 100644 --- a/src/cpmBucketManager.js +++ b/src/cpmBucketManager.js @@ -1,5 +1,5 @@ -import {find} from './polyfill.js'; -import { isEmpty } from './utils.js'; +import find from 'core-js-pure/features/array/find.js'; +const utils = require('./utils.js'); const _defaultPrecision = 2; const _lgPriceConfig = { @@ -102,7 +102,7 @@ function getCpmStringValue(cpm, config, granularityMultiplier) { } function isValidPriceConfig(config) { - if (isEmpty(config) || !config.buckets || !Array.isArray(config.buckets)) { + if (utils.isEmpty(config) || !config.buckets || !Array.isArray(config.buckets)) { return false; } let isValid = true; diff --git a/src/debugging.js b/src/debugging.js index 810cf4b432a..dc479f74674 100644 --- a/src/debugging.js +++ b/src/debugging.js @@ -1,24 +1,20 @@ -import {config} from './config.js'; -import {addBidderRequests, addBidResponse} from './auction.js'; -import {hook} from './hook.js'; -import {prefixLog} from './utils.js'; -const {logWarn, logMessage} = prefixLog('DEBUG:'); +import { config } from './config.js'; +import { logMessage as utilsLogMessage, logWarn as utilsLogWarn } from './utils.js'; +import { addBidderRequests, addBidResponse } from './auction.js'; const OVERRIDE_KEY = '$$PREBID_GLOBAL$$:debugging'; export let addBidResponseBound; export let addBidderRequestsBound; -export const onEnableOverrides = [ - (overrides) => { - removeHooks(); - addHooks(overrides); - } -]; -export const onDisableOverrides = [ - removeHooks -]; +function logMessage(msg) { + utilsLogMessage('DEBUG: ' + msg); +} + +function logWarn(msg) { + utilsLogWarn('DEBUG: ' + msg); +} function addHooks(overrides) { addBidResponseBound = addBidResponseHook.bind(overrides); @@ -35,12 +31,13 @@ function removeHooks() { export function enableOverrides(overrides, fromSession = false) { config.setConfig({'debug': true}); - onEnableOverrides.forEach((fn) => fn(overrides)); + removeHooks(); + addHooks(overrides); logMessage(`bidder overrides enabled${fromSession ? ' from session' : ''}`); } export function disableOverrides() { - onDisableOverrides.forEach((fn) => fn()); + removeHooks(); logMessage('bidder overrides disabled'); } @@ -79,7 +76,6 @@ export function applyBidOverrides(overrideObj, bidObj, bidType) { return Object.keys(overrideObj).filter(key => (['adUnitCode', 'bidder'].indexOf(key) === -1)).reduce(function(result, key) { logMessage(`bidder overrides changed '${result.adUnitCode}/${result.bidderCode}' ${bidType}.${key} from '${result[key]}.js' to '${overrideObj[key]}'`); result[key] = overrideObj[key]; - result.isDebug = true; return result; }, bidObj); } @@ -106,7 +102,7 @@ export function addBidResponseHook(next, adUnitCode, bid) { export function addBidderRequestsHook(next, bidderRequests) { const overrides = this; - const includedBidderRequests = bidderRequests.filter(function (bidderRequest) { + const includedBidderRequests = bidderRequests.filter(function(bidderRequest) { if (bidderExcluded(overrides.bidders, bidderRequest.bidderCode)) { logWarn(`bidRequest '${bidderRequest.bidderCode}' excluded from auction by bidder overrides`); return false; @@ -129,27 +125,19 @@ export function addBidderRequestsHook(next, bidderRequests) { next(includedBidderRequests); } -export const saveDebuggingConfig = hook('sync', function (debugConfig, {sessionStorage = window.sessionStorage} = {}) { - if (!debugConfig.enabled) { +export function getConfig(debugging) { + if (!debugging.enabled) { + disableOverrides(); try { - sessionStorage.removeItem(OVERRIDE_KEY); + window.sessionStorage.removeItem(OVERRIDE_KEY); } catch (e) {} } else { try { - sessionStorage.setItem(OVERRIDE_KEY, JSON.stringify(debugConfig)); + window.sessionStorage.setItem(OVERRIDE_KEY, JSON.stringify(debugging)); } catch (e) {} - } -}); - -export function getConfig(debugging, {sessionStorage = window.sessionStorage} = {}) { - saveDebuggingConfig(debugging, {sessionStorage}); - if (!debugging.enabled) { - disableOverrides(); - } else { enableOverrides(debugging); } } - config.getConfig('debugging', ({debugging}) => getConfig(debugging)); export function sessionLoader(storage) { diff --git a/src/events.js b/src/events.js index 148e7b3a2f1..8749ddf206b 100644 --- a/src/events.js +++ b/src/events.js @@ -16,7 +16,8 @@ var idPaths = CONSTANTS.EVENT_ID_PATHS; // keep a record of all events fired var eventsFired = []; -const _public = (function () { + +module.exports = (function () { var _handlers = {}; var _public = {}; @@ -148,5 +149,3 @@ const _public = (function () { return _public; }()); - -export const {on, off, get, getEvents, emit} = _public; diff --git a/src/hook.js b/src/hook.js index 2c8e4c7a6e7..9050bf2f7dc 100644 --- a/src/hook.js +++ b/src/hook.js @@ -13,18 +13,14 @@ export function setupBeforeHookFnOnce(baseFn, hookFn, priority = 15) { baseFn.before(hookFn, priority); } } -const submoduleInstallMap = {}; -export function module(name, install, {postInstallAllowed = false} = {}) { +export function module(name, install) { hook('async', function (submodules) { submodules.forEach(args => install(...args)); - if (postInstallAllowed) submoduleInstallMap[name] = install; }, name)([]); // will be queued until hook.ready() called in pbjs.processQueue(); } export function submodule(name, ...args) { - const install = submoduleInstallMap[name]; - if (install) return install(...args); getHook(name).before((next, modules) => { modules.push(args); next(modules); diff --git a/src/native.js b/src/native.js index ba5e3a62901..7596b38534d 100644 --- a/src/native.js +++ b/src/native.js @@ -1,6 +1,5 @@ -import { deepAccess, getKeyByValue, insertHtmlIntoIframe, logError, triggerPixel } from './utils.js'; -import {includes} from './polyfill.js'; -import {auctionManager} from './auctionManager.js'; +import { deepAccess, getBidRequest, getKeyByValue, insertHtmlIntoIframe, logError, triggerPixel } from './utils.js'; +import includes from 'core-js-pure/features/array/includes.js'; const CONSTANTS = require('./constants.json'); @@ -36,16 +35,6 @@ export function processNativeAdUnitParams(params) { return params; } -export function decorateAdUnitsWithNativeParams(adUnits) { - adUnits.forEach(adUnit => { - const nativeParams = - adUnit.nativeParams || deepAccess(adUnit, 'mediaTypes.native'); - if (nativeParams) { - adUnit.nativeParams = processNativeAdUnitParams(nativeParams); - } - }); -} - /** * Check if the native type specified in the adUnit is supported by Prebid. */ @@ -79,13 +68,16 @@ export const hasNonNativeBidder = adUnit => * @param {BidRequest[]} bidRequests All bid requests for an auction * @return {Boolean} If object is valid */ -export function nativeBidIsValid(bid, {index = auctionManager.index} = {}) { +export function nativeBidIsValid(bid, bidRequests) { + const bidRequest = getBidRequest(bid.requestId, bidRequests); + if (!bidRequest) { return false; } + // all native bid responses must define a landing page url if (!deepAccess(bid, 'native.clickUrl')) { return false; } - const requestedAssets = index.getAdUnit(bid).nativeParams; + const requestedAssets = bidRequest.nativeParams; if (!requestedAssets) { return true; } @@ -147,21 +139,21 @@ export function fireNativeTrackers(message, adObject) { * @param {Object} bid * @return {Object} targeting */ -export function getNativeTargeting(bid, {index = auctionManager.index} = {}) { +export function getNativeTargeting(bid, bidReq) { let keyValues = {}; - const adUnit = index.getAdUnit(bid); - if (deepAccess(adUnit, 'nativeParams.rendererUrl')) { - bid['native']['rendererUrl'] = getAssetValue(adUnit.nativeParams['rendererUrl']); - } else if (deepAccess(adUnit, 'nativeParams.adTemplate')) { - bid['native']['adTemplate'] = getAssetValue(adUnit.nativeParams['adTemplate']); + + if (deepAccess(bidReq, 'nativeParams.rendererUrl')) { + bid['native']['rendererUrl'] = getAssetValue(bidReq.nativeParams['rendererUrl']); + } else if (deepAccess(bidReq, 'nativeParams.adTemplate')) { + bid['native']['adTemplate'] = getAssetValue(bidReq.nativeParams['adTemplate']); } const globalSendTargetingKeys = deepAccess( - adUnit, + bidReq, `nativeParams.sendTargetingKeys` ) !== false; - const nativeKeys = getNativeKeys(adUnit); + const nativeKeys = getNativeKeys(bidReq); const flatBidNativeKeys = { ...bid.native, ...bid.native.ext }; delete flatBidNativeKeys.ext; @@ -174,9 +166,9 @@ export function getNativeTargeting(bid, {index = auctionManager.index} = {}) { return; } - let sendPlaceholder = deepAccess(adUnit, `nativeParams.${asset}.sendId`); + let sendPlaceholder = deepAccess(bidReq, `nativeParams.${asset}.sendId`); if (typeof sendPlaceholder !== 'boolean') { - sendPlaceholder = deepAccess(adUnit, `nativeParams.ext.${asset}.sendId`); + sendPlaceholder = deepAccess(bidReq, `nativeParams.ext.${asset}.sendId`); } if (sendPlaceholder) { @@ -184,9 +176,9 @@ export function getNativeTargeting(bid, {index = auctionManager.index} = {}) { value = placeholder; } - let assetSendTargetingKeys = deepAccess(adUnit, `nativeParams.${asset}.sendTargetingKeys`) + let assetSendTargetingKeys = deepAccess(bidReq, `nativeParams.${asset}.sendTargetingKeys`) if (typeof assetSendTargetingKeys !== 'boolean') { - assetSendTargetingKeys = deepAccess(adUnit, `nativeParams.ext.${asset}.sendTargetingKeys`); + assetSendTargetingKeys = deepAccess(bidReq, `nativeParams.ext.${asset}.sendTargetingKeys`); } const sendTargeting = typeof assetSendTargetingKeys === 'boolean' ? assetSendTargetingKeys : globalSendTargetingKeys; @@ -267,11 +259,11 @@ function getAssetValue(value) { return value; } -function getNativeKeys(adUnit) { +function getNativeKeys(bidReq) { const extraNativeKeys = {} - if (deepAccess(adUnit, 'nativeParams.ext')) { - Object.keys(adUnit.nativeParams.ext).forEach(extKey => { + if (deepAccess(bidReq, 'nativeParams.ext')) { + Object.keys(bidReq.nativeParams.ext).forEach(extKey => { extraNativeKeys[extKey] = `hb_native_${extKey}`; }) } diff --git a/src/polyfill.js b/src/polyfill.js deleted file mode 100644 index 183c2d46bf6..00000000000 --- a/src/polyfill.js +++ /dev/null @@ -1,18 +0,0 @@ -// These stubs are here to help transition away from core-js polyfills for browsers we are no longer supporting. -// You should not need these for new code; use stock JS instead! - -export function includes(target, elem, start) { - return (target && target.includes(elem, start)) || false; -} - -export function arrayFrom() { - return Array.from.apply(Array, arguments); -} - -export function find(arr, pred, thisArg) { - return arr && arr.find(pred, thisArg); -} - -export function findIndex(arr, pred, thisArg) { - return arr && arr.findIndex(pred, thisArg); -} diff --git a/src/prebid.js b/src/prebid.js index 4a7d01dfe76..3264a5fc60b 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -1,12 +1,7 @@ /** @module pbjs */ import { getGlobal } from './prebidGlobal.js'; -import { - adUnitsFilter, flatten, getHighestCpm, isArrayOfNums, isGptPubadsDefined, uniques, logInfo, - contains, logError, isArray, deepClone, deepAccess, isNumber, logWarn, logMessage, isFn, - transformAdServerTargetingObj, bind, replaceAuctionPrice, replaceClickThrough, insertElement, - inIframe, callBurl, createInvisibleIframe, generateUUID, unsupportedBidderMessage, isEmpty -} from './utils.js'; +import { adUnitsFilter, flatten, getHighestCpm, isArrayOfNums, isGptPubadsDefined, uniques } from './utils.js'; import { listenMessagesFromCreative } from './secureCreatives.js'; import { userSync } from './userSync.js'; import { config } from './config.js'; @@ -14,22 +9,21 @@ import { auctionManager } from './auctionManager.js'; import { filters, targeting } from './targeting.js'; import { hook } from './hook.js'; import { sessionLoader } from './debugging.js'; -import {includes} from './polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js'; import { adunitCounter } from './adUnits.js'; import { executeRenderer, isRendererRequired } from './Renderer.js'; import { createBid } from './bidfactory.js'; import { storageCallbacks } from './storageManager.js'; -import { emitAdRenderSucceeded, emitAdRenderFail } from './adRendering.js'; -import {gdprDataHandler, getS2SBidderSet, uspDataHandler} from './adapterManager.js'; const $$PREBID_GLOBAL$$ = getGlobal(); const CONSTANTS = require('./constants.json'); +const utils = require('./utils.js'); const adapterManager = require('./adapterManager.js').default; const events = require('./events.js'); const { triggerUserSyncs } = userSync; /* private variables */ -const { ADD_AD_UNITS, BID_WON, REQUEST_BIDS, SET_TARGETING, STALE_RENDER } = CONSTANTS.EVENTS; +const { ADD_AD_UNITS, BID_WON, REQUEST_BIDS, SET_TARGETING, AD_RENDER_FAILED, AD_RENDER_SUCCEEDED, STALE_RENDER } = CONSTANTS.EVENTS; const { PREVENT_WRITING_ON_MAIN_DOCUMENT, NO_AD, EXCEPTION, CANNOT_FIND_AD, MISSING_DOC_OR_ADID } = CONSTANTS.AD_RENDER_FAILED_REASON; const eventValidators = { @@ -47,9 +41,10 @@ $$PREBID_GLOBAL$$.libLoaded = true; // version auto generated from build $$PREBID_GLOBAL$$.version = 'v$prebid.version$'; -logInfo('Prebid.js v$prebid.version$ loaded'); +utils.logInfo('Prebid.js v$prebid.version$ loaded'); -$$PREBID_GLOBAL$$.installedModules = $$PREBID_GLOBAL$$.installedModules || []; +// modules list generated from build +$$PREBID_GLOBAL$$.installedModules = ['v$prebid.modulesList$']; // create adUnit array $$PREBID_GLOBAL$$.adUnits = $$PREBID_GLOBAL$$.adUnits || []; @@ -62,8 +57,8 @@ function checkDefinedPlacement(id) { .reduce(flatten) .filter(uniques); - if (!contains(adUnitCodes, id)) { - logError('The "' + id + '" placement is not defined.'); + if (!utils.contains(adUnitCodes, id)) { + utils.logError('The "' + id + '" placement is not defined.'); return; } @@ -79,7 +74,7 @@ function setRenderSize(doc, width, height) { function validateSizes(sizes, targLength) { let cleanSizes = []; - if (isArray(sizes) && ((targLength) ? sizes.length === targLength : sizes.length > 0)) { + if (utils.isArray(sizes) && ((targLength) ? sizes.length === targLength : sizes.length > 0)) { // check if an array of arrays or array of numbers if (sizes.every(sz => isArrayOfNums(sz, 2))) { cleanSizes = sizes; @@ -91,7 +86,7 @@ function validateSizes(sizes, targLength) { } function validateBannerMediaType(adUnit) { - const validatedAdUnit = deepClone(adUnit); + const validatedAdUnit = utils.deepClone(adUnit); const banner = validatedAdUnit.mediaTypes.banner; const bannerSizes = validateSizes(banner.sizes); if (bannerSizes.length > 0) { @@ -99,14 +94,14 @@ function validateBannerMediaType(adUnit) { // Deprecation Warning: This property will be deprecated in next release in favor of adUnit.mediaTypes.banner.sizes validatedAdUnit.sizes = bannerSizes; } else { - logError('Detected a mediaTypes.banner object without a proper sizes field. Please ensure the sizes are listed like: [[300, 250], ...]. Removing invalid mediaTypes.banner object from request.'); + utils.logError('Detected a mediaTypes.banner object without a proper sizes field. Please ensure the sizes are listed like: [[300, 250], ...]. Removing invalid mediaTypes.banner object from request.'); delete validatedAdUnit.mediaTypes.banner } return validatedAdUnit; } function validateVideoMediaType(adUnit) { - const validatedAdUnit = deepClone(adUnit); + const validatedAdUnit = utils.deepClone(adUnit); const video = validatedAdUnit.mediaTypes.video; if (video.playerSize) { let tarPlayerSizeLen = (typeof video.playerSize[0] === 'number') ? 2 : 1; @@ -114,13 +109,13 @@ function validateVideoMediaType(adUnit) { const videoSizes = validateSizes(video.playerSize, tarPlayerSizeLen); if (videoSizes.length > 0) { if (tarPlayerSizeLen === 2) { - logInfo('Transforming video.playerSize from [640,480] to [[640,480]] so it\'s in the proper format.'); + utils.logInfo('Transforming video.playerSize from [640,480] to [[640,480]] so it\'s in the proper format.'); } video.playerSize = videoSizes; // Deprecation Warning: This property will be deprecated in next release in favor of adUnit.mediaTypes.video.playerSize validatedAdUnit.sizes = videoSizes; } else { - logError('Detected incorrect configuration of mediaTypes.video.playerSize. Please specify only one set of dimensions in a format like: [[640, 480]]. Removing invalid mediaTypes.video.playerSize property from request.'); + utils.logError('Detected incorrect configuration of mediaTypes.video.playerSize. Please specify only one set of dimensions in a format like: [[640, 480]]. Removing invalid mediaTypes.video.playerSize property from request.'); delete validatedAdUnit.mediaTypes.video.playerSize; } } @@ -128,30 +123,30 @@ function validateVideoMediaType(adUnit) { } function validateNativeMediaType(adUnit) { - const validatedAdUnit = deepClone(adUnit); + const validatedAdUnit = utils.deepClone(adUnit); const native = validatedAdUnit.mediaTypes.native; if (native.image && native.image.sizes && !Array.isArray(native.image.sizes)) { - logError('Please use an array of sizes for native.image.sizes field. Removing invalid mediaTypes.native.image.sizes property from request.'); + utils.logError('Please use an array of sizes for native.image.sizes field. Removing invalid mediaTypes.native.image.sizes property from request.'); delete validatedAdUnit.mediaTypes.native.image.sizes; } if (native.image && native.image.aspect_ratios && !Array.isArray(native.image.aspect_ratios)) { - logError('Please use an array of sizes for native.image.aspect_ratios field. Removing invalid mediaTypes.native.image.aspect_ratios property from request.'); + utils.logError('Please use an array of sizes for native.image.aspect_ratios field. Removing invalid mediaTypes.native.image.aspect_ratios property from request.'); delete validatedAdUnit.mediaTypes.native.image.aspect_ratios; } if (native.icon && native.icon.sizes && !Array.isArray(native.icon.sizes)) { - logError('Please use an array of sizes for native.icon.sizes field. Removing invalid mediaTypes.native.icon.sizes property from request.'); + utils.logError('Please use an array of sizes for native.icon.sizes field. Removing invalid mediaTypes.native.icon.sizes property from request.'); delete validatedAdUnit.mediaTypes.native.icon.sizes; } return validatedAdUnit; } function validateAdUnitPos(adUnit, mediaType) { - let pos = deepAccess(adUnit, `mediaTypes.${mediaType}.pos`); + let pos = utils.deepAccess(adUnit, `mediaTypes.${mediaType}.pos`); - if (!isNumber(pos) || isNaN(pos) || !isFinite(pos)) { + if (!pos || !utils.isNumber(pos) || !isFinite(pos)) { let warning = `Value of property 'pos' on ad unit ${adUnit.code} should be of type: Number`; - logWarn(warning); + utils.logWarn(warning); events.emit(CONSTANTS.EVENTS.AUCTION_DEBUG, {type: 'WARNING', arguments: warning}); delete adUnit.mediaTypes[mediaType].pos; } @@ -159,34 +154,7 @@ function validateAdUnitPos(adUnit, mediaType) { return adUnit } -function validateAdUnit(adUnit) { - const msg = (msg) => `adUnit.code '${adUnit.code}' ${msg}`; - - const mediaTypes = adUnit.mediaTypes; - const bids = adUnit.bids; - - if (bids != null && !isArray(bids)) { - logError(msg(`defines 'adUnit.bids' that is not an array. Removing adUnit from auction`)); - return null; - } - if (bids == null && adUnit.ortb2Imp == null) { - logError(msg(`has no 'adUnit.bids' and no 'adUnit.ortb2Imp'. Removing adUnit from auction`)); - return null; - } - if (!mediaTypes || Object.keys(mediaTypes).length === 0) { - logError(msg(`does not define a 'mediaTypes' object. This is a required field for the auction, so this adUnit has been removed.`)); - return null; - } - if (adUnit.ortb2Imp != null && (bids == null || bids.length === 0)) { - adUnit.bids = [{bidder: null}]; // the 'null' bidder is treated as an s2s-only placeholder by adapterManager - logMessage(msg(`defines 'adUnit.ortb2Imp' with no 'adUnit.bids'; it will be seen only by S2S adapters`)); - } - - return adUnit; -} - export const adUnitSetupChecks = { - validateAdUnit, validateBannerMediaType, validateVideoMediaType, validateNativeMediaType, @@ -197,12 +165,20 @@ export const checkAdUnitSetup = hook('sync', function (adUnits) { const validatedAdUnits = []; adUnits.forEach(adUnit => { - adUnit = validateAdUnit(adUnit); - if (adUnit == null) return; - const mediaTypes = adUnit.mediaTypes; + const bids = adUnit.bids; let validatedBanner, validatedVideo, validatedNative; + if (!bids || !utils.isArray(bids)) { + utils.logError(`Detected adUnit.code '${adUnit.code}' did not have 'adUnit.bids' defined or 'adUnit.bids' is not an array. Removing adUnit from auction.`); + return; + } + + if (!mediaTypes || Object.keys(mediaTypes).length === 0) { + utils.logError(`Detected adUnit.code '${adUnit.code}' did not have a 'mediaTypes' object defined. This is a required field for the auction, so this adUnit has been removed.`); + return; + } + if (mediaTypes.banner) { validatedBanner = validateBannerMediaType(adUnit); if (mediaTypes.banner.hasOwnProperty('pos')) validatedBanner = validateAdUnitPos(validatedBanner, 'banner'); @@ -238,14 +214,14 @@ export const checkAdUnitSetup = hook('sync', function (adUnits) { * @return {Array} returnObj return bids array */ $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCodeStr = function (adunitCode) { - logInfo('Invoking $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCodeStr', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCodeStr', arguments); // call to retrieve bids array if (adunitCode) { var res = $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCode(adunitCode); - return transformAdServerTargetingObj(res); + return utils.transformAdServerTargetingObj(res); } else { - logMessage('Need to call getAdserverTargetingForAdUnitCodeStr with adunitCode'); + utils.logMessage('Need to call getAdserverTargetingForAdUnitCodeStr with adunitCode'); } }; @@ -263,7 +239,7 @@ $$PREBID_GLOBAL$$.getHighestUnusedBidResponseForAdUnitCode = function (adunitCod return bid.length ? bid.reduce(getHighestCpm) : {} } else { - logMessage('Need to call getHighestUnusedBidResponseForAdUnitCode with adunitCode'); + utils.logMessage('Need to call getHighestUnusedBidResponseForAdUnitCode with adunitCode'); } }; @@ -284,31 +260,13 @@ $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCode = function (adUnitCode) { */ $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) { - logInfo('Invoking $$PREBID_GLOBAL$$.getAdserverTargeting', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.getAdserverTargeting', arguments); return targeting.getAllTargeting(adUnitCode); }; -/** - * returns all consent data - * @return {Object} Map of consent types and data - * @alias module:pbjs.getConsentData - */ -function getConsentMetadata() { - return { - gdpr: gdprDataHandler.getConsentMeta(), - usp: uspDataHandler.getConsentMeta(), - coppa: !!(config.getConfig('coppa')) - } -} - -$$PREBID_GLOBAL$$.getConsentMetadata = function () { - logInfo('Invoking $$PREBID_GLOBAL$$.getConsentMetadata'); - return getConsentMetadata(); -}; - function getBids(type) { const responses = auctionManager[type]() - .filter(bind.call(adUnitsFilter, this, auctionManager.getAdUnitCodes())); + .filter(utils.bind.call(adUnitsFilter, this, auctionManager.getAdUnitCodes())); // find the last auction id to get responses for most recent auction only const currentAuctionId = auctionManager.getLastAuctionId(); @@ -333,7 +291,7 @@ function getBids(type) { */ $$PREBID_GLOBAL$$.getNoBids = function () { - logInfo('Invoking $$PREBID_GLOBAL$$.getNoBids', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.getNoBids', arguments); return getBids('getNoBids'); }; @@ -356,7 +314,7 @@ $$PREBID_GLOBAL$$.getNoBidsForAdUnitCode = function (adUnitCode) { */ $$PREBID_GLOBAL$$.getBidResponses = function () { - logInfo('Invoking $$PREBID_GLOBAL$$.getBidResponses', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.getBidResponses', arguments); return getBids('getBidsReceived'); }; @@ -379,9 +337,9 @@ $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode = function (adUnitCode) { * @alias module:pbjs.setTargetingForGPTAsync */ $$PREBID_GLOBAL$$.setTargetingForGPTAsync = function (adUnit, customSlotMatching) { - logInfo('Invoking $$PREBID_GLOBAL$$.setTargetingForGPTAsync', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.setTargetingForGPTAsync', arguments); if (!isGptPubadsDefined()) { - logError('window.googletag is not defined on the page'); + utils.logError('window.googletag is not defined on the page'); return; } @@ -412,9 +370,9 @@ $$PREBID_GLOBAL$$.setTargetingForGPTAsync = function (adUnit, customSlotMatching * @alias module:pbjs.setTargetingForAst */ $$PREBID_GLOBAL$$.setTargetingForAst = function (adUnitCodes) { - logInfo('Invoking $$PREBID_GLOBAL$$.setTargetingForAn', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.setTargetingForAn', arguments); if (!targeting.isApntagDefined()) { - logError('window.apntag is not defined on the page'); + utils.logError('window.apntag is not defined on the page'); return; } @@ -424,29 +382,33 @@ $$PREBID_GLOBAL$$.setTargetingForAst = function (adUnitCodes) { events.emit(SET_TARGETING, targeting.getAllTargeting()); }; -/** - * This function will check for presence of given node in given parent. If not present - will inject it. - * @param {Node} node node, whose existance is in question - * @param {Document} doc document element do look in - * @param {string} tagName tag name to look in - */ -function reinjectNodeIfRemoved(node, doc, tagName) { - const injectionNode = doc.querySelector(tagName); - if (!node.parentNode || node.parentNode !== injectionNode) { - insertElement(node, doc, tagName); - } +function emitAdRenderFail({ reason, message, bid, id }) { + const data = { reason, message }; + if (bid) data.bid = bid; + if (id) data.adId = id; + + utils.logError(message); + events.emit(AD_RENDER_FAILED, data); +} + +function emitAdRenderSucceeded({ doc, bid, id }) { + const data = { doc }; + if (bid) data.bid = bid; + if (id) data.adId = id; + + events.emit(AD_RENDER_SUCCEEDED, data); } /** * This function will render the ad (based on params) in the given iframe document passed through. * Note that doc SHOULD NOT be the parent document page as we can't doc.write() asynchronously - * @param {Document} doc document + * @param {HTMLDocument} doc document * @param {string} id bid id to locate the ad * @alias module:pbjs.renderAd */ $$PREBID_GLOBAL$$.renderAd = hook('async', function (doc, id, options) { - logInfo('Invoking $$PREBID_GLOBAL$$.renderAd', arguments); - logMessage('Calling renderAd with adId :' + id); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.renderAd', arguments); + utils.logMessage('Calling renderAd with adId :' + id); if (doc && id) { try { @@ -456,22 +418,23 @@ $$PREBID_GLOBAL$$.renderAd = hook('async', function (doc, id, options) { if (bid) { let shouldRender = true; if (bid && bid.status === CONSTANTS.BID_STATUS.RENDERED) { - logWarn(`Ad id ${bid.adId} has been rendered before`); + utils.logWarn(`Ad id ${bid.adId} has been rendered before`); events.emit(STALE_RENDER, bid); - if (deepAccess(config.getConfig('auctionOptions'), 'suppressStaleRender')) { + if (utils.deepAccess(config.getConfig('auctionOptions'), 'suppressStaleRender')) { shouldRender = false; } } if (shouldRender) { // replace macros according to openRTB with price paid = bid.cpm - bid.ad = replaceAuctionPrice(bid.ad, bid.originalCpm || bid.cpm); - bid.adUrl = replaceAuctionPrice(bid.adUrl, bid.originalCpm || bid.cpm); + bid.ad = utils.replaceAuctionPrice(bid.ad, bid.cpm); + bid.adUrl = utils.replaceAuctionPrice(bid.adUrl, bid.cpm); + // replacing clickthrough if submitted if (options && options.clickThrough) { const {clickThrough} = options; - bid.ad = replaceClickThrough(bid.ad, clickThrough); - bid.adUrl = replaceClickThrough(bid.adUrl, clickThrough); + bid.ad = utils.replaceClickThrough(bid.ad, clickThrough); + bid.adUrl = utils.replaceClickThrough(bid.adUrl, clickThrough); } // save winning bids @@ -483,34 +446,43 @@ $$PREBID_GLOBAL$$.renderAd = hook('async', function (doc, id, options) { const {height, width, ad, mediaType, adUrl, renderer} = bid; const creativeComment = document.createComment(`Creative ${bid.creativeId} served by ${bid.bidder} Prebid.js Header Bidding`); - insertElement(creativeComment, doc, 'html'); if (isRendererRequired(renderer)) { - executeRenderer(renderer, bid, doc); - reinjectNodeIfRemoved(creativeComment, doc, 'html'); + executeRenderer(renderer, bid); + utils.insertElement(creativeComment, doc, 'html'); emitAdRenderSucceeded({ doc, bid, id }); - } else if ((doc === document && !inIframe()) || mediaType === 'video') { + } else if ((doc === document && !utils.inIframe()) || mediaType === 'video') { const message = `Error trying to write ad. Ad render call ad id ${id} was prevented from writing to the main document.`; emitAdRenderFail({reason: PREVENT_WRITING_ON_MAIN_DOCUMENT, message, bid, id}); } else if (ad) { + // will check if browser is firefox and below version 67, if so execute special doc.open() + // for details see: https://github.com/prebid/Prebid.js/pull/3524 + // TODO remove this browser specific code at later date (when Firefox < 67 usage is mostly gone) + if (navigator.userAgent && navigator.userAgent.toLowerCase().indexOf('firefox/') > -1) { + const firefoxVerRegx = /firefox\/([\d\.]+)/; + let firefoxVer = navigator.userAgent.toLowerCase().match(firefoxVerRegx)[1]; // grabs the text in the 1st matching group + if (firefoxVer && parseInt(firefoxVer, 10) < 67) { + doc.open('text/html', 'replace'); + } + } doc.write(ad); doc.close(); setRenderSize(doc, width, height); - reinjectNodeIfRemoved(creativeComment, doc, 'html'); - callBurl(bid); + utils.insertElement(creativeComment, doc, 'html'); + utils.callBurl(bid); emitAdRenderSucceeded({ doc, bid, id }); } else if (adUrl) { - const iframe = createInvisibleIframe(); + const iframe = utils.createInvisibleIframe(); iframe.height = height; iframe.width = width; iframe.style.display = 'inline'; iframe.style.overflow = 'hidden'; iframe.src = adUrl; - insertElement(iframe, doc, 'body'); + utils.insertElement(iframe, doc, 'body'); setRenderSize(doc, width, height); - reinjectNodeIfRemoved(creativeComment, doc, 'html'); - callBurl(bid); + utils.insertElement(creativeComment, doc, 'html'); + utils.callBurl(bid); emitAdRenderSucceeded({ doc, bid, id }); } else { const message = `Error trying to write ad. No ad for bid response id: ${id}`; @@ -537,7 +509,7 @@ $$PREBID_GLOBAL$$.renderAd = hook('async', function (doc, id, options) { * @alias module:pbjs.removeAdUnit */ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { - logInfo('Invoking $$PREBID_GLOBAL$$.removeAdUnit', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.removeAdUnit', arguments); if (!adUnitCode) { $$PREBID_GLOBAL$$.adUnits = []; @@ -546,7 +518,7 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { let adUnitCodes; - if (isArray(adUnitCode)) { + if (utils.isArray(adUnitCode)) { adUnitCodes = adUnitCode; } else { adUnitCodes = [adUnitCode]; @@ -574,11 +546,21 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { $$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels, auctionId } = {}) { events.emit(REQUEST_BIDS); const cbTimeout = timeout || config.getConfig('bidderTimeout'); - adUnits = (adUnits && config.convertAdUnitFpd(isArray(adUnits) ? adUnits : [adUnits])) || $$PREBID_GLOBAL$$.adUnits; + adUnits = (adUnits && config.convertAdUnitFpd(utils.isArray(adUnits) ? adUnits : [adUnits])) || $$PREBID_GLOBAL$$.adUnits; - logInfo('Invoking $$PREBID_GLOBAL$$.requestBids', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.requestBids', arguments); - const s2sBidders = getS2SBidderSet(config.getConfig('s2sConfig') || []); + let _s2sConfigs = []; + const s2sBidders = []; + config.getConfig('s2sConfig', config => { + if (config && config.s2sConfig) { + _s2sConfigs = Array.isArray(config.s2sConfig) ? config.s2sConfig : [config.s2sConfig]; + } + }); + + _s2sConfigs.forEach(s2sConfig => { + s2sBidders.push(...s2sConfig.bidders); + }); adUnits = checkAdUnitSetup(adUnits); @@ -604,9 +586,9 @@ $$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeo const allBidders = adUnit.bids.map(bid => bid.bidder); const bidderRegistry = adapterManager.bidderRegistry; - const bidders = allBidders.filter(bidder => !s2sBidders.has(bidder)); + const bidders = (s2sBidders) ? allBidders.filter(bidder => !includes(s2sBidders, bidder)) : allBidders; - adUnit.transactionId = generateUUID(); + adUnit.transactionId = utils.generateUUID(); bidders.forEach(bidder => { const adapter = bidderRegistry[bidder]; @@ -618,7 +600,7 @@ $$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeo const bidderEligible = adUnitMediaTypes.some(type => includes(bidderMediaTypes, type)); if (!bidderEligible) { // drop the bidder from the ad unit if it's not compatible - logWarn(unsupportedBidderMessage(adUnit, bidder)); + utils.logWarn(utils.unsupportedBidderMessage(adUnit, bidder)); adUnit.bids = adUnit.bids.filter(bid => bid.bidder !== bidder); } else { adunitCounter.incrementBidderRequestsCounter(adUnit.code, bidder); @@ -628,13 +610,13 @@ $$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeo }); if (!adUnits || adUnits.length === 0) { - logMessage('No adUnits configured. No bids requested.'); + utils.logMessage('No adUnits configured. No bids requested.'); if (typeof bidsBackHandler === 'function') { // executeCallback, this will only be called in case of first request try { bidsBackHandler(); } catch (e) { - logError('Error executing bidsBackHandler', null, e); + utils.logError('Error executing bidsBackHandler', null, e); } } return; @@ -644,7 +626,7 @@ $$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeo let adUnitsLen = adUnits.length; if (adUnitsLen > 15) { - logInfo(`Current auction ${auction.getAuctionId()} contains ${adUnitsLen} adUnits.`, adUnits); + utils.logInfo(`Current auction ${auction.getAuctionId()} contains ${adUnitsLen} adUnits.`, adUnits); } adUnitCodes.forEach(code => targeting.setLatestAuctionForAdUnit(code, auction.getAuctionId())); @@ -674,8 +656,8 @@ $$PREBID_GLOBAL$$.requestBids.before(executeCallbacks, 49); * @alias module:pbjs.addAdUnits */ $$PREBID_GLOBAL$$.addAdUnits = function (adUnitArr) { - logInfo('Invoking $$PREBID_GLOBAL$$.addAdUnits', arguments); - $$PREBID_GLOBAL$$.adUnits.push.apply($$PREBID_GLOBAL$$.adUnits, config.convertAdUnitFpd(isArray(adUnitArr) ? adUnitArr : [adUnitArr])); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.addAdUnits', arguments); + $$PREBID_GLOBAL$$.adUnits.push.apply($$PREBID_GLOBAL$$.adUnits, config.convertAdUnitFpd(utils.isArray(adUnitArr) ? adUnitArr : [adUnitArr])); // emit event events.emit(ADD_AD_UNITS); }; @@ -697,14 +679,14 @@ $$PREBID_GLOBAL$$.addAdUnits = function (adUnitArr) { * Currently `bidWon` is the only event that accepts an `id` parameter. */ $$PREBID_GLOBAL$$.onEvent = function (event, handler, id) { - logInfo('Invoking $$PREBID_GLOBAL$$.onEvent', arguments); - if (!isFn(handler)) { - logError('The event handler provided is not a function and was not set on event "' + event + '".'); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.onEvent', arguments); + if (!utils.isFn(handler)) { + utils.logError('The event handler provided is not a function and was not set on event "' + event + '".'); return; } if (id && !eventValidators[event].call(null, id)) { - logError('The id provided is not valid for event "' + event + '" and no handler was set.'); + utils.logError('The id provided is not valid for event "' + event + '" and no handler was set.'); return; } @@ -718,7 +700,7 @@ $$PREBID_GLOBAL$$.onEvent = function (event, handler, id) { * @alias module:pbjs.offEvent */ $$PREBID_GLOBAL$$.offEvent = function (event, handler, id) { - logInfo('Invoking $$PREBID_GLOBAL$$.offEvent', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.offEvent', arguments); if (id && !eventValidators[event].call(null, id)) { return; } @@ -732,7 +714,7 @@ $$PREBID_GLOBAL$$.offEvent = function (event, handler, id) { * @alias module:pbjs.getEvents */ $$PREBID_GLOBAL$$.getEvents = function () { - logInfo('Invoking $$PREBID_GLOBAL$$.getEvents'); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.getEvents'); return events.getEvents(); }; @@ -743,11 +725,11 @@ $$PREBID_GLOBAL$$.getEvents = function () { * @alias module:pbjs.registerBidAdapter */ $$PREBID_GLOBAL$$.registerBidAdapter = function (bidderAdaptor, bidderCode) { - logInfo('Invoking $$PREBID_GLOBAL$$.registerBidAdapter', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.registerBidAdapter', arguments); try { adapterManager.registerBidAdapter(bidderAdaptor(), bidderCode); } catch (e) { - logError('Error registering bidder adapter : ' + e.message); + utils.logError('Error registering bidder adapter : ' + e.message); } }; @@ -757,11 +739,11 @@ $$PREBID_GLOBAL$$.registerBidAdapter = function (bidderAdaptor, bidderCode) { * @alias module:pbjs.registerAnalyticsAdapter */ $$PREBID_GLOBAL$$.registerAnalyticsAdapter = function (options) { - logInfo('Invoking $$PREBID_GLOBAL$$.registerAnalyticsAdapter', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.registerAnalyticsAdapter', arguments); try { adapterManager.registerAnalyticsAdapter(options); } catch (e) { - logError('Error registering analytics adapter : ' + e.message); + utils.logError('Error registering analytics adapter : ' + e.message); } }; @@ -772,7 +754,7 @@ $$PREBID_GLOBAL$$.registerAnalyticsAdapter = function (options) { * @return {Object} bidResponse [description] */ $$PREBID_GLOBAL$$.createBid = function (statusCode) { - logInfo('Invoking $$PREBID_GLOBAL$$.createBid', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.createBid', arguments); return createBid(statusCode); }; @@ -795,11 +777,11 @@ $$PREBID_GLOBAL$$.createBid = function (statusCode) { const enableAnalyticsCallbacks = []; const enableAnalyticsCb = hook('async', function (config) { - if (config && !isEmpty(config)) { - logInfo('Invoking $$PREBID_GLOBAL$$.enableAnalytics for: ', config); + if (config && !utils.isEmpty(config)) { + utils.logInfo('Invoking $$PREBID_GLOBAL$$.enableAnalytics for: ', config); adapterManager.enableAnalytics(config); } else { - logError('$$PREBID_GLOBAL$$.enableAnalytics should be called with option {}'); + utils.logError('$$PREBID_GLOBAL$$.enableAnalytics should be called with option {}'); } }, 'enableAnalyticsCb'); @@ -811,11 +793,11 @@ $$PREBID_GLOBAL$$.enableAnalytics = function (config) { * @alias module:pbjs.aliasBidder */ $$PREBID_GLOBAL$$.aliasBidder = function (bidderCode, alias, options) { - logInfo('Invoking $$PREBID_GLOBAL$$.aliasBidder', arguments); + utils.logInfo('Invoking $$PREBID_GLOBAL$$.aliasBidder', arguments); if (bidderCode && alias) { adapterManager.aliasBidAdapter(bidderCode, alias, options); } else { - logError('bidderCode and alias must be passed as arguments', '$$PREBID_GLOBAL$$.aliasBidder'); + utils.logError('bidderCode and alias must be passed as arguments', '$$PREBID_GLOBAL$$.aliasBidder'); } }; @@ -901,7 +883,7 @@ $$PREBID_GLOBAL$$.markWinningBidAsUsed = function (markBidRequest) { } else if (markBidRequest.adId) { bids = auctionManager.getBidsReceived().filter(bid => bid.adId === markBidRequest.adId); } else { - logWarn('Improper use of markWinningBidAsUsed. It needs an adUnitCode or an adId to function.'); + utils.logWarn('Improper use of markWinningBidAsUsed. It needs an adUnitCode or an adId to function.'); } if (bids.length > 0) { @@ -915,9 +897,6 @@ $$PREBID_GLOBAL$$.markWinningBidAsUsed = function (markBidRequest) { * @alias module:pbjs.getConfig */ $$PREBID_GLOBAL$$.getConfig = config.getConfig; -$$PREBID_GLOBAL$$.readConfig = config.readConfig; -$$PREBID_GLOBAL$$.mergeConfig = config.mergeConfig; -$$PREBID_GLOBAL$$.mergeBidderConfig = config.mergeBidderConfig; /** * Set Prebid config options. @@ -995,10 +974,10 @@ $$PREBID_GLOBAL$$.cmd.push = function (command) { try { command.call(); } catch (e) { - logError('Error processing command :', e.message, e.stack); + utils.logError('Error processing command :', e.message, e.stack); } } else { - logError('Commands written into $$PREBID_GLOBAL$$.cmd.push must be wrapped in a function'); + utils.logError('Commands written into $$PREBID_GLOBAL$$.cmd.push must be wrapped in a function'); } }; @@ -1011,7 +990,7 @@ function processQueue(queue) { cmd.call(); cmd.called = true; } catch (e) { - logError('Error processing command :', 'prebid.js', e); + utils.logError('Error processing command :', 'prebid.js', e); } } }); diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 5cfa25fbbc8..60e60688c64 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -3,47 +3,23 @@ access to a publisher page from creative payloads. */ -import * as events from './events.js'; +import events from './events.js'; import { fireNativeTrackers, getAssetMessage, getAllAssetsMessage } from './native.js'; import constants from './constants.json'; -import {deepAccess, isApnGetTagDefined, isGptPubadsDefined, logError, logWarn, replaceAuctionPrice} from './utils.js'; -import {auctionManager} from './auctionManager.js'; -import {find, includes} from './polyfill.js'; -import {executeRenderer, isRendererRequired} from './Renderer.js'; -import {config} from './config.js'; -import {emitAdRenderFail, emitAdRenderSucceeded} from './adRendering.js'; +import { logWarn, replaceAuctionPrice, deepAccess, isGptPubadsDefined, isApnGetTagDefined } from './utils.js'; +import { auctionManager } from './auctionManager.js'; +import find from 'core-js-pure/features/array/find.js'; +import { isRendererRequired, executeRenderer } from './Renderer.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import { config } from './config.js'; const BID_WON = constants.EVENTS.BID_WON; const STALE_RENDER = constants.EVENTS.STALE_RENDER; -const HANDLER_MAP = { - 'Prebid Request': handleRenderRequest, - 'Prebid Native': handleNativeRequest, - 'Prebid Event': handleEventRequest, -} - export function listenMessagesFromCreative() { window.addEventListener('message', receiveMessage, false); } -export function getReplier(ev) { - if (ev.origin == null && ev.ports.length === 0) { - return function () { - const msg = 'Cannot post message to a frame with null origin. Please update creatives to use MessageChannel, see https://github.com/prebid/Prebid.js/issues/7870' - logError(msg) - throw new Error(msg); - } - } else if (ev.ports.length > 0) { - return function (message) { - ev.ports[0].postMessage(JSON.stringify(message)); - } - } else { - return function (message) { - ev.source.postMessage(JSON.stringify(message), ev.origin); - } - } -} - export function receiveMessage(ev) { var key = ev.message ? 'message' : 'data'; var data = {}; @@ -53,128 +29,71 @@ export function receiveMessage(ev) { return; } - if (data && data.adId && data.message) { + if (data && data.adId) { const adObject = find(auctionManager.getBidsReceived(), function (bid) { return bid.adId === data.adId; }); - if (HANDLER_MAP.hasOwnProperty(data.message)) { - HANDLER_MAP[data.message](getReplier(ev), data, adObject); - } - } -} -function handleRenderRequest(reply, data, adObject) { - if (adObject == null) { - emitAdRenderFail({ - reason: constants.AD_RENDER_FAILED_REASON.CANNOT_FIND_AD, - message: `Cannot find ad '${data.adId}' for cross-origin render request`, - id: data.adId - }); - return; - } - if (adObject.status === constants.BID_STATUS.RENDERED) { - logWarn(`Ad id ${adObject.adId} has been rendered before`); - events.emit(STALE_RENDER, adObject); - if (deepAccess(config.getConfig('auctionOptions'), 'suppressStaleRender')) { - return; - } - } + if (adObject && data.message === 'Prebid Request') { + if (adObject.status === constants.BID_STATUS.RENDERED) { + logWarn(`Ad id ${adObject.adId} has been rendered before`); + events.emit(STALE_RENDER, adObject); + if (deepAccess(config.getConfig('auctionOptions'), 'suppressStaleRender')) { + return; + } + } - try { - _sendAdToCreative(adObject, reply); - } catch (e) { - emitAdRenderFail({ - reason: constants.AD_RENDER_FAILED_REASON.EXCEPTION, - message: e.message, - id: data.adId, - bid: adObject - }); - return; - } + _sendAdToCreative(adObject, ev); - // save winning bids - auctionManager.addWinningBid(adObject); + // save winning bids + auctionManager.addWinningBid(adObject); - events.emit(BID_WON, adObject); -} + events.emit(BID_WON, adObject); + } -function handleNativeRequest(reply, data, adObject) { - // handle this script from native template in an ad server - // window.parent.postMessage(JSON.stringify({ - // message: 'Prebid Native', - // adId: '%%PATTERN:hb_adid%%' - // }), '*'); - if (adObject == null) { - logError(`Cannot find ad '${data.adId}' for x-origin event request`); - return; - } - switch (data.action) { - case 'assetRequest': - reply(getAssetMessage(data, adObject)); - break; - case 'allAssetRequest': - reply(getAllAssetsMessage(data, adObject)); - break; - case 'resizeNativeHeight': - adObject.height = data.height; - adObject.width = data.width; - resizeRemoteCreative(adObject); - break; - default: - const trackerType = fireNativeTrackers(data, adObject); - if (trackerType === 'click') { + // handle this script from native template in an ad server + // window.parent.postMessage(JSON.stringify({ + // message: 'Prebid Native', + // adId: '%%PATTERN:hb_adid%%' + // }), '*'); + if (adObject && data.message === 'Prebid Native') { + if (data.action === 'assetRequest') { + const message = getAssetMessage(data, adObject); + ev.source.postMessage(JSON.stringify(message), ev.origin); return; + } else if (data.action === 'allAssetRequest') { + const message = getAllAssetsMessage(data, adObject); + ev.source.postMessage(JSON.stringify(message), ev.origin); + } else if (data.action === 'resizeNativeHeight') { + adObject.height = data.height; + adObject.width = data.width; + resizeRemoteCreative(adObject); } + + const trackerType = fireNativeTrackers(data, adObject); + if (trackerType === 'click') { return; } + auctionManager.addWinningBid(adObject); events.emit(BID_WON, adObject); + } } } -function handleEventRequest(reply, data, adObject) { - if (adObject == null) { - logError(`Cannot find ad '${data.adId}' for x-origin event request`); - return; - } - if (adObject.status !== constants.BID_STATUS.RENDERED) { - logWarn(`Received x-origin event request without corresponding render request for ad '${data.adId}'`); - return; - } - switch (data.event) { - case constants.EVENTS.AD_RENDER_FAILED: - emitAdRenderFail({ - bid: adObject, - id: data.adId, - reason: data.info.reason, - message: data.info.message - }); - break; - case constants.EVENTS.AD_RENDER_SUCCEEDED: - emitAdRenderSucceeded({ - doc: null, - bid: adObject, - id: data.adId - }); - break; - default: - logError(`Received x-origin event request for unsupported event: '${data.event}' (adId: '${data.adId}')`) - } -} - -export function _sendAdToCreative(adObject, reply) { - const { adId, ad, adUrl, width, height, renderer, cpm, originalCpm } = adObject; +export function _sendAdToCreative(adObject, ev) { + const { adId, ad, adUrl, width, height, renderer, cpm } = adObject; // rendering for outstream safeframe if (isRendererRequired(renderer)) { executeRenderer(renderer, adObject); } else if (adId) { resizeRemoteCreative(adObject); - reply({ + ev.source.postMessage(JSON.stringify({ message: 'Prebid Response', - ad: replaceAuctionPrice(ad, originalCpm || cpm), - adUrl: replaceAuctionPrice(adUrl, originalCpm || cpm), + ad: replaceAuctionPrice(ad, cpm), + adUrl: replaceAuctionPrice(adUrl, cpm), adId, width, height - }); + }), ev.origin); } } @@ -209,12 +128,11 @@ function resizeRemoteCreative({ adId, adUnitCode, width, height }) { } function getDfpElementId(adId) { - const slot = find(window.googletag.pubads().getSlots(), slot => { + return find(window.googletag.pubads().getSlots(), slot => { return find(slot.getTargetingKeys(), key => { return includes(slot.getTargeting(key), adId); }); - }); - return slot ? slot.getSlotElementId() : null; + }).getSlotElementId(); } function getAstElementId(adUnitCode) { diff --git a/src/sizeMapping.js b/src/sizeMapping.js index 4333608ca95..cd5f1190069 100644 --- a/src/sizeMapping.js +++ b/src/sizeMapping.js @@ -1,6 +1,6 @@ import { config } from './config.js'; -import {logWarn, logInfo, isPlainObject, deepAccess, deepClone, getWindowTop} from './utils.js'; -import {includes} from './polyfill.js'; +import {logWarn, isPlainObject, deepAccess, deepClone, getWindowTop} from './utils.js'; +import includes from 'core-js-pure/features/array/includes.js'; let sizeConfig = []; @@ -154,48 +154,3 @@ function evaluateSizeConfig(configs) { shouldFilter: false }); } - -export function processAdUnitsForLabels(adUnits, activeLabels) { - return adUnits.reduce((adUnits, adUnit) => { - let { - active, - mediaTypes, - filterResults - } = resolveStatus( - getLabels(adUnit, activeLabels), - adUnit.mediaTypes, - adUnit.sizes - ); - - if (!active) { - logInfo(`Size mapping disabled adUnit "${adUnit.code}"`); - } else { - if (filterResults) { - logInfo(`Size mapping filtered adUnit "${adUnit.code}" banner sizes from `, filterResults.before, 'to ', filterResults.after); - } - - adUnit.mediaTypes = mediaTypes; - - adUnit.bids = adUnit.bids.reduce((bids, bid) => { - let { - active, - mediaTypes, - filterResults - } = resolveStatus(getLabels(bid, activeLabels), adUnit.mediaTypes); - - if (!active) { - logInfo(`Size mapping deactivated adUnit "${adUnit.code}" bidder "${bid.bidder}"`); - } else { - if (filterResults) { - logInfo(`Size mapping filtered adUnit "${adUnit.code}" bidder "${bid.bidder}" banner sizes from `, filterResults.before, 'to ', filterResults.after); - bid.mediaTypes = mediaTypes; - } - bids.push(bid); - } - return bids; - }, []); - adUnits.push(adUnit); - } - return adUnits; - }, []); -} diff --git a/src/storageManager.js b/src/storageManager.js index 30e8d4c8abb..66a0cf68cbf 100644 --- a/src/storageManager.js +++ b/src/storageManager.js @@ -1,7 +1,6 @@ import {hook} from './hook.js'; -import {hasDeviceAccess, checkCookieSupport, logError, logInfo, isPlainObject} from './utils.js'; -import {includes} from './polyfill.js'; -import {bidderSettings as defaultBidderSettings} from './bidderSettings.js'; +import * as utils from './utils.js'; +import includes from 'core-js-pure/features/array/includes.js'; const moduleTypeWhiteList = ['core', 'prebid-module']; @@ -11,8 +10,7 @@ export let storageCallbacks = []; * Storage options * @typedef {Object} storageOptions * @property {Number=} gvlid - Vendor id - * @property {string} moduleName? - Module name - * @property {string=} bidderCode? - Bidder code + * @property {string} moduleName - Module name * @property {string=} moduleType - Module type, value can be anyone of core or prebid-module */ @@ -20,41 +18,29 @@ export let storageCallbacks = []; * Returns list of storage related functions with gvlid, module name and module type in its scope. * All three argument are optional here. Below shows the usage of of these * - GVL Id: Pass GVL id if you are a vendor - * - Bidder code: All bid adapters need to pass bidderCode - * - Module name: All other modules need to pass module name + * - Module name: All modules need to pass module name * - Module type: Some modules may need these functions but are not vendor. e.g prebid core files in src and modules like currency. * @param {storageOptions} options */ -export function newStorageManager({gvlid, moduleName, bidderCode, moduleType} = {}, {bidderSettings = defaultBidderSettings} = {}) { - function isBidderDisallowed() { - if (bidderCode == null) { - return false; - } - const storageAllowed = bidderSettings.get(bidderCode, 'storageAllowed'); - return storageAllowed == null ? false : !storageAllowed; - } +export function newStorageManager({gvlid, moduleName, moduleType} = {}) { function isValid(cb) { if (includes(moduleTypeWhiteList, moduleType)) { let result = { valid: true } return cb(result); - } else if (isBidderDisallowed()) { - logInfo(`bidderSettings denied access to device storage for bidder '${bidderCode}'`); - const result = {valid: false}; - return cb(result); } else { let value; let hookDetails = { hasEnforcementHook: false } - validateStorageEnforcement(gvlid, bidderCode || moduleName, hookDetails, function(result) { + validateStorageEnforcement(gvlid, moduleName, hookDetails, function(result) { if (result && result.hasEnforcementHook) { value = cb(result); } else { let result = { hasEnforcementHook: false, - valid: hasDeviceAccess() + valid: utils.hasDeviceAccess() } value = cb(result); } @@ -149,7 +135,7 @@ export function newStorageManager({gvlid, moduleName, bidderCode, moduleType} = const cookiesAreEnabled = function (done) { let cb = function (result) { if (result && result.valid) { - if (checkCookieSupport()) { + if (utils.checkCookieSupport()) { return true; } window.document.cookie = 'prebid.cookieTest'; @@ -236,7 +222,7 @@ export function newStorageManager({gvlid, moduleName, bidderCode, moduleType} = try { return !!window.localStorage; } catch (e) { - logError('Local storage api disabled'); + utils.logError('Local storage api disabled'); } } return false; @@ -261,7 +247,7 @@ export function newStorageManager({gvlid, moduleName, bidderCode, moduleType} = let cb = function (result) { if (result && result.valid) { const all = []; - if (hasDeviceAccess()) { + if (utils.hasDeviceAccess()) { const cookies = document.cookie.split(';'); while (cookies.length) { const cookie = cookies.pop(); @@ -317,17 +303,12 @@ export function getCoreStorageManager(moduleName) { /** * Note: Core modules or Prebid modules like Currency, SizeMapping should use getCoreStorageManager - * This function returns storage functions to access cookies and localstorage. Bidders and User id modules should import this and use it in their module if needed. - * Bid adapters should always provide `bidderCode`. GVL ID and Module name are optional param but gvl id is needed for when gdpr enforcement module is used. - * @param {Number=} gvlid? Vendor id - required for proper GDPR integration - * @param {string=} bidderCode? - required for bid adapters - * @param {string=} moduleName? module name + * This function returns storage functions to access cookies and localstorage. Bidders and User id modules should import this and use it in their module if needed. GVL ID and Module name are optional param but gvl id is needed for when gdpr enforcement module is used. + * @param {Number=} gvlid Vendor id + * @param {string=} moduleName BidderCode or module name */ -export function getStorageManager({gvlid, moduleName, bidderCode} = {}) { - if (arguments.length > 1 || (arguments.length > 0 && !isPlainObject(arguments[0]))) { - throw new Error('Invalid invocation for getStorageManager') - } - return newStorageManager({gvlid, moduleName, bidderCode}); +export function getStorageManager(gvlid, moduleName) { + return newStorageManager({gvlid: gvlid, moduleName: moduleName}); } export function resetData() { diff --git a/src/targeting.js b/src/targeting.js index 6a80ce10806..4bbed7bb758 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -1,16 +1,14 @@ -import { - uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, groupBy, isAdUnitCodeMatchingSlot, timestamp, - deepAccess, deepClone, logError, logWarn, logInfo, isFn, isArray, logMessage, isStr, -} from './utils.js'; +import { uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, groupBy, isAdUnitCodeMatchingSlot, timestamp, deepAccess, deepClone, logError, logWarn, logInfo } from './utils.js'; import { config } from './config.js'; import { NATIVE_TARGETING_KEYS } from './native.js'; import { auctionManager } from './auctionManager.js'; import { sizeSupported } from './sizeMapping.js'; import { ADPOD } from './mediaTypes.js'; import { hook } from './hook.js'; -import { bidderSettings } from './bidderSettings.js'; -import {includes, find} from './polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js'; +import find from 'core-js-pure/features/array/find.js'; +const utils = require('./utils.js'); var CONSTANTS = require('./constants.json'); var pbTargetingKeys = []; @@ -18,10 +16,6 @@ var pbTargetingKeys = []; const MAX_DFP_KEYLENGTH = 20; const TTL_BUFFER = 1000; -const CFG_ALLOW_TARGETING_KEYS = `targetingControls.allowTargetingKeys`; -const CFG_ADD_TARGETING_KEYS = `targetingControls.addTargetingKeys`; -const TARGETING_KEY_CONFIGURATION_ERROR_MSG = `Only one of "${CFG_ALLOW_TARGETING_KEYS}" or "${CFG_ADD_TARGETING_KEYS}" can be set`; - export const TARGETING_KEYS = Object.keys(CONSTANTS.TARGETING_KEYS).map( key => CONSTANTS.TARGETING_KEYS[key] ); @@ -127,19 +121,17 @@ export function newTargeting(auctionManager) { if (isGptPubadsDefined()) { const adUnitCodes = getAdUnitCodes(adUnitCode); const adUnits = auctionManager.getAdUnits().filter(adUnit => includes(adUnitCodes, adUnit.code)); - let unsetKeys = pbTargetingKeys.reduce((reducer, key) => { - reducer[key] = null; - return reducer; - }, {}); window.googletag.pubads().getSlots().forEach(slot => { - let customSlotMatchingFunc = isFn(customSlotMatching) && customSlotMatching(slot); - // reset only registered adunits - adUnits.forEach(unit => { - if (unit.code === slot.getAdUnitPath() || - unit.code === slot.getSlotElementId() || - (isFn(customSlotMatchingFunc) && customSlotMatchingFunc(unit.code))) { - slot.updateTargetingFromMap(unsetKeys); - } + let customSlotMatchingFunc = utils.isFn(customSlotMatching) && customSlotMatching(slot); + pbTargetingKeys.forEach(function(key) { + // reset only registered adunits + adUnits.forEach(function(unit) { + if (unit.code === slot.getAdUnitPath() || + unit.code === slot.getSlotElementId() || + (utils.isFn(customSlotMatchingFunc) && customSlotMatchingFunc(unit.code))) { + slot.setTargeting(key, null); + } + }); }); }); } @@ -168,7 +160,7 @@ export function newTargeting(auctionManager) { */ function bidShouldBeAddedToTargeting(bid, adUnitCodes) { return bid.adserverTargeting && adUnitCodes && - ((isArray(adUnitCodes) && includes(adUnitCodes, bid.adUnitCode)) || + ((utils.isArray(adUnitCodes) && includes(adUnitCodes, bid.adUnitCode)) || (typeof adUnitCodes === 'string' && bid.adUnitCode === adUnitCodes)); }; @@ -265,17 +257,7 @@ export function newTargeting(auctionManager) { }); const defaultKeys = Object.keys(Object.assign({}, CONSTANTS.DEFAULT_TARGETING_KEYS, CONSTANTS.NATIVE_KEYS)); - let allowedKeys = config.getConfig(CFG_ALLOW_TARGETING_KEYS); - const addedKeys = config.getConfig(CFG_ADD_TARGETING_KEYS); - - if (addedKeys != null && allowedKeys != null) { - throw new Error(TARGETING_KEY_CONFIGURATION_ERROR_MSG); - } else if (addedKeys != null) { - allowedKeys = defaultKeys.concat(addedKeys); - } else { - allowedKeys = allowedKeys || defaultKeys; - } - + const allowedKeys = config.getConfig('targetingControls.allowTargetingKeys') || defaultKeys; if (Array.isArray(allowedKeys) && allowedKeys.length > 0) { targeting = getAllowedTargetingKeyValues(targeting, allowedKeys); } @@ -298,13 +280,6 @@ export function newTargeting(auctionManager) { return targeting; }; - // warn about conflicting configuration - config.getConfig('targetingControls', function (config) { - if (deepAccess(config, CFG_ALLOW_TARGETING_KEYS) != null && deepAccess(config, CFG_ADD_TARGETING_KEYS) != null) { - logError(TARGETING_KEY_CONFIGURATION_ERROR_MSG); - } - }); - // create an encoded string variant based on the keypairs of the provided object // - note this will encode the characters between the keys (ie = and &) function convertKeysToQueryForm(keyMap) { @@ -362,7 +337,7 @@ export function newTargeting(auctionManager) { * "div-gpt-ad-1460505748561-0": [{"hb_bidder": ["appnexusAst"]}] * }, * { - * "div-gpt-ad-1460505748561-0": [{"hb_bidder_appnexusAs": ["appnexusAst", "other"]}] + * "div-gpt-ad-1460505748561-0": [{"hb_bidder_appnexusAs": ["appnexusAst"]}] * } * ] * ``` @@ -371,7 +346,7 @@ export function newTargeting(auctionManager) { * { * "div-gpt-ad-1460505748561-0": { * "hb_bidder": "appnexusAst", - * "hb_bidder_appnexusAs": "appnexusAst,other" + * "hb_bidder_appnexusAs": "appnexusAst" * } * } * ``` @@ -385,7 +360,7 @@ export function newTargeting(auctionManager) { [Object.keys(targeting)[0]]: targeting[Object.keys(targeting)[0]] .map(target => { return { - [Object.keys(target)[0]]: target[Object.keys(target)[0]].join(',') + [Object.keys(target)[0]]: target[Object.keys(target)[0]].join(', ') }; }).reduce((p, c) => Object.assign(c, p), {}) }; @@ -404,18 +379,21 @@ export function newTargeting(auctionManager) { targeting.setTargetingForGPT = function(targetingConfig, customSlotMatching) { window.googletag.pubads().getSlots().forEach(slot => { Object.keys(targetingConfig).filter(customSlotMatching ? customSlotMatching(slot) : isAdUnitCodeMatchingSlot(slot)) - .forEach(targetId => { + .forEach(targetId => Object.keys(targetingConfig[targetId]).forEach(key => { - let value = targetingConfig[targetId][key]; - if (typeof value === 'string' && value.indexOf(',') !== -1) { - // due to the check the array will be formed only if string has ',' else plain string will be assigned as value - value = value.split(','); + let valueArr = targetingConfig[targetId][key]; + if (typeof valueArr === 'string') { + valueArr = valueArr.split(','); } - targetingConfig[targetId][key] = value; - }); - logMessage(`Attempting to set targeting-map for slot: ${slot.getSlotElementId()} with targeting-map:`, targetingConfig[targetId]); - slot.updateTargetingFromMap(targetingConfig[targetId]) - }) + valueArr = (valueArr.length > 1) ? [valueArr] : valueArr; + valueArr.map((value) => { + utils.logMessage(`Attempting to set key value for slot: ${slot.getSlotElementId()} key: ${key} value: ${value}`); + return value; + }).forEach(value => { + slot.setTargeting(key, value); + }); + }) + ) }) }; @@ -427,7 +405,7 @@ export function newTargeting(auctionManager) { function getAdUnitCodes(adUnitCode) { if (typeof adUnitCode === 'string') { return [adUnitCode]; - } else if (isArray(adUnitCode)) { + } else if (utils.isArray(adUnitCode)) { return adUnitCode; } return auctionManager.getAdUnitCodes() || []; @@ -437,15 +415,7 @@ export function newTargeting(auctionManager) { let bidsReceived = auctionManager.getBidsReceived(); if (!config.getConfig('useBidCache')) { - // don't use bid cache (i.e. filter out bids not in the latest auction) bidsReceived = bidsReceived.filter(bid => latestAuctionForAdUnit[bid.adUnitCode] === bid.auctionId) - } else { - // if custom bid cache filter function exists, run for each bid from - // previous auctions. If it returns true, include bid in bid pool - const filterFunction = config.getConfig('bidCacheFilterFunction'); - if (typeof filterFunction === 'function') { - bidsReceived = bidsReceived.filter(bid => latestAuctionForAdUnit[bid.adUnitCode] === bid.auctionId || !!filterFunction(bid)) - } } bidsReceived = bidsReceived @@ -467,7 +437,7 @@ export function newTargeting(auctionManager) { const adUnitCodes = getAdUnitCodes(adUnitCode); return bidsReceived .filter(bid => includes(adUnitCodes, bid.adUnitCode)) - .filter(bid => (bidderSettings.get(bid.bidderCode, 'allowZeroCpmBids') === true) ? bid.cpm >= 0 : bid.cpm > 0) + .filter(bid => bid.cpm > 0) .map(bid => bid.adUnitCode) .filter(uniques) .map(adUnitCode => bidsReceived @@ -485,14 +455,14 @@ export function newTargeting(auctionManager) { try { targeting.resetPresetTargetingAST(adUnitCodes); } catch (e) { - logError('unable to reset targeting for AST' + e) + utils.logError('unable to reset targeting for AST' + e) } Object.keys(astTargeting).forEach(targetId => Object.keys(astTargeting[targetId]).forEach(key => { - logMessage(`Attempting to set targeting for targetId: ${targetId} key: ${key} value: ${astTargeting[targetId][key]}`); + utils.logMessage(`Attempting to set targeting for targetId: ${targetId} key: ${key} value: ${astTargeting[targetId][key]}`); // setKeywords supports string and array as value - if (isStr(astTargeting[targetId][key]) || isArray(astTargeting[targetId][key])) { + if (utils.isStr(astTargeting[targetId][key]) || utils.isArray(astTargeting[targetId][key])) { let keywordsObj = {}; let regex = /pt[0-9]/; if (key.search(regex) < 0) { @@ -557,7 +527,7 @@ export function newTargeting(auctionManager) { function mergeAdServerTargeting(acc, bid, index, arr) { function concatTargetingValue(key) { return function(currentBidElement) { - if (!isArray(currentBidElement.adserverTargeting[key])) { + if (!utils.isArray(currentBidElement.adserverTargeting[key])) { currentBidElement.adserverTargeting[key] = [currentBidElement.adserverTargeting[key]]; } currentBidElement.adserverTargeting[key] = currentBidElement.adserverTargeting[key].concat(bid.adserverTargeting[key]).filter(uniques); @@ -664,8 +634,8 @@ export function newTargeting(auctionManager) { return Object.keys(aut) .map(function(key) { - if (isStr(aut[key])) aut[key] = aut[key].split(',').map(s => s.trim()); - if (!isArray(aut[key])) aut[key] = [ aut[key] ]; + if (utils.isStr(aut[key])) aut[key] = aut[key].split(','); + if (!utils.isArray(aut[key])) aut[key] = [ aut[key] ]; return { [key]: aut[key] }; }); } @@ -678,7 +648,7 @@ export function newTargeting(auctionManager) { } targeting.isApntagDefined = function() { - if (window.apntag && isFn(window.apntag.setKeywords)) { + if (window.apntag && utils.isFn(window.apntag.setKeywords)) { return true; } }; diff --git a/src/userSync.js b/src/userSync.js index 96c3d662cad..f653880fa29 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -1,9 +1,6 @@ -import { - deepClone, isPlainObject, logError, shuffle, logMessage, triggerPixel, insertUserSyncIframe, isArray, - logWarn, isStr, isSafariBrowser -} from './utils.js'; +import * as utils from './utils.js'; import { config } from './config.js'; -import {includes} from './polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js'; import { getCoreStorageManager } from './storageManager.js'; export const USERSYNC_DEFAULT_CONFIG = { @@ -21,7 +18,7 @@ export const USERSYNC_DEFAULT_CONFIG = { // Set userSync default values config.setDefaults({ - 'userSync': deepClone(USERSYNC_DEFAULT_CONFIG) + 'userSync': utils.deepClone(USERSYNC_DEFAULT_CONFIG) }); const storage = getCoreStorageManager('usersync'); @@ -57,7 +54,7 @@ export function newUserSync(userSyncDependencies) { // if userSync.filterSettings does not contain image/all configs, merge in default image config to ensure image pixels are fired if (conf.userSync) { let fs = conf.userSync.filterSettings; - if (isPlainObject(fs)) { + if (utils.isPlainObject(fs)) { if (!fs.image && !fs.all) { conf.userSync.filterSettings.image = { bidders: '*', @@ -94,12 +91,12 @@ export function newUserSync(userSyncDependencies) { } try { - // Iframe syncs - loadIframes(); // Image pixels fireImagePixels(); + // Iframe syncs + loadIframes(); } catch (e) { - return logError('Error firing user syncs', e); + return utils.logError('Error firing user syncs', e); } // Reset the user sync queue queue = getDefaultQueue(); @@ -109,7 +106,7 @@ export function newUserSync(userSyncDependencies) { // Randomize the order of the pixels before firing // This is to avoid giving any bidder who has registered multiple syncs // any preferential treatment and balancing them out - shuffle(queue).forEach((sync) => { + utils.shuffle(queue).forEach((sync) => { fn(sync); hasFiredBidder.add(sync[0]); }); @@ -126,9 +123,9 @@ export function newUserSync(userSyncDependencies) { } forEachFire(queue.image, (sync) => { let [bidderName, trackingPixelUrl] = sync; - logMessage(`Invoking image pixel user sync for bidder: ${bidderName}`); + utils.logMessage(`Invoking image pixel user sync for bidder: ${bidderName}`); // Create image object and add the src url - triggerPixel(trackingPixelUrl); + utils.triggerPixel(trackingPixelUrl); }); } @@ -141,21 +138,11 @@ export function newUserSync(userSyncDependencies) { if (!(permittedPixels.iframe)) { return; } - forEachFire(queue.iframe, (sync) => { let [bidderName, iframeUrl] = sync; - logMessage(`Invoking iframe user sync for bidder: ${bidderName}`); + utils.logMessage(`Invoking iframe user sync for bidder: ${bidderName}`); // Insert iframe into DOM - insertUserSyncIframe(iframeUrl); - // for a bidder, if iframe sync is present then remove image pixel - removeImagePixelsForBidder(queue, bidderName); - }); - } - - function removeImagePixelsForBidder(queue, iframeSyncBidderName) { - queue.image = queue.image.filter(imageSync => { - let imageSyncBidderName = imageSync[0]; - return imageSyncBidderName !== iframeSyncBidderName + utils.insertUserSyncIframe(iframeUrl); }); } @@ -190,21 +177,21 @@ export function newUserSync(userSyncDependencies) { */ publicApi.registerSync = (type, bidder, url) => { if (hasFiredBidder.has(bidder)) { - return logMessage(`already fired syncs for "${bidder}", ignoring registerSync call`); + return utils.logMessage(`already fired syncs for "${bidder}", ignoring registerSync call`); } - if (!usConfig.syncEnabled || !isArray(queue[type])) { - return logWarn(`User sync type "${type}" not supported`); + if (!usConfig.syncEnabled || !utils.isArray(queue[type])) { + return utils.logWarn(`User sync type "${type}" not supported`); } if (!bidder) { - return logWarn(`Bidder is required for registering sync`); + return utils.logWarn(`Bidder is required for registering sync`); } if (usConfig.syncsPerBidder !== 0 && Number(numAdapterBids[bidder]) >= usConfig.syncsPerBidder) { - return logWarn(`Number of user syncs exceeded for "${bidder}"`); + return utils.logWarn(`Number of user syncs exceeded for "${bidder}"`); } const canBidderRegisterSync = publicApi.canBidderRegisterSync(type, bidder); if (!canBidderRegisterSync) { - return logWarn(`Bidder "${bidder}" not permitted to register their "${type}" userSync pixels.`); + return utils.logWarn(`Bidder "${bidder}" not permitted to register their "${type}" userSync pixels.`); } // the bidder's pixel has passed all checks and is allowed to register @@ -251,7 +238,7 @@ export function newUserSync(userSyncDependencies) { */ function isFilterConfigValid(filterConfig, type) { if (filterConfig.all && filterConfig[type]) { - logWarn(`Detected presence of the "filterSettings.all" and "filterSettings.${type}" in userSync config. You cannot mix "all" with "iframe/image" configs; they are mutually exclusive.`); + utils.logWarn(`Detected presence of the "filterSettings.all" and "filterSettings.${type}" in userSync config. You cannot mix "all" with "iframe/image" configs; they are mutually exclusive.`); return false; } @@ -268,12 +255,12 @@ export function newUserSync(userSyncDependencies) { let biddersField = activeConfig.bidders; if (filterField && filterField !== 'include' && filterField !== 'exclude') { - logWarn(`UserSync "filterSettings.${activeConfigName}.filter" setting '${filterField}' is not a valid option; use either 'include' or 'exclude'.`); + utils.logWarn(`UserSync "filterSettings.${activeConfigName}.filter" setting '${filterField}' is not a valid option; use either 'include' or 'exclude'.`); return false; } - if (biddersField !== '*' && !(Array.isArray(biddersField) && biddersField.length > 0 && biddersField.every(bidderInList => isStr(bidderInList) && bidderInList !== '*'))) { - logWarn(`Detected an invalid setup in userSync "filterSettings.${activeConfigName}.bidders"; use either '*' (to represent all bidders) or an array of bidders.`); + if (biddersField !== '*' && !(Array.isArray(biddersField) && biddersField.length > 0 && biddersField.every(bidderInList => utils.isStr(bidderInList) && bidderInList !== '*'))) { + utils.logWarn(`Detected an invalid setup in userSync "filterSettings.${activeConfigName}.bidders"; use either '*' (to represent all bidders) or an array of bidders.`); return false; } @@ -315,7 +302,7 @@ export function newUserSync(userSyncDependencies) { return publicApi; } -const browserSupportsCookies = !isSafariBrowser() && storage.cookiesAreEnabled(); +const browserSupportsCookies = !utils.isSafariBrowser() && storage.cookiesAreEnabled(); export const userSync = newUserSync({ config: config.getConfig('userSync'), diff --git a/src/utils.js b/src/utils.js index 33755a4fb82..03c76529ddf 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,7 +1,8 @@ /* eslint-disable no-console */ import { config } from './config.js'; import clone from 'just-clone'; -import {find, includes} from './polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; const CONSTANTS = require('./constants.json'); @@ -20,17 +21,7 @@ let consoleLogExists = Boolean(consoleExists && window.console.log); let consoleInfoExists = Boolean(consoleExists && window.console.info); let consoleWarnExists = Boolean(consoleExists && window.console.warn); let consoleErrorExists = Boolean(consoleExists && window.console.error); - -const emitEvent = (function () { - // lazy load events to avoid circular import - let ev; - return function() { - if (ev == null) { - ev = require('./events.js'); - } - return ev.emit.apply(ev, arguments); - } -})(); +var events = require('./events.js'); // this allows stubbing of utility functions that are used internally by other utility functions export const internal = { @@ -273,28 +264,14 @@ export function logWarn() { if (debugTurnedOn() && consoleWarnExists) { console.warn.apply(console, decorateLog(arguments, 'WARNING:')); } - emitEvent(CONSTANTS.EVENTS.AUCTION_DEBUG, {type: 'WARNING', arguments: arguments}); + events.emit(CONSTANTS.EVENTS.AUCTION_DEBUG, {type: 'WARNING', arguments: arguments}); } export function logError() { if (debugTurnedOn() && consoleErrorExists) { console.error.apply(console, decorateLog(arguments, 'ERROR:')); } - emitEvent(CONSTANTS.EVENTS.AUCTION_DEBUG, {type: 'ERROR', arguments: arguments}); -} - -export function prefixLog(prefix) { - function decorate(fn) { - return function (...args) { - fn(prefix, ...args); - } - } - return { - logError: decorate(logError), - logWarn: decorate(logWarn), - logMessage: decorate(logMessage), - logInfo: decorate(logInfo), - } + events.emit(CONSTANTS.EVENTS.AUCTION_DEBUG, {type: 'ERROR', arguments: arguments}); } function decorateLog(args, prefix) { @@ -504,43 +481,16 @@ export function insertElement(elm, doc, target, asLastChildChild) { } catch (e) {} } -/** - * Returns a promise that completes when the given element triggers a 'load' or 'error' DOM event, or when - * `timeout` milliseconds have elapsed. - * - * @param {HTMLElement} element - * @param {Number} [timeout] - * @returns {Promise} - */ -export function waitForElementToLoad(element, timeout) { - let timer = null; - return new Promise((resolve) => { - const onLoad = function() { - element.removeEventListener('load', onLoad); - element.removeEventListener('error', onLoad); - if (timer != null) { - window.clearTimeout(timer); - } - resolve(); - }; - element.addEventListener('load', onLoad); - element.addEventListener('error', onLoad); - if (timeout != null) { - timer = window.setTimeout(onLoad, timeout); - } - }); -} - /** * Inserts an image pixel with the specified `url` for cookie sync * @param {string} url URL string of the image pixel to load * @param {function} [done] an optional exit callback, used when this usersync pixel is added during an async process - * @param {Number} [timeout] an optional timeout in milliseconds for the image to load before calling `done` */ -export function triggerPixel(url, done, timeout) { +export function triggerPixel(url, done) { const img = new Image(); if (done && internal.isFn(done)) { - waitForElementToLoad(img, timeout).then(done); + img.addEventListener('load', done); + img.addEventListener('error', done); } img.src = url; } @@ -588,18 +538,18 @@ export function insertHtmlIntoIframe(htmlCode) { * @param {string} url URL to be requested * @param {string} encodeUri boolean if URL should be encoded before inserted. Defaults to true * @param {function} [done] an optional exit callback, used when this usersync pixel is added during an async process - * @param {Number} [timeout] an optional timeout in milliseconds for the iframe to load before calling `done` */ -export function insertUserSyncIframe(url, done, timeout) { +export function insertUserSyncIframe(url, done) { let iframeHtml = internal.createTrackPixelIframeHtml(url, false, 'allow-scripts allow-same-origin'); let div = document.createElement('div'); div.innerHTML = iframeHtml; let iframe = div.firstChild; if (done && internal.isFn(done)) { - waitForElementToLoad(iframe, timeout).then(done); + iframe.addEventListener('load', done); + iframe.addEventListener('error', done); } internal.insertElement(iframe, document, 'html', true); -} +}; /** * Creates a snippet of HTML that retrieves the specified `url` @@ -706,7 +656,7 @@ export function getKeyByValue(obj, value) { export function getBidderCodes(adUnits = $$PREBID_GLOBAL$$.adUnits) { // this could memoize adUnits return adUnits.map(unit => unit.bids.map(bid => bid.bidder) - .reduce(flatten, [])).reduce(flatten, []).filter(uniques); + .reduce(flatten, [])).reduce(flatten).filter(uniques); } export function isGptPubadsDefined() { @@ -907,6 +857,12 @@ export function isValidMediaTypes(mediaTypes) { return true; } +export function getBidderRequest(bidRequests, bidder, adUnitCode) { + return find(bidRequests, request => { + return request.bids + .filter(bid => bid.bidder === bidder && bid.adUnitCode === adUnitCode).length > 0; + }) || { start: null, auctionId: null }; +} /** * Returns user configured bidder params from adunit * @param {Object} adUnits @@ -1254,21 +1210,15 @@ export function buildUrl(obj) { * This function deeply compares two objects checking for their equivalence. * @param {Object} obj1 * @param {Object} obj2 - * @param checkTypes {boolean} if set, two objects with identical properties but different constructors will *not* - * be considered equivalent. * @returns {boolean} */ -export function deepEqual(obj1, obj2, {checkTypes = false} = {}) { +export function deepEqual(obj1, obj2) { if (obj1 === obj2) return true; - else if ( - (typeof obj1 === 'object' && obj1 !== null) && - (typeof obj2 === 'object' && obj2 !== null) && - (!checkTypes || (obj1.constructor === obj2.constructor)) - ) { + else if ((typeof obj1 === 'object' && obj1 !== null) && (typeof obj2 === 'object' && obj2 !== null)) { if (Object.keys(obj1).length !== Object.keys(obj2).length) return false; for (let prop in obj1) { if (obj2.hasOwnProperty(prop)) { - if (!deepEqual(obj1[prop], obj2[prop], {checkTypes})) { + if (!deepEqual(obj1[prop], obj2[prop])) { return false; } } else { @@ -1292,20 +1242,9 @@ export function mergeDeep(target, ...sources) { mergeDeep(target[key], source[key]); } else if (isArray(source[key])) { if (!target[key]) { - Object.assign(target, { [key]: [...source[key]] }); + Object.assign(target, { [key]: source[key] }); } else if (isArray(target[key])) { - source[key].forEach(obj => { - let addItFlag = 1; - for (let i = 0; i < target[key].length; i++) { - if (deepEqual(target[key][i], obj)) { - addItFlag = 0; - break; - } - } - if (addItFlag) { - target[key].push(obj); - } - }); + target[key] = target[key].concat(source[key]); } } else { Object.assign(target, { [key]: source[key] }); @@ -1355,12 +1294,3 @@ export function cyrb53Hash(str, seed = 0) { h2 = imul(h2 ^ (h2 >>> 16), 2246822507) ^ imul(h1 ^ (h1 >>> 13), 3266489909); return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(); } - -/** - * returns a window object, which holds the provided document or null - * @param {Document} doc - * @returns {Window} - */ -export function getWindowFromDocument(doc) { - return (doc) ? doc.defaultView : null; -} diff --git a/src/video.js b/src/video.js index 977991b7134..20df7a92442 100644 --- a/src/video.js +++ b/src/video.js @@ -1,9 +1,8 @@ import adapterManager from './adapterManager.js'; -import { deepAccess, logError } from './utils.js'; +import { getBidRequest, deepAccess, logError } from './utils.js'; import { config } from '../src/config.js'; -import {includes} from './polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js'; import { hook } from './hook.js'; -import {auctionManager} from './auctionManager.js'; const VIDEO_MEDIA_TYPE = 'video'; export const OUTSTREAM = 'outstream'; @@ -29,21 +28,23 @@ export const hasNonVideoBidder = adUnit => /** * Validate that the assets required for video context are present on the bid * @param {VideoBid} bid Video bid to validate - * @param index + * @param {BidRequest[]} bidRequests All bid requests for an auction * @return {Boolean} If object is valid */ -export function isValidVideoBid(bid, {index = auctionManager.index} = {}) { - const videoMediaType = deepAccess(index.getMediaTypes(bid), 'video'); +export function isValidVideoBid(bid, bidRequests) { + const bidRequest = getBidRequest(bid.requestId, bidRequests); + + const videoMediaType = + bidRequest && deepAccess(bidRequest, 'mediaTypes.video'); const context = videoMediaType && deepAccess(videoMediaType, 'context'); - const adUnit = index.getAdUnit(bid); // if context not defined assume default 'instream' for video bids // instream bids require a vast url or vast xml content - return checkVideoBidSetup(bid, adUnit, videoMediaType, context); + return checkVideoBidSetup(bid, bidRequest, videoMediaType, context); } -export const checkVideoBidSetup = hook('sync', function(bid, adUnit, videoMediaType, context) { - if (videoMediaType && context !== OUTSTREAM) { +export const checkVideoBidSetup = hook('sync', function(bid, bidRequest, videoMediaType, context) { + if (!bidRequest || (videoMediaType && context !== OUTSTREAM)) { // xml-only video bids require a prebid cache url if (!config.getConfig('cache.url') && bid.vastXml && !bid.vastUrl) { logError(` @@ -58,7 +59,7 @@ export const checkVideoBidSetup = hook('sync', function(bid, adUnit, videoMediaT // outstream bids require a renderer on the bid or pub-defined on adunit if (context === OUTSTREAM) { - return !!(bid.renderer || (adUnit && adUnit.renderer) || videoMediaType.renderer); + return !!(bid.renderer || bidRequest.renderer || videoMediaType.renderer); } return true; diff --git a/src/videoCache.js b/src/videoCache.js index 219bca34726..9e378d90574 100644 --- a/src/videoCache.js +++ b/src/videoCache.js @@ -11,7 +11,7 @@ import { ajax } from './ajax.js'; import { config } from './config.js'; -import {auctionManager} from './auctionManager.js'; +import * as utils from './utils.js'; /** * @typedef {object} CacheableUrlBid @@ -58,11 +58,9 @@ function wrapURI(uri, impUrl) { * the bid can't be converted cleanly. * * @param {CacheableBid} bid - * @param index */ -function toStorageRequest(bid, {index = auctionManager.index} = {}) { +function toStorageRequest(bid) { const vastValue = bid.vastXml ? bid.vastXml : wrapURI(bid.vastUrl, bid.vastImpUrl); - const auction = index.getAuction(bid); let payload = { type: 'xml', @@ -74,10 +72,10 @@ function toStorageRequest(bid, {index = auctionManager.index} = {}) { payload.bidder = bid.bidder; payload.bidid = bid.requestId; payload.aid = bid.auctionId; - } - - if (auction != null) { - payload.timestamp = auction.getAuctionStart(); + // function has a thisArg set to bidderRequest for accessing the auctionStart + if (utils.isPlainObject(this) && this.hasOwnProperty('auctionStart')) { + payload.timestamp = this.auctionStart; + } } if (typeof bid.customCacheKey === 'string' && bid.customCacheKey !== '') { @@ -134,11 +132,12 @@ function shimStorageCallback(done) { * * @param {CacheableBid[]} bids A list of bid objects which should be cached. * @param {videoCacheStoreCallback} [done] An optional callback which should be executed after + * @param {BidderRequest} [bidderRequest] * the data has been stored in the cache. */ -export function store(bids, done) { +export function store(bids, done, bidderRequest) { const requestData = { - puts: bids.map(toStorageRequest) + puts: bids.map(toStorageRequest, bidderRequest) }; ajax(config.getConfig('cache.url'), shimStorageCallback(done), JSON.stringify(requestData), { diff --git a/test/.eslintrc.js b/test/.eslintrc.js index abb34438653..0ea3276dbaf 100644 --- a/test/.eslintrc.js +++ b/test/.eslintrc.js @@ -8,8 +8,7 @@ module.exports = { '$$PREBID_GLOBAL$$': false }, parserOptions: { - sourceType: 'module', - ecmaVersion: 2018 + sourceType: 'module' }, rules: { 'comma-dangle': 'off', diff --git a/test/fake-server/bundle.js b/test/fake-server/bundle.js deleted file mode 100644 index b0430458083..00000000000 --- a/test/fake-server/bundle.js +++ /dev/null @@ -1,41 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const makeBundle = require('../../gulpfile.js'); -const argv = require('yargs').argv; -const host = argv.host || 'localhost'; -const port = argv.port || 4444; -const dev = argv.dev || false; - -const REPLACE = { - 'https://ib.adnxs.com/ut/v3/prebid': `http://${host}:${port}/appnexus` -}; - -const replaceStrings = (() => { - const rules = Object.entries(REPLACE).map(([orig, repl]) => { - return [new RegExp(orig, 'g'), repl]; - }); - return function(text) { - return rules.reduce((text, [pat, repl]) => text.replace(pat, repl), text); - } -})(); - -const getBundle = (() => { - const cache = {}; - return function (modules = []) { - modules = Array.isArray(modules) ? [...modules] : [modules]; - modules.sort(); - const key = modules.join(','); - if (!cache.hasOwnProperty(key)) { - cache[key] = makeBundle(modules, dev).then(replaceStrings); - } - return cache[key]; - } -})(); - -module.exports = function (req, res, next) { - res.type('text/javascript'); - getBundle(req.query.modules).then((bundle) => { - res.write(bundle); - next(); - }).catch(next); -} diff --git a/test/fake-server/fake-responder.js b/test/fake-server/fake-responder.js index a44d02260e7..c884b00ca9c 100644 --- a/test/fake-server/fake-responder.js +++ b/test/fake-server/fake-responder.js @@ -6,6 +6,9 @@ const path = require('path'); // path to the fixture directory const fixturesPath = path.join(__dirname, 'fixtures'); +// An object storing 'Request-Response' pairs. +let REQ_RES_MAP = generateFixtures(fixturesPath); + /** * Matches 'req.body' with the responseBody pair * @param {object} requestBody - `req.body` of incoming request hitting middleware 'fakeResponder'. @@ -13,8 +16,8 @@ const fixturesPath = path.join(__dirname, 'fixtures'); */ const matchResponse = function (requestBody) { let actualUuids = []; - let reqResMap = generateFixtures(fixturesPath); - const requestResponsePairs = Object.keys(reqResMap).map(testName => reqResMap[testName]); + + const requestResponsePairs = Object.keys(REQ_RES_MAP).map(testName => REQ_RES_MAP[testName]); // delete 'uuid' property requestBody.tags.forEach(body => { @@ -35,22 +38,8 @@ const matchResponse = function (requestBody) { requestResponsePairs .forEach(reqRes => { reqRes.request.httpRequest && reqRes.request.httpRequest.body.tags.forEach(body => body.uuid && delete body.uuid) }); - const match = requestResponsePairs.filter(reqRes => reqRes.request.httpRequest && deepEqual(reqRes.request.httpRequest.body.tags, requestBody.tags)); - - try { - if (match.length === 0) { - throw new Error('No mock response found'); - } else if (match.length > 1) { - throw new Error('More than one mock response found') - } - } catch (e) { - console.error(e); - console.error('Tags:', JSON.stringify(requestBody.tags, null, 2)); - throw e; - } - // match the 'actual' requestBody with the 'expected' requestBody and find the 'responseBody' - const responseBody = match[0].response.httpResponse.body; + const responseBody = requestResponsePairs.filter(reqRes => reqRes.request.httpRequest && deepEqual(reqRes.request.httpRequest.body.tags, requestBody.tags))[0].response.httpResponse.body; // ENABLE THE FOLLOWING CODE FOR TROUBLE-SHOOTING FAKED REQUESTS; COMMENT AGAIN WHEN DONE // console.log('value found for responseBody:', responseBody); diff --git a/test/fake-server/fixtures/basic-banner/request.json b/test/fake-server/fixtures/basic-banner/request.json index 6b355cd24c0..ea85b5a6842 100644 --- a/test/fake-server/fixtures/basic-banner/request.json +++ b/test/fake-server/fixtures/basic-banner/request.json @@ -58,4 +58,4 @@ "user": {} } } -} +} \ No newline at end of file diff --git a/test/fake-server/fixtures/basic-outstream/request.json b/test/fake-server/fixtures/basic-outstream/request.json index e9f3302ab4c..611a518fc2d 100644 --- a/test/fake-server/fixtures/basic-outstream/request.json +++ b/test/fake-server/fixtures/basic-outstream/request.json @@ -20,7 +20,7 @@ "disable_psa": true, "video": { "skippable": true, - "playback_method": 2 + "playback_method": ["auto_play_sound_off"] }, "hb_source": 1 }, { @@ -40,11 +40,11 @@ "disable_psa": true, "video": { "skippable": true, - "playback_method": 2 + "playback_method": ["auto_play_sound_off"] }, "hb_source": 1 }], "user": {} } } -} +} \ No newline at end of file diff --git a/test/fake-server/index.js b/test/fake-server/index.js index e93bcfd465f..752648c6746 100644 --- a/test/fake-server/index.js +++ b/test/fake-server/index.js @@ -5,9 +5,8 @@ const morgan = require('morgan'); const bodyParser = require('body-parser'); const argv = require('yargs').argv; const fakeResponder = require('./fake-responder.js'); -const bundleMaker = require('./bundle.js'); -const PORT = argv.port || '4444'; +const PORT = argv.port || '3000'; // Initialize express app const app = express(); @@ -25,11 +24,7 @@ app.use(function(req, res, next) { next(); }); -app.get('/bundle', bundleMaker, (req, res) => { - res.send(); -}); - -app.post('/appnexus', fakeResponder, (req, res) => { +app.post('/', fakeResponder, (req, res) => { res.send(); }); diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index b0fbd7da806..908382f8daa 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -1231,7 +1231,7 @@ export function getCurrencyRates() { }; } -export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, adUnitCode, adId, status, ttl, requestId, mediaType}) { +export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, adUnitCode, adId, status, ttl, requestId}) { let bid = { 'bidderCode': bidder, 'width': '300', @@ -1259,7 +1259,6 @@ export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, ad 'hb_pb': cpm, 'foobar': '300x250' }), - 'mediaType': mediaType, 'netRevenue': true, 'currency': 'USD', 'ttl': (!ttl) ? 300 : ttl diff --git a/test/helpers/consentData.js b/test/helpers/consentData.js deleted file mode 100644 index 17ddc583f88..00000000000 --- a/test/helpers/consentData.js +++ /dev/null @@ -1,6 +0,0 @@ -import {gdprDataHandler} from 'src/adapterManager.js'; - -export function mockGdprConsent(sandbox, getConsentData = () => null) { - sandbox.stub(gdprDataHandler, 'promise').get(() => Promise.resolve(getConsentData())); - sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(getConsentData) -} diff --git a/test/helpers/indexStub.js b/test/helpers/indexStub.js deleted file mode 100644 index 2916b60ae32..00000000000 --- a/test/helpers/indexStub.js +++ /dev/null @@ -1,28 +0,0 @@ -import {AuctionIndex} from '../../src/auctionIndex.js'; - -export function stubAuctionIndex({bidRequests, bidderRequests, adUnits}) { - if (adUnits == null) { - adUnits = [] - } - if (bidderRequests == null) { - bidderRequests = [] - } - if (bidRequests != null) { - bidderRequests.push({ - bidderRequestId: 'mock-bidder-request', - bids: bidRequests - }); - } - const auction = { - getAuctionId() { - return 'mock-auction' - }, - getBidRequests() { - return bidderRequests; - }, - getAdUnits() { - return adUnits; - } - }; - return new AuctionIndex(() => ([auction])); -} diff --git a/test/helpers/prebidGlobal.js b/test/helpers/prebidGlobal.js index 94776a5242b..597076ab0db 100644 --- a/test/helpers/prebidGlobal.js +++ b/test/helpers/prebidGlobal.js @@ -1,4 +1,3 @@ window.$$PREBID_GLOBAL$$ = (window.$$PREBID_GLOBAL$$ || {}); -window.$$PREBID_GLOBAL$$.installedModules = (window.$$PREBID_GLOBAL$$.installedModules || []); window.$$PREBID_GLOBAL$$.cmd = window.$$PREBID_GLOBAL$$.cmd || []; window.$$PREBID_GLOBAL$$.que = window.$$PREBID_GLOBAL$$.que || []; diff --git a/test/helpers/syncPromise.js b/test/helpers/syncPromise.js deleted file mode 100644 index 99361bd716e..00000000000 --- a/test/helpers/syncPromise.js +++ /dev/null @@ -1,71 +0,0 @@ -const orig = {}; -['resolve', 'reject', 'all', 'race', 'allSettled'].forEach((k) => orig[k] = Promise[k].bind(Promise)) - -// Callbacks attached through Promise.resolve(value).then(...) will usually -// not execute immediately even if `value` is immediately available. This -// breaks tests that were written before promises even though they are semantically still valid. -// They can be made to work by making promises quasi-synchronous. - -export function SyncPromise(value, fail = false) { - if (value instanceof SyncPromise) { - return value; - } else if (typeof value === 'object' && typeof value.then === 'function') { - return orig.resolve(value); - } else { - Object.assign(this, { - then: function (cb, err) { - const handler = fail ? err : cb; - if (handler != null) { - return new SyncPromise(handler(value)); - } else { - return this; - } - }, - catch: function (cb) { - if (fail) { - return new SyncPromise(cb(value)) - } else { - return this; - } - }, - finally: function (cb) { - cb(); - return this; - }, - __value: fail ? {status: 'rejected', reason: value} : {status: 'fulfilled', value} - }) - } -} - -Object.assign(SyncPromise, { - resolve: (val) => new SyncPromise(val), - reject: (val) => new SyncPromise(val, true), - race: (promises) => promises.find((p) => p instanceof SyncPromise) || orig.race(promises), - allSettled: (promises) => { - if (promises.every((p) => p instanceof SyncPromise)) { - return new SyncPromise(promises.map((p) => p.__value)) - } else { - return orig.allSettled(promises); - } - }, - all: (promises) => { - if (promises.every((p) => p instanceof SyncPromise)) { - return SyncPromise.allSettled(promises).then((result) => { - const err = result.find((r) => r.status === 'rejected'); - if (err != null) { - return new SyncPromise(err.reason, true); - } else { - return new SyncPromise(result.map((r) => r.value)) - } - }) - } else { - return orig.all(promises); - } - } -}) - -export function synchronizePromise(sandbox) { - Object.keys(orig).forEach((k) => { - sandbox.stub(window.Promise, k).callsFake(SyncPromise[k]); - }) -} diff --git a/test/helpers/testing-utils.js b/test/helpers/testing-utils.js index 81f22ca471d..76e2b652a79 100644 --- a/test/helpers/testing-utils.js +++ b/test/helpers/testing-utils.js @@ -1,51 +1,13 @@ /* eslint-disable no-console */ -const {expect} = require('chai'); -const utils = { +module.exports = { host: (process.env.TEST_SERVER_HOST) ? process.env.TEST_SERVER_HOST : 'localhost', protocol: (process.env.TEST_SERVER_PROTOCOL) ? 'https' : 'http', - testPageURL: function(name) { - return `${utils.protocol}://${utils.host}:9999/test/pages/${name}` - }, waitForElement: function(elementRef, time = 2000) { let element = $(elementRef); element.waitForExist({timeout: time}); }, - switchFrame: function(frameRef) { + switchFrame: function(frameRef, frameName) { let iframe = $(frameRef); browser.switchToFrame(iframe); - }, - loadAndWaitForElement(url, selector, pause = 3000, timeout = 2000, retries = 3, attempt = 1) { - browser.url(url); - browser.pause(pause); - if (selector != null) { - try { - utils.waitForElement(selector, timeout); - } catch (e) { - if (attempt < retries) { - utils.loadAndWaitForElement(url, selector, pause, timeout, retries, attempt + 1); - } - } - } - }, - setupTest({url, waitFor, expectGAMCreative = null, pause = 3000, timeout = 2000, retries = 3}, name, fn) { - describe(name, function () { - this.retries(retries); - before(() => utils.loadAndWaitForElement(url, waitFor, pause, timeout, retries)); - fn.call(this); - if (expectGAMCreative) { - expectGAMCreative = expectGAMCreative === true ? waitFor : expectGAMCreative; - it(`should render GAM creative`, () => { - utils.switchFrame(expectGAMCreative); - const creative = [ - '> a > img', // banner - '> div[class="card"]' // native - ].map((child) => `body > div[class="GoogleActiveViewElement"] ${child}`) - .join(', '); - expect($(creative).isExisting()).to.be.true; - }); - } - }); } } - -module.exports = utils; diff --git a/test/pages/banner.html b/test/pages/banner.html index 2e88d356647..75993cefb39 100644 --- a/test/pages/banner.html +++ b/test/pages/banner.html @@ -7,7 +7,7 @@ Prebid.js Banner Example - + diff --git a/test/pages/bidderSettings.html b/test/pages/bidderSettings.html index 205fc250be1..015ad3ca45f 100644 --- a/test/pages/bidderSettings.html +++ b/test/pages/bidderSettings.html @@ -1,7 +1,7 @@ - + + + - + - +
'}, + {ad: '
'}, ], adomain: ['advertiserdomain.com'] }, native: { - ad: '<\!DOCTYPE html>↵ ↵ ↵ ↵ ↵
↵ ', + ad: '↵ ↵ ↵ ↵ ↵
↵ ', beacon: '', cpm: 36.0008, displaytype: '1', @@ -357,78 +311,6 @@ describe('AdgenerationAdapter', function () { creativeid: '1k2kv35vsa5r', dealid: 'fd5sa5fa7f', ttl: 1000 - }, - upperBillboard: { - 'ad': '<\!DOCTYPE html>\n \n \n \n \n \n \n \n
\n \n
\n \n', - 'beacon': '', - 'beaconurl': 'https://tg.socdm.com/bc/v3?b=Y2hzbT0yOTQsNGZiM2NkNWVpZD0xNDMwMzgmcG9zPVNTUExPQyZhZD0xMjMzMzIzLzI2MTA2MS4yNjU3OTkuMTIzMzMyMy8yMTY2NDY2LzE1NDQxMC8xNDMwMzg6U1NQTE9DOiovaWR4PTA7ZHNwaWQ9MTtkaTI9MjEzNC0xMzI4NjRfbmV3Zm9ybWF0X3Rlc3Q7ZnR5cGU9Mztwcj15TXB3O3ByYj15UTtwcm89eVE7cHJvYz1KUFk7Y3JkMnk9MTExLjkyO2NyeTJkPTAuMDA4OTM0OTUzNTM4MjQxNjAxMztwcnY9aWp6QVZtWW9wbmJUV1B0cWhtZEN1ZWRXNDd0MjU1MEtmYjFWYmI3SzsmZXg9MTYzMzMyNzU4MyZjdD0xNjMzMzI3NTgzODAzJnNyPWh0dHA-&xuid=Xm8Q8cCo5r8AAHCCMg0AAAAA&ctsv=m-ad240&seqid=be38bdb4-74a7-14a7-3439-b7f1ea8b4f33&seqtime=1633327583803&seqctx=gat3by5hZy5mdHlwZaEz&t=.gif', - 'cpm': 80, - 'creative_params': {}, - 'creativeid': 'ScaleOut_2146187', - 'dealid': '2134-132864_newformat_test', - 'displaytype': '1', - 'h': 180, - 'ids': { - 'anid': '', - 'diid': '', - 'idfa': '', - 'soc': 'Xm8Q8cCo5r8AAHCCMg0AAAAA' - }, - 'location_params': { - 'option': { - 'ad_type': 'upper_billboard' - } - }, - 'locationid': '143038', - 'results': [ - { - 'ad': '<\!DOCTYPE html>\n \n \n \n \n \n \n \n
\n \n
\n \n', - 'beacon': '', - 'beaconurl': 'https://tg.socdm.com/bc/v3?b=Y2hzbT0yOTQsNGZiM2NkNWVpZD0xNDMwMzgmcG9zPVNTUExPQyZhZD0xMjMzMzIzLzI2MTA2MS4yNjU3OTkuMTIzMzMyMy8yMTY2NDY2LzE1NDQxMC8xNDMwMzg6U1NQTE9DOiovaWR4PTA7ZHNwaWQ9MTtkaTI9MjEzNC0xMzI4NjRfbmV3Zm9ybWF0X3Rlc3Q7ZnR5cGU9Mztwcj15TXB3O3ByYj15UTtwcm89eVE7cHJvYz1KUFk7Y3JkMnk9MTExLjkyO2NyeTJkPTAuMDA4OTM0OTUzNTM4MjQxNjAxMztwcnY9aWp6QVZtWW9wbmJUV1B0cWhtZEN1ZWRXNDd0MjU1MEtmYjFWYmI3SzsmZXg9MTYzMzMyNzU4MyZjdD0xNjMzMzI3NTgzODAzJnNyPWh0dHA-&xuid=Xm8Q8cCo5r8AAHCCMg0AAAAA&ctsv=m-ad240&seqid=be38bdb4-74a7-14a7-3439-b7f1ea8b4f33&seqtime=1633327583803&seqctx=gat3by5hZy5mdHlwZaEz&t=.gif', - 'cpm': 80, - 'creative_params': {}, - 'creativeid': 'ScaleOut_2146187', - 'dealid': '2134-132864_newformat_test', - 'h': 180, - 'landing_url': 'https://supership.jp/', - 'rparams': {}, - 'scheduleid': '1233323', - 'trackers': { - 'imp': [ - 'https://tg.socdm.com/bc/v3?b=Y2hzbT0yOTQsNGZiM2NkNWVpZD0xNDMwMzgmcG9zPVNTUExPQyZhZD0xMjMzMzIzLzI2MTA2MS4yNjU3OTkuMTIzMzMyMy8yMTY2NDY2LzE1NDQxMC8xNDMwMzg6U1NQTE9DOiovaWR4PTA7ZHNwaWQ9MTtkaTI9MjEzNC0xMzI4NjRfbmV3Zm9ybWF0X3Rlc3Q7ZnR5cGU9Mztwcj15TXB3O3ByYj15UTtwcm89eVE7cHJvYz1KUFk7Y3JkMnk9MTExLjkyO2NyeTJkPTAuMDA4OTM0OTUzNTM4MjQxNjAxMztwcnY9aWp6QVZtWW9wbmJUV1B0cWhtZEN1ZWRXNDd0MjU1MEtmYjFWYmI3SzsmZXg9MTYzMzMyNzU4MyZjdD0xNjMzMzI3NTgzODAzJnNyPWh0dHA-&xuid=Xm8Q8cCo5r8AAHCCMg0AAAAA&ctsv=m-ad240&seqid=be38bdb4-74a7-14a7-3439-b7f1ea8b4f33&seqtime=1633327583803&seqctx=gat3by5hZy5mdHlwZaEz&t=.gif' - ], - 'viewable_imp': [ - 'https://tg.socdm.com/aux/inview?creative_id=2166466&ctsv=m-ad240&extra_field=idx%3D0%3Bdspid%3D1%3Bdi2%3D2134-132864_newformat_test%3Bftype%3D3%3Bprb%3D0%3Bpro%3D0%3Bproc%3DJPY%3Bcrd2y%3D111.92%3Bcry2d%3D0.0089349535382416013%3Bsspm%3D0%3Bsom%3D0.2%3Borgm%3D0%3Btechm%3D0%3Bssp_margin%3D0%3Bso_margin%3D0.2%3Borg_margin%3D0%3Btech_margin%3D0%3Bbs%3Dclassic%3B&family_id=1233323&id=143038&loglocation_id=154410&lookupname=143038%3ASSPLOC%3A*&pos=SSPLOC&schedule_id=261061.265799.1233323&seqid=be38bdb4-74a7-14a7-3439-b7f1ea8b4f33&seqtime=1633327583803&xuid=Xm8Q8cCo5r8AAHCCMg0AAAAA' - ], - 'viewable_measured': [ - 'https://tg.socdm.com/aux/measured?creative_id=2166466&ctsv=m-ad240&extra_field=idx%3D0%3Bdspid%3D1%3Bdi2%3D2134-132864_newformat_test%3Bftype%3D3%3Bprb%3D0%3Bpro%3D0%3Bproc%3DJPY%3Bcrd2y%3D111.92%3Bcry2d%3D0.0089349535382416013%3Bsspm%3D0%3Bsom%3D0.2%3Borgm%3D0%3Btechm%3D0%3Bssp_margin%3D0%3Bso_margin%3D0.2%3Borg_margin%3D0%3Btech_margin%3D0%3Bbs%3Dclassic%3B&family_id=1233323&id=143038&loglocation_id=154410&lookupname=143038%3ASSPLOC%3A*&pos=SSPLOC&schedule_id=261061.265799.1233323&seqid=be38bdb4-74a7-14a7-3439-b7f1ea8b4f33&seqtime=1633327583803&xuid=Xm8Q8cCo5r8AAHCCMg0AAAAA' - ] - }, - 'ttl': 1000, - 'vastxml': '\n \n \n SOADS\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n 00:00:15\n \n \n \n \n \n \n \n \n \n \n \n \n https://i.socdm.com/a/2/2095/2091787/20210810043037-de3e74aec30f36.mp4\n https://i.socdm.com/a/2/2095/2091788/20210810043037-6dd368dc91d507.mp4\n https://i.socdm.com/a/2/2095/2091789/20210810043037-c8eb814ddd85c4.webm\n https://i.socdm.com/a/2/2095/2091790/20210810043037-0a7f74c40268ab.webm\n \n \n \n \n \n \n', - 'vcpm': 0, - 'w': 320, - 'weight': 1 - } - ], - 'rotation': '0', - 'scheduleid': '1233323', - 'sdktype': '0', - 'trackers': { - 'imp': [ - 'https://tg.socdm.com/bc/v3?b=Y2hzbT0yOTQsNGZiM2NkNWVpZD0xNDMwMzgmcG9zPVNTUExPQyZhZD0xMjMzMzIzLzI2MTA2MS4yNjU3OTkuMTIzMzMyMy8yMTY2NDY2LzE1NDQxMC8xNDMwMzg6U1NQTE9DOiovaWR4PTA7ZHNwaWQ9MTtkaTI9MjEzNC0xMzI4NjRfbmV3Zm9ybWF0X3Rlc3Q7ZnR5cGU9Mztwcj15TXB3O3ByYj15UTtwcm89eVE7cHJvYz1KUFk7Y3JkMnk9MTExLjkyO2NyeTJkPTAuMDA4OTM0OTUzNTM4MjQxNjAxMztwcnY9aWp6QVZtWW9wbmJUV1B0cWhtZEN1ZWRXNDd0MjU1MEtmYjFWYmI3SzsmZXg9MTYzMzMyNzU4MyZjdD0xNjMzMzI3NTgzODAzJnNyPWh0dHA-&xuid=Xm8Q8cCo5r8AAHCCMg0AAAAA&ctsv=m-ad240&seqid=be38bdb4-74a7-14a7-3439-b7f1ea8b4f33&seqtime=1633327583803&seqctx=gat3by5hZy5mdHlwZaEz&t=.gif' - ], - 'viewable_imp': [ - 'https://tg.socdm.com/aux/inview?creative_id=2166466&ctsv=m-ad240&extra_field=idx%3D0%3Bdspid%3D1%3Bdi2%3D2134-132864_newformat_test%3Bftype%3D3%3Bprb%3D0%3Bpro%3D0%3Bproc%3DJPY%3Bcrd2y%3D111.92%3Bcry2d%3D0.0089349535382416013%3Bsspm%3D0%3Bsom%3D0.2%3Borgm%3D0%3Btechm%3D0%3Bssp_margin%3D0%3Bso_margin%3D0.2%3Borg_margin%3D0%3Btech_margin%3D0%3Bbs%3Dclassic%3B&family_id=1233323&id=143038&loglocation_id=154410&lookupname=143038%3ASSPLOC%3A*&pos=SSPLOC&schedule_id=261061.265799.1233323&seqid=be38bdb4-74a7-14a7-3439-b7f1ea8b4f33&seqtime=1633327583803&xuid=Xm8Q8cCo5r8AAHCCMg0AAAAA' - ], - 'viewable_measured': [ - 'https://tg.socdm.com/aux/measured?creative_id=2166466&ctsv=m-ad240&extra_field=idx%3D0%3Bdspid%3D1%3Bdi2%3D2134-132864_newformat_test%3Bftype%3D3%3Bprb%3D0%3Bpro%3D0%3Bproc%3DJPY%3Bcrd2y%3D111.92%3Bcry2d%3D0.0089349535382416013%3Bsspm%3D0%3Bsom%3D0.2%3Borgm%3D0%3Btechm%3D0%3Bssp_margin%3D0%3Bso_margin%3D0.2%3Borg_margin%3D0%3Btech_margin%3D0%3Bbs%3Dclassic%3B&family_id=1233323&id=143038&loglocation_id=154410&lookupname=143038%3ASSPLOC%3A*&pos=SSPLOC&schedule_id=261061.265799.1233323&seqid=be38bdb4-74a7-14a7-3439-b7f1ea8b4f33&seqtime=1633327583803&xuid=Xm8Q8cCo5r8AAHCCMg0AAAAA' - ] - }, - 'ttl': 1000, - 'vastxml': '\n \n \n SOADS\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n 00:00:15\n \n \n \n \n \n \n \n \n \n \n \n \n https://i.socdm.com/a/2/2095/2091787/20210810043037-de3e74aec30f36.mp4\n https://i.socdm.com/a/2/2095/2091788/20210810043037-6dd368dc91d507.mp4\n https://i.socdm.com/a/2/2095/2091789/20210810043037-c8eb814ddd85c4.webm\n https://i.socdm.com/a/2/2095/2091790/20210810043037-0a7f74c40268ab.webm\n \n \n \n \n \n \n', - 'vcpm': 0, - 'w': 320, } }, emptyAdomain: { @@ -449,12 +331,12 @@ describe('AdgenerationAdapter', function () { dealid: 'fd5sa5fa7f', ttl: 1000, results: [ - {ad: '<\!DOCTYPE html>
'}, + {ad: '
'}, ], adomain: [] }, native: { - ad: '<\!DOCTYPE html>↵ ↵ ↵ ↵ ↵
↵ ', + ad: '↵ ↵ ↵ ↵ ↵
↵ ', beacon: '', cpm: 36.0008, displaytype: '1', @@ -564,11 +446,11 @@ describe('AdgenerationAdapter', function () { dealid: 'fd5sa5fa7f', ttl: 1000, results: [ - {ad: '<\!DOCTYPE html>
'}, + {ad: '
'}, ], }, native: { - ad: '<\!DOCTYPE html>↵ ↵ ↵ ↵ ↵
↵ ', + ad: '↵ ↵ ↵ ↵ ↵
↵ ', beacon: '', cpm: 36.0008, displaytype: '1', @@ -709,20 +591,7 @@ describe('AdgenerationAdapter', function () { impressionTrackers: ['https://adg-dummy-dsp.s3-ap-northeast-1.amazonaws.com/1x1.gif'] }, mediaType: NATIVE - }, - upperBillboard: { - requestId: '2f6ac468a9c15e', - cpm: 80, - width: 320, - height: 180, - creativeId: 'ScaleOut_2146187', - dealId: '2134-132864_newformat_test', - currency: 'JPY', - netRevenue: true, - ttl: 1000, - ad: ``, - adomain: ['advertiserdomain.com'] - }, + } }, emptyAdomain: { banner: { @@ -827,22 +696,46 @@ describe('AdgenerationAdapter', function () { expect(result.length).to.equal(0); }); - it('handles ADGBrowserM responses', function () { - config.setConfig({ - currency: { - adServerCurrency: 'JPY' - } - }); - const result = spec.interpretResponse({body: serverResponse.normal.upperBillboard}, bidRequests.upperBillboard)[0]; - expect(result.requestId).to.equal(bidResponses.normal.upperBillboard.requestId); - expect(result.width).to.equal(bidResponses.normal.upperBillboard.width); - expect(result.height).to.equal(bidResponses.normal.upperBillboard.height); - expect(result.creativeId).to.equal(bidResponses.normal.upperBillboard.creativeId); - expect(result.dealId).to.equal(bidResponses.normal.upperBillboard.dealId); - expect(result.currency).to.equal(bidResponses.normal.upperBillboard.currency); - expect(result.netRevenue).to.equal(bidResponses.normal.upperBillboard.netRevenue); - expect(result.ttl).to.equal(bidResponses.normal.upperBillboard.ttl); - expect(result.ad).to.equal(bidResponses.normal.upperBillboard.ad); + it('handles banner responses', function () { + const result = spec.interpretResponse({body: serverResponse.normal.banner}, bidRequests.banner)[0]; + expect(result.requestId).to.equal(bidResponses.normal.banner.requestId); + expect(result.width).to.equal(bidResponses.normal.banner.width); + expect(result.height).to.equal(bidResponses.normal.banner.height); + expect(result.creativeId).to.equal(bidResponses.normal.banner.creativeId); + expect(result.dealId).to.equal(bidResponses.normal.banner.dealId); + expect(result.currency).to.equal(bidResponses.normal.banner.currency); + expect(result.netRevenue).to.equal(bidResponses.normal.banner.netRevenue); + expect(result.ttl).to.equal(bidResponses.normal.banner.ttl); + expect(result.ad).to.equal(bidResponses.normal.banner.ad); + expect(result.meta.advertiserDomains).deep.equal(bidResponses.normal.banner.adomain); + }); + + it('handles native responses', function () { + const result = spec.interpretResponse({body: serverResponse.normal.native}, bidRequests.native)[0]; + expect(result.requestId).to.equal(bidResponses.normal.native.requestId); + expect(result.width).to.equal(bidResponses.normal.native.width); + expect(result.height).to.equal(bidResponses.normal.native.height); + expect(result.creativeId).to.equal(bidResponses.normal.native.creativeId); + expect(result.dealId).to.equal(bidResponses.normal.native.dealId); + expect(result.currency).to.equal(bidResponses.normal.native.currency); + expect(result.netRevenue).to.equal(bidResponses.normal.native.netRevenue); + expect(result.ttl).to.equal(bidResponses.normal.native.ttl); + expect(result.native.title).to.equal(bidResponses.normal.native.native.title); + expect(result.native.image.url).to.equal(bidResponses.normal.native.native.image.url); + expect(result.native.image.height).to.equal(bidResponses.normal.native.native.image.height); + expect(result.native.image.width).to.equal(bidResponses.normal.native.native.image.width); + expect(result.native.icon.url).to.equal(bidResponses.normal.native.native.icon.url); + expect(result.native.icon.width).to.equal(bidResponses.normal.native.native.icon.width); + expect(result.native.icon.height).to.equal(bidResponses.normal.native.native.icon.height); + expect(result.native.sponsoredBy).to.equal(bidResponses.normal.native.native.sponsoredBy); + expect(result.native.body).to.equal(bidResponses.normal.native.native.body); + expect(result.native.cta).to.equal(bidResponses.normal.native.native.cta); + expect(decodeURIComponent(result.native.privacyLink)).to.equal(bidResponses.normal.native.native.privacyLink); + expect(result.native.clickUrl).to.equal(bidResponses.normal.native.native.clickUrl); + expect(result.native.impressionTrackers[0]).to.equal(bidResponses.normal.native.native.impressionTrackers[0]); + expect(result.native.clickTrackers[0]).to.equal(bidResponses.normal.native.native.clickTrackers[0]); + expect(result.mediaType).to.equal(bidResponses.normal.native.mediaType); + expect(result.meta.advertiserDomains).deep.equal(bidResponses.normal.native.adomain); }); it('handles banner responses for empty adomain', function () { diff --git a/test/spec/modules/adhashBidAdapter_spec.js b/test/spec/modules/adhashBidAdapter_spec.js deleted file mode 100644 index 40bf354c4d9..00000000000 --- a/test/spec/modules/adhashBidAdapter_spec.js +++ /dev/null @@ -1,217 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/adhashBidAdapter.js'; - -describe('adhashBidAdapter', function () { - describe('isBidRequestValid', function () { - const validBid = { - bidder: 'adhash', - params: { - publisherId: '0xc3b09b27e9c6ef73957901aa729b9e69e5bbfbfb', - platformURL: 'https://adhash.com/p/struma/' - }, - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - adUnitCode: 'adunit-code', - sizes: [[300, 250]], - bidId: '12345678901234', - bidderRequestId: '98765432109876', - auctionId: '01234567891234', - }; - - it('should return true when all mandatory parameters are there', function () { - expect(spec.isBidRequestValid(validBid)).to.equal(true); - }); - - it('should return false when there are no params', function () { - const bid = { ...validBid }; - delete bid.params; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when unsupported media type is requested', function () { - const bid = { ...validBid }; - bid.mediaTypes = { native: { sizes: [[300, 250]] } }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when publisherId is not a string', function () { - const bid = { ...validBid }; - bid.params.publisherId = 123; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when publisherId is not valid', function () { - const bid = { ...validBid }; - bid.params.publisherId = 'short string'; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when publisherId is not a string', function () { - const bid = { ...validBid }; - bid.params.platformURL = 123; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when publisherId is not valid', function () { - const bid = { ...validBid }; - bid.params.platformURL = 'https://'; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - const bidRequest = { - params: { - publisherId: '0xc3b09b27e9c6ef73957901aa729b9e69e5bbfbfb' - }, - sizes: [[300, 250]], - adUnitCode: 'adUnitCode' - }; - it('should build the request correctly', function () { - const result = spec.buildRequests( - [ bidRequest ], - { gdprConsent: { gdprApplies: true, consentString: 'example' }, refererInfo: { referer: 'http://example.com/' } } - ); - expect(result.length).to.equal(1); - expect(result[0].method).to.equal('POST'); - expect(result[0].url).to.equal('https://bidder.adhash.com/rtb?version=1.0&prebid=true&publisher=0xc3b09b27e9c6ef73957901aa729b9e69e5bbfbfb'); - expect(result[0].bidRequest).to.equal(bidRequest); - expect(result[0].data).to.have.property('timezone'); - expect(result[0].data).to.have.property('location'); - expect(result[0].data).to.have.property('publisherId'); - expect(result[0].data).to.have.property('size'); - expect(result[0].data).to.have.property('navigator'); - expect(result[0].data).to.have.property('creatives'); - expect(result[0].data).to.have.property('blockedCreatives'); - expect(result[0].data).to.have.property('currentTimestamp'); - expect(result[0].data).to.have.property('recentAds'); - }); - it('should build the request correctly without referer', function () { - const result = spec.buildRequests([ bidRequest ], { gdprConsent: { gdprApplies: true, consentString: 'example' } }); - expect(result.length).to.equal(1); - expect(result[0].method).to.equal('POST'); - expect(result[0].url).to.equal('https://bidder.adhash.com/rtb?version=1.0&prebid=true&publisher=0xc3b09b27e9c6ef73957901aa729b9e69e5bbfbfb'); - expect(result[0].bidRequest).to.equal(bidRequest); - expect(result[0].data).to.have.property('timezone'); - expect(result[0].data).to.have.property('location'); - expect(result[0].data).to.have.property('publisherId'); - expect(result[0].data).to.have.property('size'); - expect(result[0].data).to.have.property('navigator'); - expect(result[0].data).to.have.property('creatives'); - expect(result[0].data).to.have.property('blockedCreatives'); - expect(result[0].data).to.have.property('currentTimestamp'); - expect(result[0].data).to.have.property('recentAds'); - }); - }); - - describe('interpretResponse', function () { - const request = { - data: { some: 'data' }, - bidRequest: { - bidId: '12345678901234', - adUnitCode: 'adunit-code', - sizes: [[300, 250]], - params: { - platformURL: 'https://adhash.com/p/struma/' - } - } - }; - - let bodyStub; - - const serverResponse = { - body: { - creatives: [{ costEUR: 1.234 }], - advertiserDomains: 'adhash.com', - badWords: [ - ['onqjbeq1', 'full', 1], - ['onqjbeq2', 'partial', 1], - ['tbbqjbeq', 'full', -1], - ], - maxScore: 2 - } - }; - - afterEach(function() { - bodyStub && bodyStub.restore(); - }); - - it('should interpret the response correctly', function () { - const result = spec.interpretResponse(serverResponse, request); - expect(result.length).to.equal(1); - expect(result[0].requestId).to.equal('12345678901234'); - expect(result[0].cpm).to.equal(1.234); - expect(result[0].width).to.equal(300); - expect(result[0].height).to.equal(250); - expect(result[0].creativeId).to.equal('adunit-code'); - expect(result[0].netRevenue).to.equal(true); - expect(result[0].currency).to.equal('EUR'); - expect(result[0].ttl).to.equal(60); - expect(result[0].meta.advertiserDomains).to.eql(['adhash.com']); - }); - - it('should return empty array when there are bad words (full)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { - return 'example text badWord1 badWord1 example badWord1 text' + ' word'.repeat(493); - }); - expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); - }); - - it('should return empty array when there are bad words (partial)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { - return 'example text partialBadWord2 badword2 example BadWord2text' + ' word'.repeat(494); - }); - expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); - }); - - it('should return non-empty array when there are not enough bad words (full)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { - return 'example text badWord1 badWord1 example text' + ' word'.repeat(494); - }); - expect(spec.interpretResponse(serverResponse, request).length).to.equal(1); - }); - - it('should return non-empty array when there are not enough bad words (partial)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { - return 'example text partialBadWord2 example' + ' word'.repeat(496); - }); - expect(spec.interpretResponse(serverResponse, request).length).to.equal(1); - }); - - it('should return non-empty array when there are no-bad word matches', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { - return 'example text partialBadWord1 example text' + ' word'.repeat(495); - }); - expect(spec.interpretResponse(serverResponse, request).length).to.equal(1); - }); - - it('should return non-empty array when there are bad words and good words', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { - return 'example text badWord1 badWord1 example badWord1 goodWord goodWord ' + ' word'.repeat(492); - }); - expect(spec.interpretResponse(serverResponse, request).length).to.equal(1); - }); - - it('should return non-empty array when there is a problem with the brand-safety', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { - return null; - }); - expect(spec.interpretResponse(serverResponse, request).length).to.equal(1); - }); - - it('should return empty array when there are no creatives returned', function () { - expect(spec.interpretResponse({body: {creatives: []}}, request).length).to.equal(0); - }); - - it('should return empty array when there is no creatives key in the response', function () { - expect(spec.interpretResponse({body: {}}, request).length).to.equal(0); - }); - - it('should return empty array when something is not right', function () { - expect(spec.interpretResponse(null, request).length).to.equal(0); - }); - }); -}); diff --git a/test/spec/modules/adheseBidAdapter_spec.js b/test/spec/modules/adheseBidAdapter_spec.js index 3fe0a62b2a0..78ca25d6be2 100644 --- a/test/spec/modules/adheseBidAdapter_spec.js +++ b/test/spec/modules/adheseBidAdapter_spec.js @@ -1,6 +1,5 @@ import {expect} from 'chai'; import {spec} from 'modules/adheseBidAdapter.js'; -import {config} from 'src/config.js'; const BID_ID = 456; const TTL = 360; @@ -132,21 +131,12 @@ describe('AdheseAdapter', function () { expect(JSON.parse(req.data)).to.not.have.key('eids'); }); - it('should request vast content as url by default', function () { + it('should request vast content as url', function () { let req = spec.buildRequests([ minimalBid() ], bidderRequest); expect(JSON.parse(req.data).vastContentAsUrl).to.equal(true); }); - it('should request vast content as markup when configured', function () { - sinon.stub(config, 'getConfig').withArgs('adhese').returns({ vastContentAsUrl: false }); - - let req = spec.buildRequests([ minimalBid() ], bidderRequest); - - expect(JSON.parse(req.data).vastContentAsUrl).to.equal(false); - config.getConfig.restore(); - }); - it('should include bids', function () { let bid = minimalBid(); let req = spec.buildRequests([ bid ], bidderRequest); @@ -165,22 +155,6 @@ describe('AdheseAdapter', function () { expect(req.url).to.equal('https://ads-demo.adhese.com/json'); }); - - it('should include params specified in the config', function () { - sinon.stub(config, 'getConfig').withArgs('adhese').returns({ globalTargets: { 'tl': [ 'all' ] } }); - let req = spec.buildRequests([ minimalBid() ], bidderRequest); - - expect(JSON.parse(req.data).parameters).to.deep.include({ 'tl': [ 'all' ] }); - config.getConfig.restore(); - }); - - it('should give priority to bid params over config params', function () { - sinon.stub(config, 'getConfig').withArgs('adhese').returns({ globalTargets: { 'xt': ['CONFIG_CONSENT_STRING'] } }); - let req = spec.buildRequests([ minimalBid() ], bidderRequest); - - expect(JSON.parse(req.data).parameters).to.deep.include({ 'xt': [ 'CONSENT_STRING' ] }); - config.getConfig.restore(); - }); }); describe('interpretResponse', () => { diff --git a/test/spec/modules/adlooxAdServerVideo_spec.js b/test/spec/modules/adlooxAdServerVideo_spec.js index 170982a51bd..bf8fe9d43f0 100644 --- a/test/spec/modules/adlooxAdServerVideo_spec.js +++ b/test/spec/modules/adlooxAdServerVideo_spec.js @@ -3,7 +3,7 @@ import analyticsAdapter from 'modules/adlooxAnalyticsAdapter.js'; import { ajax } from 'src/ajax.js'; import { buildVideoUrl } from 'modules/adlooxAdServerVideo.js'; import { expect } from 'chai'; -import * as events from 'src/events.js'; +import events from 'src/events.js'; import { targeting } from 'src/targeting.js'; import * as utils from 'src/utils.js'; diff --git a/test/spec/modules/adlooxAnalyticsAdapter_spec.js b/test/spec/modules/adlooxAnalyticsAdapter_spec.js index 8acd02c7f26..0264922f45e 100644 --- a/test/spec/modules/adlooxAnalyticsAdapter_spec.js +++ b/test/spec/modules/adlooxAnalyticsAdapter_spec.js @@ -2,8 +2,8 @@ import adapterManager from 'src/adapterManager.js'; import analyticsAdapter, { command as analyticsCommand, COMMAND } from 'modules/adlooxAnalyticsAdapter.js'; import { AUCTION_COMPLETED } from 'src/auction.js'; import { expect } from 'chai'; -import * as events from 'src/events.js'; -import CONSTANTS from 'src/constants.json'; +import events from 'src/events.js'; +import { EVENTS } from 'src/constants.json'; import * as utils from 'src/utils.js'; import { loadExternalScriptStub } from 'test/mocks/adloaderStub.js'; @@ -35,7 +35,7 @@ describe('Adloox Analytics Adapter', function () { tagid: 0, params: { dummy1: '%%client%%', - dummy2: '%%pbadslot%%', + dummy2: '%%pbAdSlot%%', dummy3: function(bid) { throw new Error(esplode) } } }; @@ -143,10 +143,10 @@ describe('Adloox Analytics Adapter', function () { return arg.tagName === 'LINK' && arg.getAttribute('rel') === 'preload' && arg.getAttribute('as') === 'script' && href_uri.href === uri.href; }; - events.emit(CONSTANTS.EVENTS.AUCTION_END, auctionDetails); + events.emit(EVENTS.AUCTION_END, auctionDetails); expect(insertElementStub.calledWith(sinon.match(isLinkPreloadAsScript))).to.true; - events.emit(CONSTANTS.EVENTS.AUCTION_END, auctionDetails); + events.emit(EVENTS.AUCTION_END, auctionDetails); expect(insertElementStub.callCount).to.equal(1); done(); @@ -167,7 +167,7 @@ describe('Adloox Analytics Adapter', function () { const querySelectorStub = sandbox.stub(document, 'querySelector'); querySelectorStub.withArgs(`#${bid.adUnitCode}`).returns(slot); - events.emit(CONSTANTS.EVENTS.BID_WON, bid); + events.emit(EVENTS.BID_WON, bid); const [urlInserted, moduleCode] = loadExternalScriptStub.getCall(0).args; @@ -196,7 +196,7 @@ describe('Adloox Analytics Adapter', function () { const querySelectorStub = sandbox.stub(document, 'querySelector'); querySelectorStub.withArgs(`#${bid.adUnitCode}`).returns(slot); - events.emit(CONSTANTS.EVENTS.BID_WON, bidIgnore); + events.emit(EVENTS.BID_WON, bidIgnore); expect(parent.querySelector('script')).is.null; @@ -238,7 +238,7 @@ describe('Adloox Analytics Adapter', function () { it('should inject tracking event', function (done) { const data = { - eventType: CONSTANTS.EVENTS.BID_WON, + eventType: EVENTS.BID_WON, args: bid }; diff --git a/test/spec/modules/adlooxRtdProvider_spec.js b/test/spec/modules/adlooxRtdProvider_spec.js deleted file mode 100644 index b576ffb9f3b..00000000000 --- a/test/spec/modules/adlooxRtdProvider_spec.js +++ /dev/null @@ -1,313 +0,0 @@ -import adapterManager from 'src/adapterManager.js'; -import analyticsAdapter from 'modules/adlooxAnalyticsAdapter.js'; -import { config as _config } from 'src/config.js'; -import { expect } from 'chai'; -import * as events from 'src/events.js'; -import * as prebidGlobal from 'src/prebidGlobal.js'; -import { subModuleObj as rtdProvider } from 'modules/adlooxRtdProvider.js'; -import * as utils from 'src/utils.js'; - -const analyticsAdapterName = 'adloox'; - -describe('Adloox RTD Provider', function () { - let sandbox; - - const adUnit = { - code: 'ad-slot-1', - ortb2Imp: { - ext: { - data: { - pbadslot: '/123456/home/ad-slot-1' - } - } - }, - mediaTypes: { - banner: { - sizes: [ [300, 250] ] - } - }, - bids: [ - { - bidder: 'dummy' - } - ] - }; - - const analyticsOptions = { - js: 'https://j.adlooxtracking.com/ads/js/tfav_adl_%%clientid%%.js', - client: 'adlooxtest', - clientid: 127, - platformid: 0, - tagid: 0 - }; - - const config = {}; - - adapterManager.registerAnalyticsAdapter({ - code: analyticsAdapterName, - adapter: analyticsAdapter - }); - - before(function () { - sandbox = sinon.sandbox.create(); - sandbox.stub(events, 'getEvents').returns([]); - }); - - after(function () { - sandbox.restore(); - sandbox = undefined; - }); - - describe('invalid config', function () { - it('should require config', function (done) { - const ret = rtdProvider.init(); - - expect(ret).is.false; - - done(); - }); - - it('should reject non-object config.params', function (done) { - const ret = rtdProvider.init({ params: null }); - - expect(ret).is.false; - - done(); - }); - - it('should reject non-string config.params.api_origin', function (done) { - const ret = rtdProvider.init({ params: { api_origin: null } }); - - expect(ret).is.false; - - done(); - }); - - it('should reject less than one config.params.imps', function (done) { - const ret = rtdProvider.init({ params: { imps: 0 } }); - - expect(ret).is.false; - - done(); - }); - - it('should reject negative config.params.freqcap_ip', function (done) { - const ret = rtdProvider.init({ params: { freqcap_ip: -1 } }); - - expect(ret).is.false; - - done(); - }); - - it('should reject negative integer config.params.freqcap_ipua', function (done) { - const ret = rtdProvider.init({ params: { freqcap_ipua: -1 } }); - - expect(ret).is.false; - - done(); - }); - - it('should reject non-array of integers with value greater than zero config.params.thresholds', function (done) { - const ret = rtdProvider.init({ params: { thresholds: [ 70, null ] } }); - - expect(ret).is.false; - - done(); - }); - - it('should reject non-boolean config.params.slotinpath', function (done) { - const ret = rtdProvider.init({ params: { slotinpath: null } }); - - expect(ret).is.false; - - done(); - }); - - it('should reject invalid config.params.params (legacy/deprecated)', function (done) { - const ret = rtdProvider.init({ params: { params: { clientid: 0, tagid: 0 } } }); - - expect(ret).is.false; - - done(); - }); - }); - - describe('process segments', function () { - before(function () { - adapterManager.enableAnalytics({ - provider: analyticsAdapterName, - options: analyticsOptions - }); - expect(analyticsAdapter.context).is.not.null; - }); - - after(function () { - analyticsAdapter.disableAnalytics(); - expect(analyticsAdapter.context).is.null; - }); - - let server = null; - let __config = null, CONFIG = null; - let getConfigStub, setConfigStub; - beforeEach(function () { - server = sinon.createFakeServer(); - __config = {}; - CONFIG = utils.deepClone(config); - getConfigStub = sinon.stub(_config, 'getConfig').callsFake(function (path) { - return utils.deepAccess(__config, path); - }); - setConfigStub = sinon.stub(_config, 'setConfig').callsFake(function (obj) { - utils.mergeDeep(__config, obj); - }); - }); - afterEach(function () { - setConfigStub.restore(); - getConfigStub.restore(); - getConfigStub = setConfigStub = undefined; - CONFIG = null; - __config = null; - server.restore(); - server = null; - }); - - it('should fetch segments', function (done) { - const adUnitWithSegments = utils.deepClone(adUnit); - const getGlobalStub = sinon.stub(prebidGlobal, 'getGlobal').returns({ - adUnits: [ adUnitWithSegments ] - }); - - const ret = rtdProvider.init(CONFIG); - expect(ret).is.true; - - const callback = function () { - expect(__config.ortb2.site.ext.data.adloox_rtd.ok).is.true; - expect(__config.ortb2.site.ext.data.adloox_rtd.nope).is.undefined; - expect(__config.ortb2.user.ext.data.adloox_rtd.unused).is.false; - expect(__config.ortb2.user.ext.data.adloox_rtd.nope).is.undefined; - expect(adUnitWithSegments.ortb2Imp.ext.data.adloox_rtd.dis.length).is.equal(3); - expect(adUnitWithSegments.ortb2Imp.ext.data.adloox_rtd.nope).is.undefined; - - getGlobalStub.restore(); - - done(); - }; - rtdProvider.getBidRequestData({}, callback, CONFIG, null); - - const request = server.requests[0]; - const response = { unused: false, _: [ { d: 77 } ] }; - request.respond(200, { 'content-type': 'application/json' }, JSON.stringify(response)); - }); - - it('should set ad server targeting', function (done) { - utils.deepSetValue(__config, 'ortb2.site.ext.data.adloox_rtd.ok', true); - - const adUnitWithSegments = utils.deepClone(adUnit); - utils.deepSetValue(adUnitWithSegments, 'ortb2Imp.ext.data.adloox_rtd.dis', [ 50, 60 ]); - const getGlobalStub = sinon.stub(prebidGlobal, 'getGlobal').returns({ - adUnits: [ adUnitWithSegments ] - }); - - const targetingData = rtdProvider.getTargetingData([ adUnitWithSegments.code ], CONFIG); - expect(Object.keys(targetingData).length).is.equal(1); - expect(Object.keys(targetingData[adUnit.code]).length).is.equal(2); - expect(targetingData[adUnit.code].adl_ok).is.equal(1); - expect(targetingData[adUnit.code].adl_dis.length).is.equal(2); - - getGlobalStub.restore(); - - done(); - }); - }); - - describe('measure atf', function () { - const adUnitCopy = utils.deepClone(adUnit); - - const ratio = 0.38; - const [ [width, height] ] = utils.getAdUnitSizes(adUnitCopy); - - before(function () { - adapterManager.enableAnalytics({ - provider: analyticsAdapterName, - options: analyticsOptions - }); - expect(analyticsAdapter.context).is.not.null; - }); - - after(function () { - analyticsAdapter.disableAnalytics(); - expect(analyticsAdapter.context).is.null; - }); - - it(`should return ${ratio} for same-origin`, function (done) { - const el = document.createElement('div'); - el.setAttribute('id', adUnitCopy.code); - - const offset = height * ratio; - const elStub = sinon.stub(el, 'getBoundingClientRect').returns({ - top: 0 - (height - offset), - bottom: height - offset, - left: 0, - right: width - }); - - const querySelectorStub = sinon.stub(document, 'querySelector'); - querySelectorStub.withArgs(`#${adUnitCopy.code}`).returns(el); - - rtdProvider.atf(adUnitCopy, function(x) { - expect(x).is.equal(ratio); - - querySelectorStub.restore(); - elStub.restore(); - - done(); - }); - }); - - ('IntersectionObserver' in window ? it : it.skip)(`should return ${ratio} for cross-origin`, function (done) { - const frameElementStub = sinon.stub(window, 'frameElement').value(null); - - const el = document.createElement('div'); - el.setAttribute('id', adUnitCopy.code); - - const elStub = sinon.stub(el, 'getBoundingClientRect').returns({ - top: 0, - bottom: height, - left: 0, - right: width - }); - - const querySelectorStub = sinon.stub(document, 'querySelector'); - querySelectorStub.withArgs(`#${adUnitCopy.code}`).returns(el); - - let intersectionObserverStubFn = null; - const intersectionObserverStub = sinon.stub(window, 'IntersectionObserver').callsFake((fn) => { - intersectionObserverStubFn = fn; - return { - observe: (element) => { - expect(element).is.equal(el); - - intersectionObserverStubFn([{ - target: element, - intersectionRect: { width, height }, - intersectionRatio: ratio - }]); - }, - unobserve: (element) => { - expect(element).is.equal(el); - } - } - }); - - rtdProvider.atf(adUnitCopy, function(x) { - expect(x).is.equal(ratio); - - intersectionObserverStub.restore(); - querySelectorStub.restore(); - elStub.restore(); - frameElementStub.restore(); - - done(); - }); - }); - }); -}); diff --git a/test/spec/modules/admanBidAdapter_spec.js b/test/spec/modules/admanBidAdapter_spec.js deleted file mode 100644 index feee8e39b45..00000000000 --- a/test/spec/modules/admanBidAdapter_spec.js +++ /dev/null @@ -1,338 +0,0 @@ -import {expect} from 'chai'; -import {spec} from '../../../modules/admanBidAdapter.js'; -import {deepClone} from '../../../src/utils' - -describe('AdmanAdapter', function () { - let bidBanner = { - bidId: '2dd581a2b6281d', - bidder: 'adman', - bidderRequestId: '145e1d6a7837c9', - params: { - placementId: 0 - }, - placementCode: 'placementid_0', - auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62', - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '0', - hp: 1, - rid: 'bidrequestid', - // name: 'alladsallthetime', - domain: 'example.com' - } - ] - } - }; - - let bidVideo = deepClone({ - ...bidBanner, - params: { - placementId: 0, - traffic: 'video' - }, - mediaTypes: { - video: { - playerSize: [300, 250] - } - } - }); - - let bidderRequest = { - bidderCode: 'adman', - auctionId: 'fffffff-ffff-ffff-ffff-ffffffffffff', - bidderRequestId: 'ffffffffffffff', - start: 1472239426002, - auctionStart: 1472239426000, - timeout: 5000, - uspConsent: '1YN-', - gdprConsent: 'gdprConsent', - refererInfo: { - referer: 'http://www.example.com', - reachedTop: true, - }, - bids: [bidBanner, bidVideo] - } - - describe('isBidRequestValid', function () { - it('Should return true when placementId can be cast to a number', function () { - expect(spec.isBidRequestValid(bidBanner)).to.be.true; - }); - it('Should return false when placementId is not a number', function () { - bidBanner.params.placementId = 'aaa'; - expect(spec.isBidRequestValid(bidBanner)).to.be.false; - bidBanner.params.placementId = 0; - }); - }); - - describe('buildRequests', function () { - let serverRequest = spec.buildRequests([bidBanner], bidderRequest); - it('Creates a ServerRequest object with method, URL and data', function () { - expect(serverRequest).to.exist; - expect(serverRequest.method).to.exist; - expect(serverRequest.url).to.exist; - expect(serverRequest.data).to.exist; - }); - it('Returns POST method', function () { - expect(serverRequest.method).to.equal('POST'); - }); - it('Returns valid URL', function () { - expect(serverRequest.url).to.equal('https://pub.admanmedia.com/?c=o&m=multi'); - }); - it('Should contain ccpa', function() { - expect(serverRequest.data.ccpa).to.be.an('string') - }) - - it('Returns valid BANNER data if array of bids is valid', function () { - serverRequest = spec.buildRequests([bidBanner], bidderRequest); - let data = serverRequest.data; - expect(data).to.be.an('object'); - expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'ccpa', 'gdpr'); - expect(data.deviceWidth).to.be.a('number'); - expect(data.deviceHeight).to.be.a('number'); - expect(data.language).to.be.a('string'); - expect(data.secure).to.be.within(0, 1); - expect(data.host).to.be.a('string'); - expect(data.page).to.be.a('string'); - let placements = data['placements']; - for (let i = 0; i < placements.length; i++) { - let placement = placements[i]; - expect(placement).to.have.all.keys('placementId', 'eids', 'bidId', 'traffic', 'sizes', 'schain', 'bidFloor'); - expect(placement.schain).to.be.an('object') - expect(placement.placementId).to.be.a('number'); - expect(placement.bidId).to.be.a('string'); - expect(placement.traffic).to.be.a('string'); - expect(placement.sizes).to.be.an('array'); - expect(placement.bidFloor).to.be.an('number'); - } - }); - - it('Returns valid VIDEO data if array of bids is valid', function () { - serverRequest = spec.buildRequests([bidVideo], bidderRequest); - let data = serverRequest.data; - expect(data).to.be.an('object'); - expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'ccpa', 'gdpr'); - expect(data.deviceWidth).to.be.a('number'); - expect(data.deviceHeight).to.be.a('number'); - expect(data.language).to.be.a('string'); - expect(data.secure).to.be.within(0, 1); - expect(data.host).to.be.a('string'); - expect(data.page).to.be.a('string'); - let placements = data['placements']; - for (let i = 0; i < placements.length; i++) { - let placement = placements[i]; - expect(placement).to.have.all.keys('placementId', 'eids', 'bidId', 'traffic', 'sizes', 'schain', 'bidFloor', - 'playerSize', 'minduration', 'maxduration', 'mimes', 'protocols', 'startdelay', 'placement', 'skip', - 'skipafter', 'minbitrate', 'maxbitrate', 'delivery', 'playbackmethod', 'api', 'linearity'); - expect(placement.schain).to.be.an('object') - expect(placement.placementId).to.be.a('number'); - expect(placement.bidId).to.be.a('string'); - expect(placement.traffic).to.be.a('string'); - expect(placement.sizes).to.be.an('array'); - expect(placement.bidFloor).to.be.an('number'); - } - }); - - it('Returns empty data if no valid requests are passed', function () { - serverRequest = spec.buildRequests([]); - let data = serverRequest.data; - expect(data.placements).to.be.an('array').that.is.empty; - }); - }); - - describe('buildRequests with user ids', function () { - bidBanner.userId = {} - bidBanner.userId.uid2 = { id: 'uid2id123' }; - let serverRequest = spec.buildRequests([bidBanner], bidderRequest); - it('Returns valid data if array of bids is valid', function () { - let data = serverRequest.data; - let placements = data['placements']; - expect(data).to.be.an('object'); - for (let i = 0; i < placements.length; i++) { - let placement = placements[i]; - expect(placement).to.have.property('eids') - expect(placement.eids).to.be.an('array') - expect(placement.eids.length).to.be.equal(1) - for (let index in placement.eids) { - let v = placement.eids[index]; - expect(v).to.have.all.keys('source', 'uids') - expect(v.source).to.be.oneOf(['uidapi.com']) - expect(v.uids).to.be.an('array'); - expect(v.uids.length).to.be.equal(1) - expect(v.uids[0]).to.have.property('id') - } - } - }); - }); - - describe('interpretResponse', function () { - it('(BANNER) Returns an array of valid server responses if response object is valid', function () { - const resBannerObject = { - body: [ { - requestId: '123', - mediaType: 'banner', - cpm: 0.3, - width: 320, - height: 50, - ad: '

Hello ad

', - ttl: 1000, - creativeId: '123asd', - netRevenue: true, - currency: 'USD', - adomain: ['example.com'], - meta: { - advertiserDomains: ['google.com'], - advertiserId: 1234 - } - } ] - }; - - const serverResponses = spec.interpretResponse(resBannerObject); - - expect(serverResponses).to.be.an('array').that.is.not.empty; - for (let i = 0; i < serverResponses.length; i++) { - let dataItem = serverResponses[i]; - expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', - 'netRevenue', 'currency', 'mediaType', 'meta', 'adomain'); - expect(dataItem.requestId).to.be.a('string'); - expect(dataItem.cpm).to.be.a('number'); - expect(dataItem.width).to.be.a('number'); - expect(dataItem.height).to.be.a('number'); - expect(dataItem.ad).to.be.a('string'); - expect(dataItem.ttl).to.be.a('number'); - expect(dataItem.creativeId).to.be.a('string'); - expect(dataItem.netRevenue).to.be.a('boolean'); - expect(dataItem.currency).to.be.a('string'); - expect(dataItem.mediaType).to.be.a('string'); - expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains'); - } - }); - - it('(VIDEO) Returns an array of valid server responses if response object is valid', function () { - const resVideoObject = { - body: [ { - requestId: '123', - mediaType: 'video', - cpm: 0.3, - width: 320, - height: 50, - vastUrl: 'https://', - ttl: 1000, - creativeId: '123asd', - netRevenue: true, - currency: 'USD', - adomain: ['example.com'], - meta: { - advertiserDomains: ['google.com'], - advertiserId: 1234 - } - } ] - }; - - const serverResponses = spec.interpretResponse(resVideoObject); - - expect(serverResponses).to.be.an('array').that.is.not.empty; - for (let i = 0; i < serverResponses.length; i++) { - let dataItem = serverResponses[i]; - expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'vastUrl', 'ttl', 'creativeId', - 'netRevenue', 'currency', 'mediaType', 'meta', 'adomain'); - expect(dataItem.requestId).to.be.a('string'); - expect(dataItem.cpm).to.be.a('number'); - expect(dataItem.width).to.be.a('number'); - expect(dataItem.height).to.be.a('number'); - expect(dataItem.vastUrl).to.be.a('string'); - expect(dataItem.ttl).to.be.a('number'); - expect(dataItem.creativeId).to.be.a('string'); - expect(dataItem.netRevenue).to.be.a('boolean'); - expect(dataItem.currency).to.be.a('string'); - expect(dataItem.mediaType).to.be.a('string'); - expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains'); - } - }); - - it('(NATIVE) Returns an array of valid server responses if response object is valid', function () { - const resNativeObject = { - body: [ { - requestId: '123', - mediaType: 'native', - cpm: 0.3, - width: 320, - height: 50, - native: { - title: 'title', - image: 'image', - impressionTrackers: [ 'https://' ] - }, - ttl: 1000, - creativeId: '123asd', - netRevenue: true, - currency: 'USD', - adomain: ['example.com'], - meta: { - advertiserDomains: ['google.com'], - advertiserId: 1234 - } - } ] - }; - - const serverResponses = spec.interpretResponse(resNativeObject); - - expect(serverResponses).to.be.an('array').that.is.not.empty; - for (let i = 0; i < serverResponses.length; i++) { - let dataItem = serverResponses[i]; - expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'native', 'ttl', 'creativeId', - 'netRevenue', 'currency', 'mediaType', 'meta', 'adomain'); - expect(dataItem.requestId).to.be.a('string'); - expect(dataItem.cpm).to.be.a('number'); - expect(dataItem.width).to.be.a('number'); - expect(dataItem.height).to.be.a('number'); - expect(dataItem.native).to.be.an('object'); - expect(dataItem.ttl).to.be.a('number'); - expect(dataItem.creativeId).to.be.a('string'); - expect(dataItem.netRevenue).to.be.a('boolean'); - expect(dataItem.currency).to.be.a('string'); - expect(dataItem.mediaType).to.be.a('string'); - expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains'); - } - }); - - it('Invalid mediaType in response', function () { - const resBadObject = { - body: [ { - mediaType: 'other', - requestId: '123', - cpm: 0.3, - ttl: 1000, - creativeId: '123asd', - currency: 'USD' - } ] - }; - - const serverResponses = spec.interpretResponse(resBadObject); - - expect(serverResponses).to.be.an('array').that.is.empty; - }); - }); - - describe('getUserSyncs', function () { - const gdprConsent = { consentString: 'consentString', gdprApplies: 1 }; - const consentString = { consentString: 'consentString' } - let userSync = spec.getUserSyncs({}, {}, gdprConsent, consentString); - it('Returns valid URL and type', function () { - expect(userSync).to.be.an('array').with.lengthOf(1); - expect(userSync[0].type).to.exist; - expect(userSync[0].url).to.exist; - expect(userSync[0].type).to.be.equal('image'); - expect(userSync[0].url).to.be.equal('https://sync.admanmedia.com/image?pbjs=1&gdpr=0&gdpr_consent=consentString&ccpa_consent=consentString&coppa=0'); - }); - }); -}); diff --git a/test/spec/modules/admaruBidAdapter_spec.js b/test/spec/modules/admaruBidAdapter_spec.js deleted file mode 100644 index a45ddae108f..00000000000 --- a/test/spec/modules/admaruBidAdapter_spec.js +++ /dev/null @@ -1,124 +0,0 @@ -import { expect } from 'chai'; -import { newBidder } from 'src/adapters/bidderFactory.js'; -import { spec } from '../../../modules/admaruBidAdapter.js'; - -const ENDPOINT = 'https://p1.admaru.net/AdCall'; - -describe('Admaru Adapter', function () { - const adapter = newBidder(spec); - - describe('inherited functions', function () { - it('should exists and is a function', function () { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValidForBanner', () => { - let bid = { - 'bidder': 'admaru', - 'params': { - 'pub_id': '1234', - 'adspace_id': '1234' - }, - 'adUnitCode': 'adunit-code', - 'mediaTypes': { - 'banner': { - 'sizes': [ - [300, 250] - ] - } - }, - 'sizes': [[300, 250]], - 'bidId': '26e88c3c703e66', - 'bidderRequestId': '1a8ff729f6c1a3', - 'auctionId': 'cb65d954-ffe1-4f4a-8603-02b521c00333', - }; - - it('should return true when required params found', () => { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when required params are not passed', () => { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - wrong: 'missing pub_id or adspace_id' - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequestsForBanner', () => { - let bidRequests = [ - { - 'bidder': 'admaru', - 'params': { - 'pub_id': '1234', - 'adspace_id': '1234' - }, - 'adUnitCode': 'adunit-code', - 'mediaTypes': { - 'banner': { - 'sizes': [ - [300, 250] - ] - } - }, - 'sizes': [[300, 250]], - 'bidId': '26e88c3c703e66', - 'bidderRequestId': '1a8ff729f6c1a3', - 'auctionId': 'cb65d954-ffe1-4f4a-8603-02b521c00333' - } - ]; - - it('should add parameters to the tag', () => { - const request = spec.buildRequests(bidRequests); - const payload = request[0].data; - expect(payload.pub_id).to.equal('1234'); - expect(payload.adspace_id).to.equal('1234'); - // expect(payload.refererInfo).to.equal('{"referer": "https://www.admaru.com/test/admaru_prebid/icv_reminder/test.html","reachedTop": true,"numIframes": 1,"stack": ["https://www.admaru.com/test/admaru_prebid/icv_reminder/test.html","https://www.admaru.com/test/admaru_prebid/icv_reminder/test.html"]}'); - // expect(payload.os).to.equal('windows'); - // expect(payload.platform).to.equal('pc_web'); - expect(payload.bidderRequestId).to.equal('1a8ff729f6c1a3'); - expect(payload.bidId).to.equal('26e88c3c703e66'); - }); - - it('sends bid request to ENDPOINT via GET', () => { - const request = spec.buildRequests(bidRequests); - expect(request[0].url).to.contain(ENDPOINT); - expect(request[0].method).to.equal('GET'); - }); - }); - - describe('interpretResponseForBanner', () => { - let bidRequests = [ - { - 'bidder': 'admaru', - 'params': { - 'pub_id': '1234', - 'adspace_id': '1234' - }, - 'adUnitCode': 'adunit-code', - 'mediaTypes': { - 'banner': { - 'sizes': [ - [300, 250] - ] - } - }, - 'sizes': [[300, 250]], - 'bidId': '26e88c3c703e66', - 'bidderRequestId': '1a8ff729f6c1a3', - 'auctionId': 'cb65d954-ffe1-4f4a-8603-02b521c00333' - } - ]; - - it('handles nobid responses', () => { - var request = spec.buildRequests(bidRequests); - let response = ''; - - let result = spec.interpretResponse(response, request[0]); - expect(result.length).to.equal(0); - }); - }); -}); diff --git a/test/spec/modules/admixerBidAdapter_spec.js b/test/spec/modules/admixerBidAdapter_spec.js index 6dfde0d0652..27dc895e3a4 100644 --- a/test/spec/modules/admixerBidAdapter_spec.js +++ b/test/spec/modules/admixerBidAdapter_spec.js @@ -67,7 +67,7 @@ describe('AdmixerAdapter', function () { it('should add referrer and imp to be equal bidRequest', function () { const request = spec.buildRequests(validRequest, bidderRequest); - const payload = request.data; + const payload = JSON.parse(request.data.substr(5)); expect(payload.referrer).to.not.be.undefined; expect(payload.imps[0]).to.deep.equal(validRequest[0]); }); @@ -75,7 +75,7 @@ describe('AdmixerAdapter', function () { it('sends bid request to ENDPOINT via GET', function () { const request = spec.buildRequests(validRequest, bidderRequest); expect(request.url).to.equal(ENDPOINT_URL); - expect(request.method).to.equal('POST'); + expect(request.method).to.equal('GET'); }); it('sends bid request to CUSTOM_ENDPOINT via GET', function () { @@ -85,7 +85,7 @@ describe('AdmixerAdapter', function () { }); const request = config.runWithBidder(BIDDER_CODE, () => spec.buildRequests(validRequest, bidderRequest)); expect(request.url).to.equal(ENDPOINT_URL_CUSTOM); - expect(request.method).to.equal('POST'); + expect(request.method).to.equal('GET'); }); }); diff --git a/test/spec/modules/adnuntiusBidAdapter_spec.js b/test/spec/modules/adnuntiusBidAdapter_spec.js index 25b72216395..e2682b8d0d5 100644 --- a/test/spec/modules/adnuntiusBidAdapter_spec.js +++ b/test/spec/modules/adnuntiusBidAdapter_spec.js @@ -11,7 +11,7 @@ describe('adnuntiusBidAdapter', function () { const GVLID = 855; const usi = utils.generateUUID() const meta = [{ key: 'usi', value: usi }] - const storage = getStorageManager({gvlid: GVLID, moduleName: 'adnuntius'}) + const storage = getStorageManager(GVLID, 'adnuntius') storage.setDataInLocalStorage('adn.metaData', JSON.stringify(meta)) afterEach(function () { @@ -19,7 +19,6 @@ describe('adnuntiusBidAdapter', function () { }); const tzo = new Date().getTimezoneOffset(); const ENDPOINT_URL = `${URL}${tzo}&format=json&userId=${usi}`; - const ENDPOINT_URL_NOCOOKIE = `${URL}${tzo}&format=json&userId=${usi}&noCookies=true`; const ENDPOINT_URL_SEGMENTS = `${URL}${tzo}&format=json&segments=segment1,segment2,segment3&userId=${usi}`; const ENDPOINT_URL_CONSENT = `${URL}${tzo}&format=json&consentString=consentString&userId=${usi}`; const adapter = newBidder(spec); @@ -200,108 +199,6 @@ describe('adnuntiusBidAdapter', function () { expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL); }); - - it('should pass segments if available in config', function () { - config.setBidderConfig({ - bidders: ['adnuntius', 'other'], - config: { - ortb2: { - user: { - data: [{ - name: 'adnuntius', - segment: [{ id: 'segment1' }, { id: 'segment2' }] - }, - { - name: 'other', - segment: ['segment3'] - }], - } - } - } - }); - - const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidRequests)); - expect(request.length).to.equal(1); - expect(request[0]).to.have.property('url') - expect(request[0].url).to.equal(ENDPOINT_URL_SEGMENTS); - }); - - it('should skip segments in config if not either id or array of strings', function () { - config.setBidderConfig({ - bidders: ['adnuntius', 'other'], - config: { - ortb2: { - user: { - data: [{ - name: 'adnuntius', - segment: [{ id: 'segment1' }, { id: 'segment2' }, { id: 'segment3' }] - }, - { - name: 'other', - segment: [{ - notright: 'segment4' - }] - }], - } - } - } - }); - - const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidRequests)); - expect(request.length).to.equal(1); - expect(request[0]).to.have.property('url') - expect(request[0].url).to.equal(ENDPOINT_URL_SEGMENTS); - }); - - it('should user user ID if present in ortb2.user.id field', function () { - config.setBidderConfig({ - bidders: ['adnuntius', 'other'], - config: { - ortb2: { - user: { - id: usi - } - } - } - }); - - const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidRequests)); - expect(request.length).to.equal(1); - expect(request[0]).to.have.property('url') - expect(request[0].url).to.equal(ENDPOINT_URL); - }); - }); - - describe('user privacy', function () { - it('should send GDPR Consent data if gdprApplies', function () { - let request = spec.buildRequests(bidRequests, { gdprConsent: { gdprApplies: true, consentString: 'consentString' } }); - expect(request.length).to.equal(1); - expect(request[0]).to.have.property('url') - expect(request[0].url).to.equal(ENDPOINT_URL_CONSENT); - }); - - it('should not send GDPR Consent data if gdprApplies equals undefined', function () { - let request = spec.buildRequests(bidRequests, { gdprConsent: { gdprApplies: undefined, consentString: 'consentString' } }); - expect(request.length).to.equal(1); - expect(request[0]).to.have.property('url') - expect(request[0].url).to.equal(ENDPOINT_URL); - }); - }); - - describe('use cookie', function () { - it('should send noCookie in url if set to false.', function () { - config.setBidderConfig({ - bidders: ['adnuntius'], - config: { - useCookie: false - } - }); - - const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidRequests)); - expect(request.length).to.equal(1); - expect(request[0]).to.have.property('url') - expect(request[0].url).to.equal(ENDPOINT_URL_NOCOOKIE); - }); }); describe('interpretResponse', function () { diff --git a/test/spec/modules/adnuntiusRtdProvider_spec.js b/test/spec/modules/adnuntiusRtdProvider_spec.js deleted file mode 100644 index c1fcfbf298f..00000000000 --- a/test/spec/modules/adnuntiusRtdProvider_spec.js +++ /dev/null @@ -1,145 +0,0 @@ -import { adnuntiusSubmodule } from 'modules/adnuntiusRtdProvider.js'; -import { expect } from 'chai'; -import { server } from 'test/mocks/xhr.js'; -import { config as _config } from 'src/config.js'; - -const responseHeader = { 'Content-Type': 'application/json' }; - -describe('adnuntiusRtdProvider is a RTD provider that', function () { - describe('has a method `init` that', function () { - it('exists', function () { - expect(adnuntiusSubmodule.init).to.be.a('function'); - }); - it('returns false missing config params', function () { - const config = { - name: 'adnuntius', - waitForIt: true, - }; - const value = adnuntiusSubmodule.init(config); - expect(value).to.equal(false); - }); - it('returns false if missing providers param', function () { - const config = { - name: 'adnuntius', - waitForIt: true, - params: {} - }; - const value = adnuntiusSubmodule.init(config); - expect(value).to.equal(false); - }); - it('returns true if providers param included', function () { - const config = { - name: 'adnuntius', - waitForIt: true, - params: { - providers: [] - } - }; - const value = adnuntiusSubmodule.init(config); - expect(value).to.equal(true); - }); - }); - - describe('has a method `getBidRequestData` that', function () { - it('exists', function () { - expect(adnuntiusSubmodule.getBidRequestData).to.be.a('function'); - }); - it('verify config params', function () { - expect(config.name).to.not.be.undefined; - expect(config.name).to.equal('adnuntius'); - expect(config.params.providers).to.not.be.undefined; - expect(config.params).to.have.property('providers'); - expect(config.params.providers[0]).to.have.property('siteId') - expect(config.params.providers[0]).to.have.property('userId') - }); - - it('send correct request', function () { - const callback = sinon.spy(); - let request; - const adUnitsOriginal = adUnits; - adnuntiusSubmodule.getBidRequestData({ adUnits: adUnits }, callback, config); - request = server.requests[0]; - request.respond(200, responseHeader, JSON.stringify(data)); - expect(request.url).to.be.include(`&s=site123&browserId=mike`); - expect(adUnits).to.length(2); - expect(adUnits[0]).to.be.eq(adUnitsOriginal[0]); - }); - }); - - describe('has a method `setGlobalConfig` that', function () { - it('exists', function () { - expect(adnuntiusSubmodule.setGlobalConfig).to.be.a('function'); - }); - - it('sets global config', function () { - adnuntiusSubmodule.setGlobalConfig(config, concatSegments); - const globalConfig = _config.getBidderConfig() - expect(globalConfig).to.have.property('adnuntius') - expect(globalConfig.adnuntius).to.have.property('ortb2') - expect(globalConfig.adnuntius.ortb2).to.have.property('user') - expect(globalConfig.adnuntius.ortb2.user).to.have.property('data') - expect(globalConfig.adnuntius.ortb2.user.data).to.be.a('array') - expect(globalConfig.adnuntius.ortb2.user.data[0]).to.have.property('name') - expect(globalConfig.adnuntius.ortb2.user.data[0].name).to.equal('adnuntius') - expect(globalConfig.adnuntius.ortb2.user.data[0]).to.have.property('segment') - expect(globalConfig.adnuntius.ortb2.user.data[0].segment).to.be.a('array') - expect(globalConfig.adnuntius.ortb2.user.data[0].segment[0]).to.have.property('id') - expect(globalConfig.adnuntius.ortb2.user.data[0].segment[0].id).to.equal('segment2') - }); - }); -}); - -const config = { - name: 'adnuntius', - waitForIt: true, - params: { - bidders: ['adnuntius'], - providers: [{ - siteId: 'site123', - userId: 'mike' - }] - } -}; - -const adUnits = [ - { - code: 'one-div-id', - mediaTypes: { - banner: { - sizes: [970, 250] - } - }, - bids: [ - { - bidder: 'appnexus', - params: { - placementId: 12345370, - } - }] - }, - { - code: 'two-div-id', - mediaTypes: { - banner: { sizes: [300, 250] } - }, - bids: [ - { - bidder: 'appnexus', - params: { - placementId: 12345370, - } - }] - }]; - -const data = { - 'expiryEpochMillis': 1640165064285, - 'segments': [ - 'segment2', - 'segment1' - ] -}; - -const concatSegments = [ - { id: 'segment2' }, - { id: 'segment1' }, -] diff --git a/test/spec/modules/adomikAnalyticsAdapter_spec.js b/test/spec/modules/adomikAnalyticsAdapter_spec.js index d872d6f8e08..1414b2402b9 100644 --- a/test/spec/modules/adomikAnalyticsAdapter_spec.js +++ b/test/spec/modules/adomikAnalyticsAdapter_spec.js @@ -1,6 +1,5 @@ import adomikAnalytics from 'modules/adomikAnalyticsAdapter.js'; -import { expect } from 'chai'; - +import {expect} from 'chai'; let events = require('src/events'); let adapterManager = require('src/adapterManager').default; let constants = require('src/constants.json'); @@ -9,35 +8,41 @@ describe('Adomik Prebid Analytic', function () { let sendEventStub; let sendWonEventStub; let clock; - - beforeEach(function () { + before(function () { clock = sinon.useFakeTimers(); - sinon.spy(adomikAnalytics, 'track'); - sendEventStub = sinon.stub(adomikAnalytics, 'sendTypedEvent'); - sendWonEventStub = sinon.stub(adomikAnalytics, 'sendWonEvent'); - sinon.stub(events, 'getEvents').returns([]); - adomikAnalytics.currentContext = undefined; - - adapterManager.registerAnalyticsAdapter({ - code: 'adomik', - adapter: adomikAnalytics - }); }); - - afterEach(function () { - adomikAnalytics.disableAnalytics(); + after(function () { clock.restore(); - adomikAnalytics.track.restore(); - sendEventStub.restore(); - sendWonEventStub.restore(); - events.getEvents.restore(); }); - describe('adomikAnalytics.enableAnalytics', function () { + describe('enableAnalytics', function () { + beforeEach(function () { + sinon.spy(adomikAnalytics, 'track'); + sendEventStub = sinon.stub(adomikAnalytics, 'sendTypedEvent'); + sendWonEventStub = sinon.stub(adomikAnalytics, 'sendWonEvent'); + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(function () { + adomikAnalytics.track.restore(); + sendEventStub.restore(); + sendWonEventStub.restore(); + events.getEvents.restore(); + }); + + after(function () { + adomikAnalytics.disableAnalytics(); + }); + it('should catch all events', function (done) { + adapterManager.registerAnalyticsAdapter({ + code: 'adomik', + adapter: adomikAnalytics + }); + const initOptions = { id: '123456', - url: 'testurl' + url: 'testurl', }; const bid = { @@ -64,7 +69,6 @@ describe('Adomik Prebid Analytic', function () { expect(adomikAnalytics.currentContext).to.deep.equal({ uid: '123456', url: 'testurl', - sampling: undefined, id: '', timeouted: false }); @@ -75,7 +79,6 @@ describe('Adomik Prebid Analytic', function () { expect(adomikAnalytics.currentContext).to.deep.equal({ uid: '123456', url: 'testurl', - sampling: undefined, id: 'test-test-test', timeouted: false }); @@ -88,7 +91,7 @@ describe('Adomik Prebid Analytic', function () { type: 'request', event: { bidder: 'BIDDERTEST', - placementCode: '0000', + placementCode: 'placementtest', } }); @@ -136,118 +139,5 @@ describe('Adomik Prebid Analytic', function () { sinon.assert.callCount(adomikAnalytics.track, 6); }); - - describe('when sampling is undefined', function () { - beforeEach(function() { - adapterManager.enableAnalytics({ - provider: 'adomik', - options: { id: '123456', url: 'testurl' } - }); - }); - - it('is enabled', function () { - expect(adomikAnalytics.currentContext).is.not.null; - }); - }); - - describe('when sampling is 0', function () { - beforeEach(function() { - adapterManager.enableAnalytics({ - provider: 'adomik', - options: { id: '123456', url: 'testurl', sampling: 0 } - }); - }); - - it('is disabled', function () { - expect(adomikAnalytics.currentContext).to.equal(undefined); - }); - }); - - describe('when sampling is 1', function () { - beforeEach(function() { - adapterManager.enableAnalytics({ - provider: 'adomik', - options: { id: '123456', url: 'testurl', sampling: 1 } - }); - }); - - it('is enabled', function () { - expect(adomikAnalytics.currentContext).is.not.null; - }); - }); - - describe('when options is not defined', function () { - beforeEach(function() { - adapterManager.enableAnalytics({ provider: 'adomik' }); - }); - - it('is disabled', function () { - expect(adomikAnalytics.currentContext).to.equal(undefined); - }); - }); - - describe('when id is not defined in options', function () { - beforeEach(function() { - adapterManager.enableAnalytics({ provider: 'adomik', url: 'xxx' }); - }); - - it('is disabled', function () { - expect(adomikAnalytics.currentContext).to.equal(undefined); - }); - }); - - describe('when url is not defined in options', function () { - beforeEach(function() { - adapterManager.enableAnalytics({ provider: 'adomik', id: 'xxx' }); - }); - - it('is disabled', function () { - expect(adomikAnalytics.currentContext).to.equal(undefined); - }); - }); - }); - - describe('adomikAnalytics.getKeyValues', function () { - it('returns [undefined, undefined]', function () { - let [testId, testValue] = adomikAnalytics.getKeyValues() - expect(testId).to.equal(undefined); - expect(testValue).to.equal(undefined); - }); - - describe('when test is in scope', function () { - beforeEach(function () { - sessionStorage.setItem(window.location.hostname + '_AdomikTestInScope', true); - }); - - it('returns [undefined, undefined]', function () { - let [testId, testValue] = adomikAnalytics.getKeyValues() - expect(testId).to.equal(undefined); - expect(testValue).to.equal(undefined); - }); - - describe('when key values are defined', function () { - beforeEach(function () { - sessionStorage.setItem(window.location.hostname + '_AdomikTest', '{"testId":"12345","testOptionLabel":"1000"}'); - }); - - it('returns key values', function () { - let [testId, testValue] = adomikAnalytics.getKeyValues() - expect(testId).to.equal('12345'); - expect(testValue).to.equal('1000'); - }); - - describe('when preventTest is on', function () { - beforeEach(function () { - sessionStorage.setItem(window.location.hostname + '_NoAdomikTest', true); - }); - - it('returns [undefined, undefined]', function () { - let [testId, testValue] = adomikAnalytics.getKeyValues() - expect(testId).to.equal(undefined); - expect(testValue).to.equal(undefined); - }); - }); - }); - }); }); }); diff --git a/test/spec/modules/adotBidAdapter_spec.js b/test/spec/modules/adotBidAdapter_spec.js index 81b9c5e15e9..40605b17b20 100644 --- a/test/spec/modules/adotBidAdapter_spec.js +++ b/test/spec/modules/adotBidAdapter_spec.js @@ -1,333 +1,3163 @@ import { expect } from 'chai'; +import { executeRenderer } from 'src/Renderer.js'; +import * as utils from 'src/utils.js'; import { spec } from 'modules/adotBidAdapter.js'; const BIDDER_URL = 'https://dsp.adotmob.com/headerbidding/bidrequest'; describe('Adot Adapter', function () { - describe('isBidRequestValid', function () { - it('should return false if video and !isValidVideo', function () { - const bid = { mediaTypes: { video: {} } }; - const isBidRequestValid = spec.isBidRequestValid(bid); - expect(isBidRequestValid).to.equal(false); - }) - - it('should return true if video and isValidVideo', function () { - const bid = { mediaTypes: { video: { 'mimes': 1, 'protocols': 1 } } }; - const isBidRequestValid = spec.isBidRequestValid(bid); - expect(isBidRequestValid).to.equal(true); - }) - - it('should return true if !video', function () { - const bid = { mediaTypes: { banner: {} } }; - const isBidRequestValid = spec.isBidRequestValid(bid); - expect(isBidRequestValid).to.equal(true); - }) - }); + const examples = { + adUnit_banner: { + adUnitCode: 'ad_unit_banner', + bidder: 'adot', + bidderRequestId: 'bid_request_id', + bidId: 'bid_id', + params: {}, + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + } + }, - describe('buildRequests', function () { - it('should build request (banner)', function () { - const bidderRequestId = 'bidderRequestId'; - const validBidRequests = [{ bidderRequestId, mediaTypes: {} }, { bidderRequestId, bidId: 'bidId', mediaTypes: { banner: { sizes: [[300, 250]] } }, params: { placementId: 'placementId', adUnitCode: 200 } }]; - const bidderRequest = { position: 2, refererInfo: { referer: 'http://localhost.com' }, gdprConsent: { consentString: 'consentString', gdprApplies: true } }; - - const request = spec.buildRequests(validBidRequests, bidderRequest); - const buildBidRequestResponse = { - id: bidderRequestId, - imp: [{ - id: validBidRequests[1].bidId, - ext: { - placementId: validBidRequests[1].params.placementId, - adUnitCode: validBidRequests[1].adUnitCode, - container: undefined - }, - banner: { - pos: bidderRequest.position, - format: [{ w: validBidRequests[1].mediaTypes.banner.sizes[0][0], h: validBidRequests[1].mediaTypes.banner.sizes[0][1] }] - }, - bidfloorcur: 'USD', - bidfloor: 0 - }], - site: { - page: bidderRequest.refererInfo.referer, - domain: 'localhost.com', - name: 'localhost.com', - publisher: { - // id: 'adot' - id: undefined + adUnit_video_outstream: { + adUnitCode: 'ad_unit_video_outstream', + bidder: 'adot', + bidderRequestId: 'bid_request_id', + bidId: 'bid_id', + params: {}, + mediaTypes: { + video: { + context: 'outstream', + playerSize: [[300, 250]], + mimes: ['video/mp4'], + minDuration: 5, + maxDuration: 30, + protocols: [2, 3] + } + } + }, + + adUnit_video_instream: { + adUnitCode: 'ad_unit_video_instream', + bidder: 'adot', + bidderRequestId: 'bid_request_id', + bidId: 'bid_id', + params: { + video: { + instreamContext: 'pre-roll' + } + }, + mediaTypes: { + video: { + context: 'instream', + playerSize: [[300, 250]], + mimes: ['video/mp4'], + minDuration: 5, + maxDuration: 30, + protocols: [2, 3] + } + } + }, + + adUnitContext: { + refererInfo: { + referer: 'https://we-are-adot.com/test', + }, + gdprConsent: { + consentString: 'consent_string', + gdprApplies: true + } + }, + + adUnit_position: { + adUnitCode: 'ad_unit_position', + bidder: 'adot', + bidderRequestId: 'bid_request_id', + bidId: 'bid_id', + params: { + position: 1 + }, + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + } + }, + + adUnit_native: { + adUnitCode: 'ad_unit_native', + bidder: 'adot', + bidderRequestId: 'bid_request_id', + bidId: 'bid_id', + params: {}, + mediaTypes: { + native: { + title: {required: true, len: 140}, + icon: {required: true, sizes: [50, 50]}, + image: {required: false, sizes: [320, 200]}, + sponsoredBy: {required: false}, + body: {required: false}, + cta: {required: true} + } + } + }, + + serverRequest_banner: { + method: 'POST', + url: 'https://we-are-adot.com/bidrequest', + data: { + id: 'bid_request_id', + imp: [ + { + id: 'imp_id_banner_0_0', + banner: { + format: [{ + w: 300, + h: 200 + }] + }, + video: null } + ], + site: { + page: 'https://we-are-adot.com/test', + domain: 'we-are-adot.com', + name: 'we-are-adot.com' }, - device: { ua: navigator.userAgent, language: navigator.language }, - user: { ext: { consent: bidderRequest.gdprConsent.consentString } }, - regs: { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies } }, - ext: { - adot: { adapter_version: 'v2.0.0' }, - should_use_gzip: true + device: { + ua: '', + language: 'en' }, - at: 1 + user: null, + regs: null, + at: 1, + ext: { + adot: { + 'adapter_version': 'v1.0.0' + } + } + }, + _adot_internal: { + impressions: [ + { + impressionId: 'imp_id_banner_0_0', + adUnitCode: 'ad_unit_banner', + bidId: 'imp_id_banner' + } + ] } + }, - expect(request).to.deep.equal([{ - method: 'POST', - url: BIDDER_URL, - data: buildBidRequestResponse - }]) - }) - - it('should build request (native)', function () { - const bidderRequestId = 'bidderRequestId'; - const validBidRequests = [{ bidderRequestId, mediaTypes: {} }, { bidderRequestId, bidId: 'bidId', mediaTypes: { native: { title: { required: true, len: 50, sizes: [[300, 250]] }, wrong: {}, image: {} } }, params: { placementId: 'placementId', adUnitCode: 200 } }]; - const bidderRequest = { position: 2, refererInfo: { referer: 'http://localhost.com' }, gdprConsent: { consentString: 'consentString', gdprApplies: true } }; - - const request = spec.buildRequests(validBidRequests, bidderRequest); - const buildBidRequestResponse = { - id: bidderRequestId, - imp: [{ - id: validBidRequests[1].bidId, - ext: { - placementId: validBidRequests[1].params.placementId, - adUnitCode: validBidRequests[1].adUnitCode, - container: undefined + serverRequest_banner_twoImps: { + method: 'POST', + url: 'https://we-are-adot.com/bidrequest', + data: { + id: 'bid_request_id', + imp: [ + { + id: 'imp_id_banner_0_0', + banner: { + format: [{ + w: 300, + h: 200 + }] + }, + video: null }, - native: { - request: '{\"assets\":[{\"id\":1,\"required\":true,\"title\":{\"len\":50,\"wmin\":300,\"hmin\":250}},{\"id\":3,\"img\":{\"type\":3}}]}' - }, - bidfloorcur: 'USD', - bidfloor: 0 - }], + { + id: 'imp_id_banner_2_0_0', + banner: { + format: [{ + w: 300, + h: 200 + }] + }, + video: null + } + ], site: { - page: bidderRequest.refererInfo.referer, - domain: 'localhost.com', - name: 'localhost.com', - publisher: { - // id: 'adot' - id: undefined + page: 'https://we-are-adot.com/test', + domain: 'we-are-adot.com', + name: 'we-are-adot.com' + }, + device: { + ua: '', + language: 'en' + }, + user: null, + regs: null, + at: 1, + ext: { + adot: { + 'adapter_version': 'v1.0.0' + } + } + }, + _adot_internal: { + impressions: [ + { + impressionId: 'imp_id_banner_0_0', + adUnitCode: 'ad_unit_banner', + bidId: 'imp_id_banner' + }, + { + impressionId: 'imp_id_banner_2_0_0', + adUnitCode: 'ad_unit_banner_2', + bidId: 'imp_id_banner_2' + } + ] + } + }, + + serverRequest_video_instream: { + method: 'POST', + url: 'https://we-are-adot.com/bidrequest', + data: { + id: 'bid_request_id', + imp: [ + { + id: 'imp_id_video_instream_0', + banner: null, + video: { + mimes: ['video/mp4'], + w: 300, + h: 200, + startdelay: 0, + minduration: 5, + maxduration: 35, + protocols: [2, 3] + } } + ], + site: { + page: 'https://we-are-adot.com/test', + domain: 'we-are-adot.com', + name: 'we-are-adot.com' }, - device: { ua: navigator.userAgent, language: navigator.language }, - user: { ext: { consent: bidderRequest.gdprConsent.consentString } }, - regs: { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies } }, + device: { + ua: '', + language: 'en' + }, + user: null, + regs: null, + at: 1, ext: { - adot: { adapter_version: 'v2.0.0' }, - should_use_gzip: true + adot: { + 'adapter_version': 'v1.0.0' + } + } + }, + _adot_internal: { + impressions: [ + { + impressionId: 'imp_id_video_instream_0', + adUnitCode: 'ad_unit_video_instream', + bidId: 'imp_id_video_instream' + } + ] + } + }, + + serverRequest_video_outstream: { + method: 'POST', + url: 'https://we-are-adot.com/bidrequest', + data: { + id: 'bid_request_id', + imp: [ + { + id: 'imp_id_video_outstream_0', + banner: null, + video: { + mimes: ['video/mp4'], + w: 300, + h: 200, + startdelay: null, + minduration: 5, + maxduration: 35, + protocols: [2, 3] + } + } + ], + site: { + page: 'https://we-are-adot.com/test', + domain: 'we-are-adot.com', + name: 'we-are-adot.com' }, - at: 1 + device: { + ua: '', + language: 'en' + }, + user: null, + regs: null, + at: 1, + ext: { + adot: { + 'adapter_version': 'v1.0.0' + } + } + }, + _adot_internal: { + impressions: [ + { + impressionId: 'imp_id_video_outstream_0', + adUnitCode: 'ad_unit_video_outstream', + bidId: 'imp_id_video_outstream' + } + ] } + }, - expect(request).to.deep.equal([{ - method: 'POST', - url: BIDDER_URL, - data: buildBidRequestResponse - }]) - }) - - it('should build request (video)', function () { - const bidderRequestId = 'bidderRequestId'; - const validBidRequests = [{ bidderRequestId, mediaTypes: {} }, { bidderRequestId, bidId: 'bidId', mediaTypes: { video: { playerSize: [[300, 250]], minduration: 1, maxduration: 2, api: 'api', linearity: 'linearity', mimes: [], placement: 'placement', playbackmethod: 'playbackmethod', protocols: 'protocol', startdelay: 'startdelay' } }, params: { placementId: 'placementId', adUnitCode: 200 } }]; - const bidderRequest = { position: 2, refererInfo: { referer: 'http://localhost.com' }, gdprConsent: { consentString: 'consentString', gdprApplies: true } }; - - const request = spec.buildRequests(validBidRequests, bidderRequest); - const buildBidRequestResponse = { - id: bidderRequestId, - imp: [{ - id: validBidRequests[1].bidId, - ext: { - placementId: validBidRequests[1].params.placementId, - adUnitCode: validBidRequests[1].adUnitCode, - container: undefined - }, - video: { - api: 'api', - h: 250, - linearity: 'linearity', - maxduration: 2, - mimes: [], - minduration: 1, - placement: 'placement', - playbackmethod: 'playbackmethod', - pos: 0, - protocols: 'protocol', - skip: 0, - startdelay: 'startdelay', - w: 300 + serverRequest_video_instream_outstream: { + method: 'POST', + url: 'https://we-are-adot.com/bidrequest', + data: { + id: 'bid_request_id', + imp: [ + { + id: 'imp_id_video_instream_0', + banner: null, + video: { + mimes: ['video/mp4'], + w: 300, + h: 200, + startdelay: 0, + minduration: 5, + maxduration: 35, + protocols: [2, 3] + } }, - bidfloorcur: 'USD', - bidfloor: 0 - }], + { + id: 'imp_id_video_outstream_0', + banner: null, + video: { + mimes: ['video/mp4'], + w: 300, + h: 200, + startdelay: null, + minduration: 5, + maxduration: 35, + protocols: [2, 3] + } + } + ], site: { - page: bidderRequest.refererInfo.referer, - domain: 'localhost.com', - name: 'localhost.com', - publisher: { - // id: 'adot' - id: undefined + page: 'https://we-are-adot.com/test', + domain: 'we-are-adot.com', + name: 'we-are-adot.com' + }, + device: { + ua: '', + language: 'en' + }, + user: null, + regs: null, + at: 1, + ext: { + adot: { + 'adapter_version': 'v1.0.0' + } + } + }, + _adot_internal: { + impressions: [ + { + impressionId: 'imp_id_video_instream_0', + adUnitCode: 'ad_unit_video_instream', + bidId: 'imp_id_video_instream' + }, + { + impressionId: 'imp_id_video_outstream_0', + adUnitCode: 'ad_unit_video_outstream', + bidId: 'imp_id_video_outstream' + } + ] + } + }, + + serverRequest_position: { + method: 'POST', + url: 'https://we-are-adot.com/bidrequest', + data: { + id: 'bid_request_id', + imp: [ + { + id: 'imp_id_banner', + banner: { + format: [{ + w: 300, + h: 200 + }], + position: 1 + }, + video: null } + ], + site: { + page: 'https://we-are-adot.com/test', + domain: 'we-are-adot.com', + name: 'we-are-adot.com' + }, + device: { + ua: '', + language: 'en' }, - device: { ua: navigator.userAgent, language: navigator.language }, - user: { ext: { consent: bidderRequest.gdprConsent.consentString } }, - regs: { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies } }, + user: null, + regs: null, + at: 1, ext: { - adot: { adapter_version: 'v2.0.0' }, - should_use_gzip: true + adot: { + 'adapter_version': 'v1.0.0' + } + } + }, + _adot_internal: { + impressions: [ + { + impressionId: 'imp_id_banner', + adUnitCode: 'ad_unit_position' + } + ] + } + }, + + serverRequest_native: { + method: 'POST', + url: 'https://we-are-adot.com/bidrequest', + data: { + id: 'bid_request_id', + imp: [ + { + id: 'imp_id_native_0', + native: { + request: { + assets: [ + { + id: 1, + required: true, + title: { + len: 140 + } + }, + { + id: 2, + required: true, + img: { + type: 1, + wmin: 50, + hmin: 50 + } + }, + { + id: 3, + required: false, + img: { + type: 3, + wmin: 320, + hmin: 200 + } + }, + { + id: 4, + required: false, + data: { + type: 1 + } + }, + { + id: 5, + required: false, + data: { + type: 2 + } + }, + { + id: 6, + required: true, + data: { + type: 12 + } + } + ] + } + }, + video: null, + banner: null + } + ], + site: { + page: 'https://we-are-adot.com/test', + domain: 'we-are-adot.com', + name: 'we-are-adot.com' + }, + device: { + ua: '', + language: 'en' }, - at: 1 + user: null, + regs: null, + at: 1, + ext: { + adot: { + 'adapter_version': 'v1.0.0' + } + } + }, + _adot_internal: { + impressions: [ + { + impressionId: 'imp_id_native_0', + adUnitCode: 'ad_unit_native', + bidId: 'imp_id_native' + } + ] } + }, - expect(request).to.deep.equal([{ - method: 'POST', - url: BIDDER_URL, - data: buildBidRequestResponse - }]) - }) - }); + serverResponse_banner: { + body: { + cur: 'EUR', + seatbid: [ + { + bid: [ + { + impid: 'imp_id_banner_0_0', + crid: 'creative_id', + adm: 'creative_data_${AUCTION_PRICE}', + nurl: 'win_notice_url_${AUCTION_PRICE}', + price: 1.5, + h: 350, + w: 300, + ext: { + adot: { + media_type: 'banner' + } + } + } + ] + } + ] + } + }, - describe('interpretResponse', function () { - it('should return [] if !isValidResponse', function () { - const serverResponse = 'response'; - const request = 'request'; - const interpretedResponse = spec.interpretResponse(serverResponse, request); - expect(interpretedResponse).to.deep.equal([]); - }) - - it('should return [] if !isValidRequest', function () { - const serverResponse = { body: { cur: 'EUR', seatbid: [] } }; - const request = 'request'; - const interpretedResponse = spec.interpretResponse(serverResponse, request); - expect(interpretedResponse).to.deep.equal([]); - }) - - it('should return bidResponse with random media type', function () { - const impId = 'impId'; - const bid = { adm: 'adm', impid: impId, price: 2, crid: 'crid', dealid: 'dealid', adomain: 'adomain', ext: { adot: { media_type: 'media_type', size: { w: 300, h: 250 } } } } - const serverResponse = { body: { cur: 'EUR', seatbid: [{ bid: {} }, { bid: [bid] }] } }; - const request = { data: { imp: [{ id: impId }] } }; - const bidResponse = { - requestId: impId, - cpm: bid.price, - currency: serverResponse.body.cur, - ttl: 10, - creativeId: bid.crid, - netRevenue: true, - mediaType: bid.ext.adot.media_type, - dealId: bid.dealid, - meta: { advertiserDomains: bid.adomain }, - width: bid.ext.adot.size.w, - height: bid.ext.adot.size.h, - ad: bid.adm, - adUrl: null, - vastXml: null, - vastUrl: null, - renderer: null + serverResponse_banner_twoBids: { + body: { + cur: 'EUR', + seatbid: [ + { + bid: [ + { + impid: 'imp_id_banner_0_0', + crid: 'creative_id', + adm: 'creative_data_${AUCTION_PRICE}', + nurl: 'win_notice_url_${AUCTION_PRICE}', + price: 1.5, + h: 350, + w: 300, + adomain: ['adot'], + ext: { + adot: { + media_type: 'banner' + } + } + }, + { + impid: 'imp_id_banner_2_0_0', + crid: 'creative_id_2', + adm: 'creative_data_2_${AUCTION_PRICE}', + nurl: 'win_notice_url_2_${AUCTION_PRICE}', + adomain: ['adot'], + price: 2.5, + h: 400, + w: 350, + ext: { + adot: { + media_type: 'banner' + } + } + } + ] + } + ] } + }, - const interpretedResponse = spec.interpretResponse(serverResponse, request); - expect(interpretedResponse).to.deep.equal([bidResponse]); - }) - - it('should return bidResponse with native', function () { - const impId = 'impId'; - const bid = { adm: '{"native":{"assets":[{"id":1,"title":{"text":"title"}},{"id":3,"img":{"url":"url","w":300,"h":250}}],"link":{"url":"clickUrl","clicktrackers":"clicktrackers"},"imptrackers":["imptracker"],"jstracker":"jstracker"}}', impid: impId, price: 2, crid: 'crid', dealid: 'dealid', adomain: 'adomain', ext: { adot: { media_type: 'native', size: { width: 300, height: 250 } } } } - const serverResponse = { body: { cur: 'EUR', seatbid: [{ bid: {} }, { bid: [bid] }] } }; - const request = { data: { imp: [{ id: impId }] } }; - const bidResponse = { - requestId: impId, - cpm: bid.price, - currency: serverResponse.body.cur, - ttl: 10, - creativeId: bid.crid, - netRevenue: true, - mediaType: bid.ext.adot.media_type, - dealId: bid.dealid, - meta: { advertiserDomains: bid.adomain }, - native: { - title: 'title', - image: { url: 'url', width: 300, height: 250 }, - clickUrl: 'clickUrl', - clickTrackers: 'clicktrackers', - impressionTrackers: ['imptracker'], - javascriptTrackers: ['jstracker'] - } + serverResponse_video_instream: { + body: { + cur: 'EUR', + seatbid: [ + { + bid: [ + { + impid: 'imp_id_video_instream_0', + crid: 'creative_id', + adm: 'creative_data_${AUCTION_PRICE}', + nurl: 'win_notice_url_${AUCTION_PRICE}', + price: 1.5, + ext: { + adot: { + media_type: 'video' + } + } + } + ] + } + ] } + }, - const interpretedResponse = spec.interpretResponse(serverResponse, request); - expect(interpretedResponse).to.deep.equal([bidResponse]); - }) - - it('should return bidResponse with video', function () { - const impId = 'impId'; - const bid = { nurl: 'nurl', impid: impId, price: 2, crid: 'crid', dealid: 'dealid', adomain: 'adomain', ext: { adot: { media_type: 'video', size: { w: 300, h: 250 }, container: {}, adUnitCode: 20, video: { type: 'outstream' } } } } - const serverResponse = { body: { cur: 'EUR', seatbid: [{ bid: {} }, { bid: [bid] }] } }; - const request = { data: { imp: [{ id: impId }] } }; - const bidResponse = { - requestId: impId, - cpm: bid.price, - currency: serverResponse.body.cur, - ttl: 10, - creativeId: bid.crid, - netRevenue: true, - mediaType: bid.ext.adot.media_type, - dealId: bid.dealid, - meta: { advertiserDomains: bid.adomain }, - w: bid.ext.adot.size.w, - h: bid.ext.adot.size.h, - ad: null, - adUrl: bid.nurl, - vastXml: null, - vastUrl: bid.nurl + serverResponse_video_outstream: { + body: { + cur: 'EUR', + seatbid: [ + { + bid: [ + { + impid: 'imp_id_video_outstream_0', + crid: 'creative_id', + adm: 'creative_data_${AUCTION_PRICE}', + nurl: 'win_notice_url_${AUCTION_PRICE}', + price: 1.5, + ext: { + adot: { + media_type: 'video' + } + } + } + ] + } + ] + } + }, + + serverResponse_video_instream_outstream: { + body: { + cur: 'EUR', + seatbid: [ + { + bid: [ + { + impid: 'imp_id_video_instream_0', + crid: 'creative_id', + adm: 'creative_data_${AUCTION_PRICE}', + nurl: 'win_notice_url_${AUCTION_PRICE}', + price: 1.5, + ext: { + adot: { + media_type: 'video' + } + } + }, + { + impid: 'imp_id_video_outstream_0', + crid: 'creative_id', + adm: 'creative_data_${AUCTION_PRICE}', + nurl: 'win_notice_url_${AUCTION_PRICE}', + price: 1.5, + ext: { + adot: { + media_type: 'video' + } + } + } + ] + } + ] } + }, + + serverResponse_native: { + body: { + cur: 'EUR', + seatbid: [ + { + bid: [ + { + impid: 'imp_id_native_0', + crid: 'creative_id', + adm: '{"native":{"assets":[{"id":1,"title":{"len":140,"text":"Hi everyone"}},{"id":2,"img":{"url":"https://adotmob.com","type":1,"w":50,"h":50}},{"id":3,"img":{"url":"https://adotmob.com","type":3,"w":320,"h":200}},{"id":4,"data":{"type":1,"value":"adotmob"}},{"id":5,"data":{"type":2,"value":"This is a test ad"}},{"id":6,"data":{"type":12,"value":"Click to buy"}}],"link":{"url":"https://adotmob.com?auction=${AUCTION_PRICE}"}}}', + nurl: 'win_notice_url_${AUCTION_PRICE}', + price: 1.5, + ext: { + adot: { + media_type: 'native' + } + } + } + ] + } + ] + } + } + }; + + describe('isBidRequestValid', function () { + describe('General', function () { + it('should return false when not given an ad unit', function () { + const adUnit = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an invalid ad unit', function () { + const adUnit = 'bad_bid'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit without bidder code', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.bidder = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with a bad bidder code', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.bidder = 'unknownBidder'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit without ad unit code', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.adUnitCode = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid ad unit code', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.adUnitCode = {}; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit without bid request identifier', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.bidderRequestId = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid bid request identifier', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.bidderRequestId = {}; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit without impression identifier', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.bidId = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid impression identifier', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.bidId = {}; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit without media types', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with empty media types', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes = {}; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with invalid media types', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes = 'bad_media_types'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + }); + + describe('Banner', function () { + it('should return true when given a valid ad unit', function () { + const adUnit = examples.adUnit_banner; + + expect(spec.isBidRequestValid(adUnit)).to.equal(true); + }); + + it('should return true when given a valid ad unit without bidder parameters', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.params = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(true); + }); + + it('should return false when given an ad unit without size', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); - const interpretedResponse = spec.interpretResponse(serverResponse, request); - expect(interpretedResponse).to.be.an('array').and.to.have.lengthOf(1) - expect(interpretedResponse[0].requestId).to.deep.equal(bidResponse.requestId); - expect(interpretedResponse[0].cpm).to.deep.equal(bidResponse.cpm); - expect(interpretedResponse[0].currency).to.deep.equal(bidResponse.currency); - expect(interpretedResponse[0].ttl).to.deep.equal(bidResponse.ttl); - expect(interpretedResponse[0].creativeId).to.deep.equal(bidResponse.creativeId); - expect(interpretedResponse[0].netRevenue).to.deep.equal(bidResponse.netRevenue); - expect(interpretedResponse[0].mediaType).to.deep.equal(bidResponse.mediaType); - expect(interpretedResponse[0].dealId).to.deep.equal(bidResponse.dealId); - expect(interpretedResponse[0].meta).to.deep.equal(bidResponse.meta); - expect(interpretedResponse[0].width).to.deep.equal(bidResponse.w); - expect(interpretedResponse[0].height).to.deep.equal(bidResponse.h); - expect(interpretedResponse[0].ad).to.deep.equal(bidResponse.ad); - expect(interpretedResponse[0].adUrl).to.deep.equal(bidResponse.adUrl); - expect(interpretedResponse[0].vastXml).to.deep.equal(bidResponse.vastXml); - expect(interpretedResponse[0].vastUrl).to.deep.equal(bidResponse.vastUrl); - expect(interpretedResponse[0].renderer).to.be.an('object'); - }) + it('should return false when given an ad unit with an invalid size', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = 'bad_banner_size'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an empty size', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = []; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid size value', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = ['bad_banner_size_value']; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with a size value with less than 2 dimensions', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = [[300]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with a size value with more than 2 dimensions', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = [[300, 250, 30]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with a negative width value', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = [[-300, 250]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with a negative height value', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = [[300, -250]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid width value', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = [[false, 250]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid height value', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = [[300, {}]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + }); + + describe('Video', function () { + it('should return true when given a valid outstream ad unit', function () { + const adUnit = examples.adUnit_video_outstream; + + expect(spec.isBidRequestValid(adUnit)).to.equal(true); + }); + + it('should return true when given a valid pre-roll instream ad unit', function () { + const adUnit = utils.deepClone(examples.adUnit_video_instream); + adUnit.params.video.instreamContext = 'pre-roll'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(true); + }); + + it('should return true when given a valid mid-roll instream ad unit', function () { + const adUnit = utils.deepClone(examples.adUnit_video_instream); + adUnit.params.video.instreamContext = 'mid-roll'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(true); + }); + + it('should return true when given a valid post-roll instream ad unit', function () { + const adUnit = utils.deepClone(examples.adUnit_video_instream); + adUnit.params.video.instreamContext = 'post-roll'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(true); + }); + + it('should return true when given an ad unit without size', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(true); + }); + + it('should return true when given an ad unit with an empty size', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = []; + + expect(spec.isBidRequestValid(adUnit)).to.equal(true); + }); + + it('should return true when given an ad unit without minimum duration parameter', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.minDuration = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(true); + }); + + it('should return true when given an ad unit without maximum duration parameter', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.maxDuration = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(true); + }); + + it('should return false when given an ad unit without bidder parameters', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.params = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with invalid bidder parameters', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.params = 'bad_bidder_parameters'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit without video parameters', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with invalid video parameters', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video = 'bad_bidder_parameters'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit without mime types parameter', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.mimes = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid mime types parameter', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.mimes = 'bad_mime_types'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an empty mime types parameter', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.mimes = []; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid mime types parameter value', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.mimes = [200]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid minimum duration parameter', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.minDuration = 'bad_min_duration'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid maximum duration parameter', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.maxDuration = 'bad_max_duration'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit without protocols parameter', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.protocols = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid protocols parameter', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.protocols = 'bad_protocols'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an empty protocols parameter', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.protocols = []; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid protocols parameter value', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.protocols = ['bad_protocols_value']; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an instream ad unit without instream context', function () { + const adUnit = utils.deepClone(examples.adUnit_video_instream); + adUnit.params.video.instreamContext = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an instream ad unit with an invalid instream context', function () { + const adUnit = utils.deepClone(examples.adUnit_video_instream); + adUnit.params.video.instreamContext = 'bad_instream_context'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit without context', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.context = undefined; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid context', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.context = []; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an adpod ad unit', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.context = 'adpod'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an unknown context', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.context = 'invalid_context'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid size', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = 'bad_video_size'; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid size value', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = ['bad_video_size_value']; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with a size value with less than 2 dimensions', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = [[300]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with a size value with more than 2 dimensions', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = [[300, 250, 30]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with a negative width value', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = [[-300, 250]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with a negative height value', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = [[300, -250]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid width value', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = [[false, 250]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + + it('should return false when given an ad unit with an invalid height value', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = [[300, {}]]; + + expect(spec.isBidRequestValid(adUnit)).to.equal(false); + }); + }); }); - describe('getFloor', function () { - it('should return 0 if getFloor is not a function', function () { - const floor = spec.getFloor({ getFloor: 0 }); - expect(floor).to.deep.equal(0); - }) - - it('should return floor result if currency are correct', function () { - const currency = 'EUR'; - const floorResult = 2; - const fn = sinon.stub().callsFake(() => ({ currency, floor: floorResult })) - const adUnit = { getFloor: fn }; - const size = {}; - const mediaType = {}; - - const floor = spec.getFloor(adUnit, size, mediaType, currency); - expect(floor).to.deep.equal(floorResult); - expect(fn.calledOnce).to.equal(true); - expect(fn.calledWithExactly({ currency, mediaType, size })).to.equal(true); - }) - - it('should return floor result if currency are not correct', function () { - const currency = 'EUR'; - const floorResult = 2; - const fn = sinon.stub().callsFake(() => ({ currency: 'wrong_currency', floor: floorResult })) - const adUnit = { getFloor: fn }; - const size = {}; - const mediaType = {}; - - const floor = spec.getFloor(adUnit, size, mediaType, currency); - expect(floor).to.deep.equal(0); - expect(fn.calledOnce).to.equal(true); - expect(fn.calledWithExactly({ currency, mediaType, size })).to.equal(true); - }) + describe('buildRequests', function () { + describe('ServerRequest', function () { + it('should return a server request when given a valid ad unit and a valid ad unit context', function () { + const adUnits = [examples.adUnit_banner]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.length(1); + expect(serverRequests[0].method).to.exist.and.to.be.a('string').and.to.equal('POST'); + expect(serverRequests[0].url).to.exist.and.to.be.a('string').and.to.equal(BIDDER_URL); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0]._adot_internal).to.exist.and.to.be.an('object'); + expect(serverRequests[0]._adot_internal.impressions).to.exist.and.to.be.an('array').and.to.have.length(1); + expect(serverRequests[0]._adot_internal.impressions[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0]._adot_internal.impressions[0].impressionId).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0_0`); + expect(serverRequests[0]._adot_internal.impressions[0].adUnitCode).to.exist.and.to.be.a('string').and.to.equal(adUnits[0].adUnitCode); + }); + + it('should return a server request containing a position when given a valid ad unit and a valid ad unit context and a position in the bidder params', function () { + const adUnits = [examples.adUnit_position]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.length(1); + expect(serverRequests[0].method).to.exist.and.to.be.a('string').and.to.equal('POST'); + expect(serverRequests[0].url).to.exist.and.to.be.a('string').and.to.equal(BIDDER_URL); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0]._adot_internal).to.exist.and.to.be.an('object'); + expect(serverRequests[0]._adot_internal.impressions).to.exist.and.to.be.an('array').and.to.have.length(1); + expect(serverRequests[0]._adot_internal.impressions[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0]._adot_internal.impressions[0].impressionId).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0_0`); + expect(serverRequests[0]._adot_internal.impressions[0].adUnitCode).to.exist.and.to.be.a('string').and.to.equal(adUnits[0].adUnitCode); + expect(serverRequests[0].data.imp[0].banner.pos).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].params.position); + }); + + it('should return a server request when given two valid ad units and a valid ad unit context', function () { + const adUnits_1 = utils.deepClone(examples.adUnit_banner); + adUnits_1.bidId = 'bid_id_1'; + adUnits_1.adUnitCode = 'ad_unit_banner_1'; + + const adUnits_2 = utils.deepClone(examples.adUnit_banner); + adUnits_2.bidId = 'bid_id_2'; + adUnits_2.adUnitCode = 'ad_unit_banner_2'; + + const adUnits = [adUnits_1, adUnits_2]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.length(1); + expect(serverRequests[0].method).to.exist.and.to.be.a('string').and.to.equal('POST'); + expect(serverRequests[0].url).to.exist.and.to.be.a('string').and.to.equal(BIDDER_URL); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0]._adot_internal).to.exist.and.to.be.an('object'); + expect(serverRequests[0]._adot_internal.impressions).to.exist.and.to.be.an('array').and.to.have.length(2); + expect(serverRequests[0]._adot_internal.impressions[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0]._adot_internal.impressions[0].impressionId).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0_0`); + expect(serverRequests[0]._adot_internal.impressions[0].adUnitCode).to.exist.and.to.be.a('string').and.to.equal(adUnits[0].adUnitCode); + expect(serverRequests[0]._adot_internal.impressions[1]).to.exist.and.to.be.an('object'); + expect(serverRequests[0]._adot_internal.impressions[1].impressionId).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[1].bidId}_0_0`); + expect(serverRequests[0]._adot_internal.impressions[1].adUnitCode).to.exist.and.to.be.a('string').and.to.equal(adUnits[1].adUnitCode); + }); + + it('should return an empty server request list when given an empty ad unit list and a valid ad unit context', function () { + const adUnits = []; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.length(0); + }); + + it('should not return a server request when given no ad unit and a valid ad unit context', function () { + const serverRequests = spec.buildRequests(null, examples.adUnitContext); + + expect(serverRequests).to.equal(null); + }); + + it('should not return a server request when given a valid ad unit and no ad unit context', function () { + const adUnits = [examples.adUnit_banner]; + + const serverRequests = spec.buildRequests(adUnits, null); + + expect(serverRequests).to.be.an('array').and.to.have.length(1); + }); + + it('should not return a server request when given a valid ad unit and an invalid ad unit context', function () { + const adUnits = [examples.adUnit_banner]; + + const serverRequests = spec.buildRequests(adUnits, {}); + + expect(serverRequests).to.be.an('array').and.to.have.length(1); + }); + }); + + describe('BidRequest', function () { + it('should return a valid server request when given a valid ad unit', function () { + const adUnits = [examples.adUnit_banner]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.id).to.exist.and.to.be.a('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.at).to.exist.and.to.be.a('number').and.to.equal(1); + expect(serverRequests[0].data.ext).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.ext.adot).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.ext.adot.adapter_version).to.exist.and.to.be.a('string').and.to.equal('v1.0.0'); + }); + + it('should return one server request when given one valid ad unit', function () { + const adUnits = [examples.adUnit_banner]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.id).to.exist.and.to.be.a('string').and.to.equal(adUnits[0].bidderRequestId); + }); + + it('should return one server request when given two valid ad units with different impression identifiers', function () { + const adUnit_1 = utils.deepClone(examples.adUnit_banner); + adUnit_1.bidId = 'bid_id_1'; + + const adUnit_2 = utils.deepClone(examples.adUnit_banner); + adUnit_2.bidId = 'bid_id_2'; + + const adUnits = [adUnit_1, adUnit_2]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.id).to.exist.and.to.be.a('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.id).to.exist.and.to.be.a('string').and.to.equal(adUnits[1].bidderRequestId); + }); + + it('should return two server requests when given two valid ad units with different bid request identifiers', function () { + const adUnit_1 = utils.deepClone(examples.adUnit_banner); + adUnit_1.bidderRequestId = 'bidder_request_id_1'; + + const adUnit_2 = utils.deepClone(examples.adUnit_banner); + adUnit_2.bidderRequestId = 'bidder_request_id_2'; + + const adUnits = [adUnit_1, adUnit_2]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(2); + expect(serverRequests[0].data.id).to.exist.and.to.be.a('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[1].data.id).to.exist.and.to.be.a('string').and.to.equal(adUnits[1].bidderRequestId); + }); + }); + + describe('Impression', function () { + describe('Banner', function () { + it('should return a server request with one impression when given a valid ad unit', function () { + const adUnits = [examples.adUnit_banner]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0_0`); + expect(serverRequests[0].data.imp[0].banner).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].banner.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.banner.sizes[0][0]); + expect(serverRequests[0].data.imp[0].banner.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.banner.sizes[0][1]); + expect(serverRequests[0].data.imp[0].banner.format).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0].banner.format[0]).to.exist.and.to.be.an('object').and.to.deep.equal({ + w: adUnits[0].mediaTypes.banner.sizes[0][0], + h: adUnits[0].mediaTypes.banner.sizes[0][1] + }); + }); + + it('should return a server request with two impressions containing one banner formats when given a valid ad unit with two banner sizes', function () { + const adUnit = utils.deepClone(examples.adUnit_banner); + adUnit.mediaTypes.banner.sizes = [ + [300, 250], + [350, 300] + ]; + + const adUnits = [adUnit]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(2); + + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0_0`); + expect(serverRequests[0].data.imp[0].banner).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].banner.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.banner.sizes[0][0]); + expect(serverRequests[0].data.imp[0].banner.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.banner.sizes[0][1]); + expect(serverRequests[0].data.imp[0].banner.format).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0].banner.format[0]).to.exist.and.to.be.an('object').and.to.deep.equal({ + w: adUnits[0].mediaTypes.banner.sizes[0][0], + h: adUnits[0].mediaTypes.banner.sizes[0][1] + }); + + expect(serverRequests[0].data.imp[1]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[1].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0_1`); + expect(serverRequests[0].data.imp[1].banner).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[1].banner.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.banner.sizes[1][0]); + expect(serverRequests[0].data.imp[1].banner.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.banner.sizes[1][1]); + expect(serverRequests[0].data.imp[1].banner.format).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[1].banner.format[0]).to.exist.and.to.be.an('object').and.to.deep.equal({ + w: adUnits[0].mediaTypes.banner.sizes[1][0], + h: adUnits[0].mediaTypes.banner.sizes[1][1] + }); + }); + + it('should return a server request with two impressions when given two valid ad units with different impression identifiers', function () { + const adUnit_1 = utils.deepClone(examples.adUnit_banner); + adUnit_1.bidId = 'bid_id_1'; + + const adUnit_2 = utils.deepClone(examples.adUnit_banner); + adUnit_2.bidId = 'bid_id_2'; + + const adUnits = [adUnit_1, adUnit_2]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(2); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0_0`); + expect(serverRequests[0].data.imp[0].banner).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].banner.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.banner.sizes[0][0]); + expect(serverRequests[0].data.imp[0].banner.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.banner.sizes[0][1]); + expect(serverRequests[0].data.imp[0].banner.format).to.exist.and.to.be.an('array'); + expect(serverRequests[0].data.imp[0].banner.format[0]).to.exist.and.to.be.an('object').and.to.deep.equal({ + w: adUnits[0].mediaTypes.banner.sizes[0][0], + h: adUnits[0].mediaTypes.banner.sizes[0][1] + }); + expect(serverRequests[0].data.imp[1]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[1].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[1].bidId}_0_0`); + expect(serverRequests[0].data.imp[1].banner).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[1].banner.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.banner.sizes[0][0]); + expect(serverRequests[0].data.imp[1].banner.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.banner.sizes[0][1]); + expect(serverRequests[0].data.imp[1].banner.format).to.exist.and.to.be.an('array'); + expect(serverRequests[0].data.imp[1].banner.format[0]).to.exist.and.to.be.an('object').and.to.deep.equal({ + w: adUnits[1].mediaTypes.banner.sizes[0][0], + h: adUnits[1].mediaTypes.banner.sizes[0][1] + }); + }); + + it('should return a server request with one overriden impression when given two valid ad units with identical identifiers', function () { + const adUnit_1 = utils.deepClone(examples.adUnit_banner); + adUnit_1.mediaTypes.banner.sizes = [[300, 250]]; + + const adUnit_2 = utils.deepClone(examples.adUnit_banner); + adUnit_2.mediaTypes.banner.sizes = [[350, 300]]; + + const adUnits = [adUnit_1, adUnit_2]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[1].bidId}_0_0`); + expect(serverRequests[0].data.imp[0].banner).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].banner.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.banner.sizes[0][0]); + expect(serverRequests[0].data.imp[0].banner.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.banner.sizes[0][1]); + expect(serverRequests[0].data.imp[0].banner.format).to.exist.and.to.be.an('array'); + expect(serverRequests[0].data.imp[0].banner.format[0]).to.exist.and.to.be.an('object').and.to.deep.equal({ + w: adUnits[1].mediaTypes.banner.sizes[0][0], + h: adUnits[1].mediaTypes.banner.sizes[0][1] + }); + }); + + it('should return two server requests with one impression when given two valid ad units with different bid request identifiers', function () { + const adUnit_1 = utils.deepClone(examples.adUnit_banner); + adUnit_1.bidderRequestId = 'bidder_request_id_1'; + + const adUnit_2 = utils.deepClone(examples.adUnit_banner); + adUnit_2.bidderRequestId = 'bidder_request_id_2'; + + const adUnits = [adUnit_1, adUnit_2]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(2); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0_0`); + expect(serverRequests[0].data.imp[0].banner).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].banner.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.banner.sizes[0][0]); + expect(serverRequests[0].data.imp[0].banner.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.banner.sizes[0][1]); + expect(serverRequests[0].data.imp[0].banner.format).to.exist.and.to.be.an('array'); + expect(serverRequests[0].data.imp[0].banner.format[0]).to.exist.and.to.be.an('object').and.to.deep.equal({ + w: adUnits[0].mediaTypes.banner.sizes[0][0], + h: adUnits[0].mediaTypes.banner.sizes[0][1] + }); + expect(serverRequests[1].data).to.exist.and.to.be.an('object'); + expect(serverRequests[1].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[1].bidderRequestId); + expect(serverRequests[1].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[1].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[1].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[1].bidId}_0_0`); + expect(serverRequests[1].data.imp[0].banner).to.exist.and.to.be.an('object'); + expect(serverRequests[1].data.imp[0].banner.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.banner.sizes[0][0]); + expect(serverRequests[1].data.imp[0].banner.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.banner.sizes[0][1]); + expect(serverRequests[1].data.imp[0].banner.format).to.exist.and.to.be.an('array'); + expect(serverRequests[1].data.imp[0].banner.format[0]).to.exist.and.to.be.an('object').and.to.deep.equal({ + w: adUnits[1].mediaTypes.banner.sizes[0][0], + h: adUnits[1].mediaTypes.banner.sizes[0][1] + }); + }); + }); + + describe('Video', function () { + it('should return a server request with one impression when given a valid outstream ad unit', function () { + const adUnit = examples.adUnit_video_outstream; + + const adUnits = [adUnit]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.equal(null); + expect(serverRequests[0].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + }); + + it('should return a server request with one impression when given a valid pre-roll instream ad unit', function () { + const adUnit = utils.deepClone(examples.adUnit_video_instream); + adUnit.params.video.instreamContext = 'pre-roll'; + + const adUnits = [adUnit]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.exist.and.to.be.a('number').and.to.equal(0); + expect(serverRequests[0].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + }); + + it('should return a server request with one impression when given a valid mid-roll instream ad unit', function () { + const adUnit = utils.deepClone(examples.adUnit_video_instream); + adUnit.params.video.instreamContext = 'mid-roll'; + + const adUnits = [adUnit]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.exist.and.to.be.a('number').and.to.equal(-1); + expect(serverRequests[0].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + }); + + it('should return a server request with one impression when given a valid post-roll instream ad unit', function () { + const adUnit = utils.deepClone(examples.adUnit_video_instream); + adUnit.params.video.instreamContext = 'post-roll'; + + const adUnits = [adUnit]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.exist.and.to.be.a('number').and.to.equal(-2); + expect(serverRequests[0].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + }); + + it('should return a server request with one impression when given a valid ad unit without player size', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = undefined; + + const adUnits = [adUnit]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.equal(null); + expect(serverRequests[0].data.imp[0].video.w).to.equal(null); + expect(serverRequests[0].data.imp[0].video.h).to.equal(null); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + }); + + it('should return a server request with one impression when given a valid ad unit with an empty player size', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = []; + + const adUnits = [adUnit]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.equal(null); + expect(serverRequests[0].data.imp[0].video.w).to.equal(null); + expect(serverRequests[0].data.imp[0].video.h).to.equal(null); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + }); + + it('should return a server request with one impression when given a valid ad unit with multiple player sizes', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.playerSize = [[350, 300], [400, 350]]; + + const adUnits = [adUnit]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.equal(null); + expect(serverRequests[0].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + }); + + it('should return a server request with one impression when given a valid ad unit without minimum duration', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.minDuration = undefined; + + const adUnits = [adUnit]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.equal(null); + expect(serverRequests[0].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[0].video.minduration).to.equal(null); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + }); + + it('should return a server request with one impression when given a valid ad unit without maximum duration', function () { + const adUnit = utils.deepClone(examples.adUnit_video_outstream); + adUnit.mediaTypes.video.maxDuration = undefined; + + const adUnits = [adUnit]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.equal(null); + expect(serverRequests[0].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.equal(null); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + }); + + it('should return a server request with two impressions when given two valid ad units with different impression identifiers', function () { + const adUnit_1 = utils.deepClone(examples.adUnit_video_outstream); + adUnit_1.bidId = 'bid_id_1'; + + const adUnit_2 = utils.deepClone(examples.adUnit_video_outstream); + adUnit_2.bidId = 'bid_id_2'; + + const adUnits = [adUnit_1, adUnit_2]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(2); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.equal(null); + expect(serverRequests[0].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + expect(serverRequests[0].data.imp[1]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[1].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[1].bidId}_0`); + expect(serverRequests[0].data.imp[1].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[1].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[1].video.startdelay).to.equal(null); + expect(serverRequests[0].data.imp[1].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[1].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[1].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[1].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[1].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[1].mediaTypes.video.protocols); + }); + + it('should return a server request with one overridden impression when given two valid ad units with identical identifiers', function () { + const adUnit_1 = utils.deepClone(examples.adUnit_video_outstream); + adUnit_1.mediaTypes.video.minDuration = 10; + + const adUnit_2 = utils.deepClone(examples.adUnit_video_outstream); + adUnit_2.mediaTypes.video.minDuration = 15; + + const adUnits = [adUnit_1, adUnit_2]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[1].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.equal(null); + expect(serverRequests[0].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[1].mediaTypes.video.protocols); + }); + + it('should return two server requests with one impression when given two valid ad units with different bid request identifiers', function () { + const adUnit_1 = utils.deepClone(examples.adUnit_video_outstream); + adUnit_1.bidderRequestId = 'bidder_request_id_1'; + + const adUnit_2 = utils.deepClone(examples.adUnit_video_outstream); + adUnit_2.bidderRequestId = 'bidder_request_id_2'; + + const adUnits = [adUnit_1, adUnit_2]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(2); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[0].data.imp[0].video.startdelay).to.equal(null); + expect(serverRequests[0].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[0].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[0].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.minDuration); + expect(serverRequests[0].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.video.maxDuration); + expect(serverRequests[0].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.protocols); + expect(serverRequests[1].data).to.exist.and.to.be.an('object'); + expect(serverRequests[1].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[1].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[1].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[1].bidId}_0`); + expect(serverRequests[1].data.imp[0].video).to.exist.and.to.be.an('object'); + expect(serverRequests[1].data.imp[0].video.mimes).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[0].mediaTypes.video.mimes); + expect(serverRequests[1].data.imp[0].video.startdelay).to.equal(null); + expect(serverRequests[1].data.imp[0].video.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.playerSize[0][0]); + expect(serverRequests[1].data.imp[0].video.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.playerSize[0][1]); + expect(serverRequests[1].data.imp[0].video.minduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.minDuration); + expect(serverRequests[1].data.imp[0].video.maxduration).to.exist.and.to.be.a('number').and.to.equal(adUnits[1].mediaTypes.video.maxDuration); + expect(serverRequests[1].data.imp[0].video.protocols).to.exist.and.to.be.an('array').and.to.deep.equal(adUnits[1].mediaTypes.video.protocols); + }); + }); + + describe('Native', function () { + it('should return a server request with one impression when given a valid ad unit', function () { + const adUnits = [examples.adUnit_native]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnit_native); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}_0`); + expect(serverRequests[0].data.imp[0].native).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.imp[0].native.request).to.exist.and.to.be.a('string').and.to.equal(JSON.stringify(examples.serverRequest_native.data.imp[0].native.request)) + }); + }); + }); + + describe('Site', function () { + it('should return a server request with site information when given a valid ad unit and a valid ad unit context', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = examples.adUnitContext; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.site).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.site.page).to.exist.and.to.be.an('string').and.to.equal(adUnitContext.refererInfo.referer); + expect(serverRequests[0].data.site.id).to.equal(undefined); + expect(serverRequests[0].data.site.domain).to.exist.and.to.be.an('string').and.to.equal('we-are-adot.com'); + expect(serverRequests[0].data.site.name).to.exist.and.to.be.an('string').and.to.equal('we-are-adot.com'); + }); + + it('should return a server request without site information when not given an ad unit context', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = undefined; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.site).to.equal(null); + }); + + it('should return a server request without site information when given an ad unit context without referer information', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.refererInfo = undefined; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.site).to.equal(null); + }); + + it('should return a server request without site information when given an ad unit context with invalid referer information', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.refererInfo = 'bad_referer_information'; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.site).to.equal(null); + }); + + it('should return a server request without site information when given an ad unit context without referer', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.refererInfo.referer = undefined; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.site).to.equal(null); + }); + + it('should return a server request without site information when given an ad unit context with an invalid referer', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.refererInfo.referer = {}; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.site).to.equal(null); + }); + + it('should return a server request without site information when given an ad unit context with a misformatted referer', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.refererInfo.referer = 'we-are-adot'; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.site).to.equal(null); + }); + }); + + describe('Device', function () { + it('should return a server request with device information when given a valid ad unit and a valid ad unit context', function () { + const adUnits = [examples.adUnit_banner]; + + const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.device).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.device.ua).to.exist.and.to.be.a('string'); + expect(serverRequests[0].data.device.language).to.exist.and.to.be.a('string'); + }); + }); + + describe('Regs', function () { + it('should return a server request with regulations information when given a valid ad unit and a valid ad unit context with GDPR applying', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = examples.adUnitContext; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.regs).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.regs.ext).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.regs.ext.gdpr).to.exist.and.to.be.a('boolean').and.to.equal(adUnitContext.gdprConsent.gdprApplies); + }); + + it('should return a server request with regulations information when given a valid ad unit and a valid ad unit context with GDPR not applying', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.gdprConsent.gdprApplies = false; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.regs).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.regs.ext).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.regs.ext.gdpr).to.exist.and.to.be.a('boolean').and.to.equal(adUnitContext.gdprConsent.gdprApplies); + }); + + it('should return a server request without regulations information when not given an ad unit context', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = undefined; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.regs).to.equal(null); + }); + + it('should return a server request without regulations information when given an ad unit context without GDPR information', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.gdprConsent = undefined; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.regs).to.equal(null); + }); + + it('should return a server request without regulations information when given an ad unit context with invalid GDPR information', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.gdprConsent = 'bad_gdpr_consent'; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.regs).to.equal(null); + }); + + it('should return a server request without regulations information when given an ad unit context with invalid GDPR application information', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.gdprConsent.gdprApplies = 'bad_gdpr_applies'; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.regs).to.equal(null); + }); + }); + + describe('User', function () { + it('should return a server request with user information when given a valid ad unit and a valid ad unit context', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = examples.adUnitContext; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.user).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.user.ext).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.user.ext.consent).to.exist.and.to.be.a('string').and.to.equal(adUnitContext.gdprConsent.consentString); + }); + + it('should return a server request without user information when not given an ad unit context', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = undefined; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.user).to.equal(null); + }); + + it('should return a server request without user information when given an ad unit context without GDPR information', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.gdprConsent = undefined; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.user).to.equal(null); + }); + + it('should return a server request without user information when given an ad unit context with invalid GDPR information', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.gdprConsent = 'bad_gdpr_consent'; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.user).to.equal(null); + }); + + it('should return a server request without user information when given an ad unit context with an invalid consent string', function () { + const adUnits = [examples.adUnit_banner]; + + const adUnitContext = utils.deepClone(examples.adUnitContext); + adUnitContext.gdprConsent.consentString = true; + + const serverRequests = spec.buildRequests(adUnits, adUnitContext); + + expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); + expect(serverRequests[0].data).to.exist.and.to.be.an('object'); + expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); + expect(serverRequests[0].data.user).to.equal(null); + }); + }); + }); + + describe('interpretResponse', function () { + describe('General', function () { + it('should return an ad when given a valid server response with one bid with USD currency', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.cur = 'USD'; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(null); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].h); + expect(ads[0].width).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('banner'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return two ads when given a valid server response with two bids', function () { + const serverRequest = examples.serverRequest_banner_twoImps; + + const serverResponse = examples.serverResponse_banner_twoBids; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + const adm2WithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[1].adm, serverResponse.body.seatbid[0].bid[1].price); + + expect(ads).to.be.an('array').and.to.have.length(2); + + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(null); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].h); + expect(ads[0].width).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('banner'); + expect(ads[0].renderer).to.equal(null); + expect(ads[1].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[1].bidId); + expect(ads[1].ad).to.exist.and.to.be.a('string').and.to.have.string(adm2WithAuctionPriceReplaced); + expect(ads[1].adUrl).to.equal(null); + expect(ads[1].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[1].crid); + expect(ads[1].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[1].price); + expect(ads[1].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[1].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[1].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[1].height).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[1].h); + expect(ads[1].width).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[1].w); + expect(ads[1].mediaType).to.exist.and.to.be.a('string').and.to.equal('banner'); + expect(ads[1].renderer).to.equal(null); + }); + + it('should return two ads when given a valid server response with two bids that contains adomain', function () { + const serverRequest = examples.serverRequest_banner_twoImps; + + const serverResponse = examples.serverResponse_banner_twoBids; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + const adm2WithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[1].adm, serverResponse.body.seatbid[0].bid[1].price); + + expect(ads).to.be.an('array').and.to.have.length(2); + + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(null); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].meta.advertiserDomains[0]).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].adomain[0]) + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].h); + expect(ads[0].width).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('banner'); + expect(ads[0].renderer).to.equal(null); + expect(ads[1].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[1].bidId); + expect(ads[1].meta.advertiserDomains[0]).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[1].adomain[0]) + expect(ads[1].ad).to.exist.and.to.be.a('string').and.to.have.string(adm2WithAuctionPriceReplaced); + expect(ads[1].adUrl).to.equal(null); + expect(ads[1].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[1].crid); + expect(ads[1].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[1].price); + expect(ads[1].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[1].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[1].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[1].height).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[1].h); + expect(ads[1].width).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[1].w); + expect(ads[1].mediaType).to.exist.and.to.be.a('string').and.to.equal('banner'); + expect(ads[1].renderer).to.equal(null); + }); + + it('should return no ad when not given a server response', function () { + const ads = spec.interpretResponse(null); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when not given a server response body', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given an invalid server response body', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body = 'invalid_body'; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response without seat bids', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with invalid seat bids', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid = 'invalid_seat_bids'; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with an empty seat bids array', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid = []; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with an invalid seat bid', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid = 'invalid_bids'; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with an empty bids array', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid = []; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with an invalid bid', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid = ['invalid_bid']; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid without currency', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.cur = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid currency', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.cur = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid without impression identifier', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].impid = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid impression identifier', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].impid = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid without creative identifier', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].crid = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid creative identifier', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].crid = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid without ad markup and ad serving URL', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].adm = undefined; + serverResponse.body.seatbid[0].bid[0].nurl = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid ad markup', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].adm = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an ad markup without auction price macro', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].adm = 'creative_data'; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid ad serving URL', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].nurl = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an ad serving URL without auction price macro', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].nurl = 'win_notice_url'; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid without bid price', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].price = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid bid price', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].price = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid without extension', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].ext = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid extension', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].ext = 'bad_ext'; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid without adot extension', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].ext.adot = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid adot extension', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].ext.adot = 'bad_adot_ext'; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid without media type', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].ext.adot.media_type = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid media type', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].ext.adot.media_type = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an unknown media type', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].ext.adot.media_type = 'unknown_media_type'; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and no server request', function () { + const serverRequest = undefined; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and an invalid server request', function () { + const serverRequest = 'bad_server_request'; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request without bid request', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest.data = undefined; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request with an invalid bid request', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest.data = 'bad_bid_request'; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request without impression', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest.data.imp = undefined; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request with an invalid impression field', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest.data.imp = 'invalid_impressions'; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request without matching impression', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest.data.imp[0].id = 'unknown_imp_id'; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request without internal data', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest._adot_internal = undefined; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request with invalid internal data', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest._adot_internal = 'bad_internal_data'; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request without internal impression data', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest._adot_internal.impressions = undefined; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request with invalid internal impression data', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest._adot_internal.impressions = 'bad_internal_impression_data'; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request without matching internal impression', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest._adot_internal.impressions[0].impressionId = 'unknown_imp_id'; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request without internal impression ad unit code', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest._adot_internal.impressions[0].adUnitCode = undefined; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request with an invalid internal impression ad unit code', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest._adot_internal.impressions[0].adUnitCode = {}; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + }); + + describe('Banner', function () { + it('should return an ad when given a valid server response with one bid', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = examples.serverResponse_banner; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(null); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].h); + expect(ads[0].width).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('banner'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return an ad when given a valid server response with one bid without a win notice URL', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].nurl = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.equal(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(null); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].h); + expect(ads[0].width).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('banner'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return an ad when given a valid server response with one bid using an ad serving URL', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].adm = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const nurlWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].nurl, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.equal(null); + expect(ads[0].adUrl).to.exist.and.to.be.a('string').and.to.equal(nurlWithAuctionPriceReplaced); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].h); + expect(ads[0].width).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('banner'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return no ad when given a server response with a bid without height', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].h = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid height', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].h = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid without width', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].w = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid width', function () { + const serverRequest = examples.serverRequest_banner; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + serverResponse.body.seatbid[0].bid[0].w = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request without banner impression', function () { + const serverRequest = utils.deepClone(examples.serverRequest_banner); + serverRequest.data.imp[0].banner = undefined; + + const serverResponse = utils.deepClone(examples.serverResponse_banner); + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + }); + + describe('Video', function () { + it('should return an ad when given a valid server response with one bid on an instream impression', function () { + const serverRequest = examples.serverRequest_video_instream; + + const serverResponse = examples.serverResponse_video_instream; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(admWithAuctionPriceReplaced); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(serverRequest.data.imp[0].video.h); + expect(ads[0].width).to.equal(serverRequest.data.imp[0].video.w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return an ad when given a valid server response with one bid on an outstream impression', function () { + const serverRequest = examples.serverRequest_video_outstream; + + const serverResponse = examples.serverResponse_video_outstream; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(admWithAuctionPriceReplaced); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(serverRequest.data.imp[0].video.h); + expect(ads[0].width).to.equal(serverRequest.data.imp[0].video.w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[0].renderer).to.be.an('object'); + }); + + it('should return two ads when given a valid server response with two bids on both instream and outstream impressions', function () { + const serverRequest = examples.serverRequest_video_instream_outstream; + + const serverResponse = examples.serverResponse_video_instream_outstream; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + const adm2WithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[1].adm, serverResponse.body.seatbid[0].bid[1].price); + + expect(ads).to.be.an('array').and.to.have.length(2); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(admWithAuctionPriceReplaced); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(serverRequest.data.imp[0].video.h); + expect(ads[0].width).to.equal(serverRequest.data.imp[0].video.w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[0].renderer).to.equal(null); + expect(ads[1].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[1].bidId); + expect(ads[1].ad).to.exist.and.to.be.a('string').and.to.have.string(adm2WithAuctionPriceReplaced); + expect(ads[1].adUrl).to.equal(null); + expect(ads[1].vastXml).to.equal(adm2WithAuctionPriceReplaced); + expect(ads[1].vastUrl).to.equal(null); + expect(ads[1].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[1].crid); + expect(ads[1].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[1].price); + expect(ads[1].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[1].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[1].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(serverRequest.data.imp[1].video.h); + expect(ads[0].width).to.equal(serverRequest.data.imp[1].video.w); + expect(ads[1].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[1].renderer).to.be.an('object'); + }); + + it('should return an ad when given a valid server response with one bid without a win notice URL', function () { + const serverRequest = examples.serverRequest_video_instream; + + const serverResponse = utils.deepClone(examples.serverResponse_video_instream); + serverResponse.body.seatbid[0].bid[0].nurl = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(admWithAuctionPriceReplaced); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(serverRequest.data.imp[0].video.h); + expect(ads[0].width).to.equal(serverRequest.data.imp[0].video.w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return an ad when given a valid server response with one bid using an ad serving URL', function () { + const serverRequest = examples.serverRequest_video_instream; + + const serverResponse = utils.deepClone(examples.serverResponse_video_instream); + serverResponse.body.seatbid[0].bid[0].adm = undefined; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const nurlWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].nurl, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.equal(null); + expect(ads[0].adUrl).to.exist.and.to.be.a('string').and.to.have.string(nurlWithAuctionPriceReplaced); + expect(ads[0].vastXml).to.equal(null); + expect(ads[0].vastUrl).to.equal(nurlWithAuctionPriceReplaced); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(serverRequest.data.imp[0].video.h); + expect(ads[0].width).to.equal(serverRequest.data.imp[0].video.w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return an ad when given a valid server response with a bid with a video height', function () { + const serverRequest = examples.serverRequest_video_instream; + + const serverResponse = utils.deepClone(examples.serverResponse_video_instream); + serverResponse.body.seatbid[0].bid[0].h = 500; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(admWithAuctionPriceReplaced); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(serverRequest.data.imp[0].video.h); + expect(ads[0].width).to.equal(serverRequest.data.imp[0].video.w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return an ad when given a valid server response with a bid with a video width', function () { + const serverRequest = examples.serverRequest_video_instream; + + const serverResponse = utils.deepClone(examples.serverResponse_video_instream); + serverResponse.body.seatbid[0].bid[0].w = 500; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(admWithAuctionPriceReplaced); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(serverRequest.data.imp[0].video.h); + expect(ads[0].width).to.equal(serverRequest.data.imp[0].video.w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return an ad when given a valid server response with a bid with a video width and height', function () { + const serverRequest = examples.serverRequest_video_instream; + + const serverResponse = utils.deepClone(examples.serverResponse_video_instream); + serverResponse.body.seatbid[0].bid[0].w = 500; + serverResponse.body.seatbid[0].bid[0].h = 400; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(admWithAuctionPriceReplaced); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(serverResponse.body.seatbid[0].bid[0].h); + expect(ads[0].width).to.equal(serverResponse.body.seatbid[0].bid[0].w); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return an ad when given a valid server response and server request with a video impression without width', function () { + const serverRequest = utils.deepClone(examples.serverRequest_video_instream); + serverRequest.data.imp[0].video.w = null; + + const serverResponse = utils.deepClone(examples.serverResponse_video_instream); + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(admWithAuctionPriceReplaced); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(null); + expect(ads[0].width).to.equal(null); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return an ad when given a valid server response and server request with a video impression without height', function () { + const serverRequest = utils.deepClone(examples.serverRequest_video_instream); + serverRequest.data.imp[0].video.h = null; + + const serverResponse = utils.deepClone(examples.serverResponse_video_instream); + + const ads = spec.interpretResponse(serverResponse, serverRequest); + const admWithAuctionPriceReplaced = utils.replaceAuctionPrice(serverResponse.body.seatbid[0].bid[0].adm, serverResponse.body.seatbid[0].bid[0].price); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].ad).to.exist.and.to.be.a('string').and.to.have.string(admWithAuctionPriceReplaced); + expect(ads[0].adUrl).to.equal(null); + expect(ads[0].vastXml).to.equal(admWithAuctionPriceReplaced); + expect(ads[0].vastUrl).to.equal(null); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].height).to.equal(null); + expect(ads[0].width).to.equal(null); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('video'); + expect(ads[0].renderer).to.equal(null); + }); + + it('should return no ad when given a server response with a bid with an invalid height', function () { + const serverRequest = examples.serverRequest_video_instream; + + const serverResponse = utils.deepClone(examples.serverResponse_video_instream); + serverResponse.body.seatbid[0].bid[0].h = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a server response with a bid with an invalid width', function () { + const serverRequest = examples.serverRequest_video_instream; + + const serverResponse = utils.deepClone(examples.serverResponse_video_instream); + serverResponse.body.seatbid[0].bid[0].w = {}; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + it('should return no ad when given a valid server response and a server request without video impression', function () { + const serverRequest = utils.deepClone(examples.serverRequest_video_instream); + serverRequest.data.imp[0].video = undefined; + + const serverResponse = utils.deepClone(examples.serverResponse_video_instream); + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(0); + }); + + describe('Outstream renderer', function () { + function spyAdRenderingQueue(ad) { + const spy = sinon.spy(ad.renderer, 'push'); + + this.sinonSpies.push(spy); + } + + function executeAdRenderer(ad, onRendererExecution, done) { + executeRenderer(ad.renderer, ad); + + setTimeout(() => { + try { + onRendererExecution(); + } catch (err) { + done(err); + } + + done() + }, 100); + } + + before('Bind helper functions to the Mocha context', function () { + this.spyAdRenderingQueue = spyAdRenderingQueue.bind(this); + + window.VASTPlayer = function VASTPlayer() {}; + window.VASTPlayer.prototype.loadXml = function loadXml() { + return new Promise((resolve, reject) => resolve()) + }; + window.VASTPlayer.prototype.load = function load() { + return new Promise((resolve, reject) => resolve()) + }; + window.VASTPlayer.prototype.on = function on(event, callback) {}; + window.VASTPlayer.prototype.startAd = function startAd() {}; + }); + + beforeEach('Initialize the Sinon spies list', function () { + this.sinonSpies = []; + }); + + afterEach('Clear the registered Sinon spies', function () { + this.sinonSpies.forEach(spy => spy.restore()); + }); + + after('clear data', () => { + window.VASTPlayer = null; + }); + + it('should return an ad with valid renderer', function () { + const serverRequest = examples.serverRequest_video_outstream; + const serverResponse = examples.serverResponse_video_outstream; + + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].renderer).to.be.an('object'); + }); + }); + }); + + describe('Native', function () { + it('should return an ad when given a valid server response with one bid', function () { + const serverRequest = examples.serverRequest_native; + const serverResponse = examples.serverResponse_native; + const native = JSON.parse(serverResponse.body.seatbid[0].bid[0].adm).native; + const {link, assets} = native; + const ads = spec.interpretResponse(serverResponse, serverRequest); + + expect(ads).to.be.an('array').and.to.have.length(1); + expect(ads[0].requestId).to.exist.and.to.be.a('string').and.to.equal(serverRequest._adot_internal.impressions[0].bidId); + expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); + expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); + expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); + expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); + expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); + expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('native'); + expect(ads[0].native).to.exist.and.to.be.an('object'); + expect(Object.keys(ads[0].native)).to.have.length(10); + expect(ads[0].native.title).to.equal(assets[0].title.text); + expect(ads[0].native.icon.url).to.equal(assets[1].img.url); + expect(ads[0].native.icon.width).to.equal(assets[1].img.w); + expect(ads[0].native.icon.height).to.equal(assets[1].img.h); + expect(ads[0].native.image.url).to.equal(assets[2].img.url); + expect(ads[0].native.image.width).to.equal(assets[2].img.w); + expect(ads[0].native.image.height).to.equal(assets[2].img.h); + expect(ads[0].native.sponsoredBy).to.equal(assets[3].data.value); + expect(ads[0].native.body).to.equal(assets[4].data.value); + expect(ads[0].native.cta).to.equal(assets[5].data.value); + expect(ads[0].native.clickUrl).to.equal(link.url); + }); + }); }); }); diff --git a/test/spec/modules/adpartnerBidAdapter_spec.js b/test/spec/modules/adpartnerBidAdapter_spec.js deleted file mode 100644 index 94b56f7735b..00000000000 --- a/test/spec/modules/adpartnerBidAdapter_spec.js +++ /dev/null @@ -1,336 +0,0 @@ -import {expect} from 'chai'; -import {spec, ENDPOINT_PROTOCOL, ENDPOINT_DOMAIN, ENDPOINT_PATH} from 'modules/adpartnerBidAdapter.js'; -import {newBidder} from 'src/adapters/bidderFactory.js'; - -const BIDDER_CODE = 'adpartner'; - -describe('AdpartnerAdapter', function () { - const adapter = newBidder(spec); - - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(adapter.callBids).to.be.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', function () { - it('should return true when required params found', function () { - let validRequest = { - 'params': { - 'unitId': 123 - } - }; - expect(spec.isBidRequestValid(validRequest)).to.equal(true); - }); - - it('should return true when required params is srting', function () { - let validRequest = { - 'params': { - 'unitId': '456' - } - }; - expect(spec.isBidRequestValid(validRequest)).to.equal(true); - }); - - it('should return false when required params are not passed', function () { - let validRequest = { - 'params': { - 'unknownId': 123 - } - }; - expect(spec.isBidRequestValid(validRequest)).to.equal(false); - }); - - it('should return false when required params is 0', function () { - let validRequest = { - 'params': { - 'unitId': 0 - } - }; - expect(spec.isBidRequestValid(validRequest)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - let validEndpoint = ENDPOINT_PROTOCOL + '://' + ENDPOINT_DOMAIN + ENDPOINT_PATH + '?tag=123,456&partner=777&sizes=300x250|300x600,728x90,300x250&referer=https%3A%2F%2Ftest.domain'; - - let validRequest = [ - { - 'bidder': BIDDER_CODE, - 'params': { - 'unitId': 123 - }, - 'adUnitCode': 'adunit-code-1', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e' - }, - { - 'bidder': BIDDER_CODE, - 'params': { - 'unitId': '456' - }, - 'adUnitCode': 'adunit-code-2', - 'sizes': [[728, 90]], - 'bidId': '22aidtbx5eabd9' - }, - { - 'bidder': BIDDER_CODE, - 'params': { - 'partnerId': 777 - }, - 'adUnitCode': 'partner-code-3', - 'sizes': [[300, 250]], - 'bidId': '5d4531d5a6c013' - } - ]; - - let bidderRequest = { - refererInfo: { - referer: 'https://test.domain' - } - }; - - it('bidRequest HTTP method', function () { - const request = spec.buildRequests(validRequest, bidderRequest); - expect(request.method).to.equal('POST'); - }); - - it('bidRequest url', function () { - const request = spec.buildRequests(validRequest, bidderRequest); - expect(request.url).to.equal(validEndpoint); - }); - - it('bidRequest data', function () { - const request = spec.buildRequests(validRequest, bidderRequest); - const payload = JSON.parse(request.data); - expect(payload[0].unitId).to.equal(123); - expect(payload[0].sizes).to.deep.equal([[300, 250], [300, 600]]); - expect(payload[0].bidId).to.equal('30b31c1838de1e'); - expect(payload[1].unitId).to.equal(456); - expect(payload[1].sizes).to.deep.equal([[728, 90]]); - expect(payload[1].bidId).to.equal('22aidtbx5eabd9'); - expect(payload[2].partnerId).to.equal(777); - expect(payload[2].sizes).to.deep.equal([[300, 250]]); - expect(payload[2].bidId).to.equal('5d4531d5a6c013'); - }); - }); - - describe('joinSizesToString', function () { - it('success convert sizes list to string', function () { - const sizesStr = spec.joinSizesToString([[300, 250], [300, 600]]); - expect(sizesStr).to.equal('300x250|300x600'); - }); - }); - - describe('interpretResponse', function () { - const bidRequest = { - 'method': 'POST', - 'url': ENDPOINT_PROTOCOL + '://' + ENDPOINT_DOMAIN + ENDPOINT_PATH + '?tag=123,456&partner=777code=adunit-code-1,adunit-code-2,partner-code-3&bid=30b31c1838de1e,22aidtbx5eabd9,5d4531d5a6c013&sizes=300x250|300x600,728x90,300x250&referer=https%3A%2F%2Ftest.domain', - 'data': '[{"unitId": 13144370,"adUnitCode": "div-gpt-ad-1460505748561-0","sizes": [[300, 250], [300, 600]],"bidId": "2bdcb0b203c17d","referer": "https://test.domain/index.html"},' + - '{"unitId": 13144370,"adUnitCode":"div-gpt-ad-1460505748561-1","sizes": [[768, 90]],"bidId": "3dc6b8084f91a8","referer": "https://test.domain/index.html"},' + - '{"unitId": 0,"partnerId": 777,"adUnitCode":"div-gpt-ad-1460505748561-2","sizes": [[300, 250]],"bidId": "5d4531d5a6c013","referer": "https://test.domain/index.html"}]' - }; - - const bidResponse = { - body: { - 'div-gpt-ad-1460505748561-0': - { - 'ad': '
ad
', - 'width': 300, - 'height': 250, - 'creativeId': '8:123456', - 'adomain': [ - 'test.domain' - ], - 'syncs': [ - {'type': 'image', 'url': 'https://test.domain/tracker_1.gif'}, - {'type': 'image', 'url': 'https://test.domain/tracker_2.gif'}, - {'type': 'image', 'url': 'https://test.domain/tracker_3.gif'} - ], - 'winNotification': [ - { - 'method': 'POST', - 'path': '/hb/bid_won?test=1', - 'data': { - 'ad': [ - {'dsp': 8, 'id': 800008, 'cost': 1.0e-5, 'nurl': 'https://test.domain/'} - ], - 'unit_id': 1234, - 'site_id': 123 - } - } - ], - 'cpm': 0.01, - 'currency': 'USD', - 'netRevenue': true - } - }, - headers: {} - }; - - it('result is correct', function () { - const result = spec.interpretResponse(bidResponse, bidRequest); - expect(result[0].requestId).to.equal('2bdcb0b203c17d'); - expect(result[0].cpm).to.equal(0.01); - expect(result[0].width).to.equal(300); - expect(result[0].height).to.equal(250); - expect(result[0].creativeId).to.equal('8:123456'); - expect(result[0].currency).to.equal('USD'); - expect(result[0].ttl).to.equal(60); - expect(result[0].meta.advertiserDomains).to.deep.equal(['test.domain']); - expect(result[0].winNotification[0]).to.deep.equal({'method': 'POST', 'path': '/hb/bid_won?test=1', 'data': {'ad': [{'dsp': 8, 'id': 800008, 'cost': 1.0e-5, 'nurl': 'https://test.domain/'}], 'unit_id': 1234, 'site_id': 123}}); - }); - }); - - describe('adResponse', function () { - const bid = { - 'unitId': 13144370, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '2bdcb0b203c17d', - 'referer': 'https://test.domain/index.html' - }; - const ad = { - 'ad': '
ad
', - 'width': 300, - 'height': 250, - 'creativeId': '8:123456', - 'syncs': [], - 'winNotification': [], - 'cpm': 0.01, - 'currency': 'USD', - 'netRevenue': true, - 'adomain': [ - 'test.domain' - ], - }; - - it('fill ad for response', function () { - const result = spec.adResponse(bid, ad); - expect(result.requestId).to.equal('2bdcb0b203c17d'); - expect(result.cpm).to.equal(0.01); - expect(result.width).to.equal(300); - expect(result.height).to.equal(250); - expect(result.creativeId).to.equal('8:123456'); - expect(result.currency).to.equal('USD'); - expect(result.ttl).to.equal(60); - expect(result.meta.advertiserDomains).to.deep.equal(['test.domain']); - }); - }); - - describe('onBidWon', function () { - const bid = { - winNotification: [ - { - 'method': 'POST', - 'path': '/hb/bid_won?test=1', - 'data': { - 'ad': [ - {'dsp': 8, 'id': 800008, 'cost': 0.01, 'nurl': 'http://test.domain/'} - ], - 'unit_id': 1234, - 'site_id': 123 - } - } - ] - }; - - let ajaxStub; - - beforeEach(() => { - ajaxStub = sinon.stub(spec, 'postRequest') - }) - - afterEach(() => { - ajaxStub.restore() - }) - - it('calls adpartner\'s callback endpoint', () => { - const result = spec.onBidWon(bid); - expect(result).to.equal(true); - expect(ajaxStub.calledOnce).to.equal(true); - expect(ajaxStub.firstCall.args[0]).to.equal(ENDPOINT_PROTOCOL + '://' + ENDPOINT_DOMAIN + '/hb/bid_won?test=1'); - expect(ajaxStub.firstCall.args[1]).to.deep.equal(JSON.stringify(bid.winNotification[0].data)); - }); - }); - - describe('getUserSyncs', function () { - const bidResponse = [{ - body: { - 'div-gpt-ad-1460505748561-0': - { - 'ad': '
ad
', - 'width': 300, - 'height': 250, - 'creativeId': '8:123456', - 'adomain': [ - 'test.domain' - ], - 'syncs': [ - {'type': 'image', 'link': 'https://test.domain/tracker_1.gif'}, - {'type': 'image', 'link': 'https://test.domain/tracker_2.gif'}, - {'type': 'image', 'link': 'https://test.domain/tracker_3.gif'} - ], - 'winNotification': [ - { - 'method': 'POST', - 'path': '/hb/bid_won?test=1', - 'data': { - 'ad': [ - {'dsp': 8, 'id': 800008, 'cost': 1.0e-5, 'nurl': 'https://test.domain/'} - ], - 'unit_id': 1234, - 'site_id': 123 - } - } - ], - 'cpm': 0.01, - 'currency': 'USD', - 'netRevenue': true - } - }, - headers: {} - }]; - - it('should return nothing when sync is disabled', function () { - const syncOptions = { - 'iframeEnabled': false, - 'pixelEnabled': false - }; - - let syncs = spec.getUserSyncs(syncOptions); - expect(syncs).to.deep.equal([]); - }); - - it('should register image sync when only image is enabled where gdprConsent is undefined', function () { - const syncOptions = { - 'iframeEnabled': false, - 'pixelEnabled': true - }; - - const gdprConsent = undefined; - let syncs = spec.getUserSyncs(syncOptions, bidResponse, gdprConsent); - expect(syncs.length).to.equal(3); - expect(syncs[0].type).to.equal('image'); - expect(syncs[0].url).to.equal('https://test.domain/tracker_1.gif'); - }); - - it('should register image sync when only image is enabled where gdprConsent is defined', function () { - const syncOptions = { - 'iframeEnabled': false, - 'pixelEnabled': true - }; - const gdprConsent = { - consentString: 'someString', - vendorData: {}, - gdprApplies: true, - apiVersion: 2 - }; - - let syncs = spec.getUserSyncs(syncOptions, bidResponse, gdprConsent); - expect(syncs.length).to.equal(3); - expect(syncs[0].type).to.equal('image'); - expect(syncs[0].url).to.equal('https://test.domain/tracker_1.gif?gdpr=1&gdpr_consent=someString'); - }); - }); -}); diff --git a/test/spec/modules/adplusBidAdapter_spec.js b/test/spec/modules/adplusBidAdapter_spec.js deleted file mode 100644 index 840d86c80f1..00000000000 --- a/test/spec/modules/adplusBidAdapter_spec.js +++ /dev/null @@ -1,213 +0,0 @@ -import {expect} from 'chai'; -import {spec, BIDDER_CODE, ADPLUS_ENDPOINT, } from 'modules/adplusBidAdapter.js'; -import {newBidder} from 'src/adapters/bidderFactory.js'; - -describe('AplusBidAdapter', function () { - const adapter = newBidder(spec); - - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(adapter.callBids).to.be.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', function () { - it('should return true when required params found', function () { - let validRequest = { - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - params: { - inventoryId: '30', - adUnitId: '1', - } - }; - expect(spec.isBidRequestValid(validRequest)).to.equal(true); - }); - - it('should return false when required params are not passed', function () { - let validRequest = { - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - params: { - inventoryId: '30', - } - }; - expect(spec.isBidRequestValid(validRequest)).to.equal(false); - }); - - it('should return false when required param types are wrong', function () { - let validRequest = { - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - params: { - inventoryId: 30, - adUnitId: '1', - } - }; - expect(spec.isBidRequestValid(validRequest)).to.equal(false); - }); - - it('should return false when size is not exists', function () { - let validRequest = { - params: { - inventoryId: 30, - adUnitId: '1', - } - }; - expect(spec.isBidRequestValid(validRequest)).to.equal(false); - }); - - it('should return false when size is wrong', function () { - let validRequest = { - mediaTypes: { - banner: { - sizes: [[300]] - } - }, - params: { - inventoryId: 30, - adUnitId: '1', - } - }; - expect(spec.isBidRequestValid(validRequest)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - let validRequest = [ - { - bidder: BIDDER_CODE, - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - params: { - inventoryId: '-1', - adUnitId: '-3', - }, - bidId: '2bdcb0b203c17d' - }, - ]; - - let bidderRequest = { - refererInfo: { - referer: 'https://test.domain' - } - }; - - it('bidRequest HTTP method', function () { - const request = spec.buildRequests(validRequest, bidderRequest); - expect(request[0].method).to.equal('GET'); - }); - - it('bidRequest url', function () { - const request = spec.buildRequests(validRequest, bidderRequest); - expect(request[0].url).to.equal(ADPLUS_ENDPOINT); - }); - - it('tests bidRequest data is clean and has the right values', function () { - const request = spec.buildRequests(validRequest, bidderRequest); - - expect(request[0].data.bidId).to.equal('2bdcb0b203c17d'); - expect(request[0].data.inventoryId).to.equal('-1'); - expect(request[0].data.adUnitId).to.equal('-3'); - expect(request[0].data.adUnitWidth).to.equal(300); - expect(request[0].data.adUnitHeight).to.equal(250); - expect(request[0].data.sdkVersion).to.equal('1'); - expect(typeof request[0].data.session).to.equal('string'); - expect(request[0].data.session).length(36); - expect(request[0].data.interstitial).to.equal(0); - expect(request[0].data).to.not.have.deep.property('extraData'); - expect(request[0].data).to.not.have.deep.property('yearOfBirth'); - expect(request[0].data).to.not.have.deep.property('gender'); - expect(request[0].data).to.not.have.deep.property('categories'); - expect(request[0].data).to.not.have.deep.property('latitude'); - expect(request[0].data).to.not.have.deep.property('longitude'); - }); - }); - - describe('interpretResponse', function () { - const requestData = { - language: window.navigator.language, - screenWidth: 1440, - screenHeight: 900, - sdkVersion: '1', - inventoryId: '-1', - adUnitId: '-3', - adUnitWidth: 300, - adUnitHeight: 250, - domain: 'tassandigi.com', - pageUrl: 'https%3A%2F%2Ftassandigi.com%2Fserafettin%2Fads.html', - interstitial: 0, - session: '1c02db03-5289-932a-93af-7b4022611fec', - token: '1c02db03-5289-937a-93df-7b4022611fec', - secure: 1, - bidId: '2bdcb0b203c17d', - }; - const bidRequest = { - 'method': 'GET', - 'url': ADPLUS_ENDPOINT, - 'data': requestData, - }; - - const bidResponse = { - body: [ - { - 'ad': '
ad
', - 'advertiserDomains': [ - 'advertiser.com' - ], - 'categoryIDs': [ - 'IAB-111' - ], - 'cpm': 3.57, - 'creativeID': '1', - 'currency': 'TRY', - 'dealID': '1', - 'height': 300, - 'mediaType': 'banner', - 'netRevenue': true, - 'requestID': '2bdcb0b203c17d', - 'ttl': 300, - 'width': 250 - } - ], - headers: {} - }; - - const emptyBidResponse = { - body: null, - }; - - it('returns an empty array when the result body is not valid', function () { - const result = spec.interpretResponse(emptyBidResponse, bidRequest); - expect(result).to.deep.equal([]); - }); - - it('result is correct', function () { - const result = spec.interpretResponse(bidResponse, bidRequest); - expect(result[0].requestId).to.equal('2bdcb0b203c17d'); - expect(result[0].cpm).to.equal(3.57); - expect(result[0].width).to.equal(250); - expect(result[0].height).to.equal(300); - expect(result[0].creativeId).to.equal('1'); - expect(result[0].currency).to.equal('TRY'); - expect(result[0].dealId).to.equal('1'); - expect(result[0].mediaType).to.equal('banner'); - expect(result[0].netRevenue).to.equal(true); - expect(result[0].ttl).to.equal(300); - expect(result[0].meta.advertiserDomains).to.deep.equal(['advertiser.com']); - expect(result[0].meta.secondaryCatIds).to.deep.equal(['IAB-111']); - }); - }); -}); diff --git a/test/spec/modules/adpod_spec.js b/test/spec/modules/adpod_spec.js index a6164f919ef..5e4bcce1fe6 100644 --- a/test/spec/modules/adpod_spec.js +++ b/test/spec/modules/adpod_spec.js @@ -73,11 +73,16 @@ describe('adpod.js', function () { mediaType: 'video' }; - let videoMT = { - context: 'outstream' - }; + let bidderRequest = { + adUnitCode: 'adUnit_123', + mediaTypes: { + video: { + context: 'outstream' + } + } + } - callPrebidCacheHook(callbackFn, auctionInstance, bid, function () {}, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bid, function () {}, bidderRequest); expect(callbackResult).to.equal(true); }); @@ -127,16 +132,22 @@ describe('adpod.js', function () { } }; - let videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 300, - durationRangeSec: [15, 30, 45], - requireExactDuration: false + let bidderRequest = { + adUnitCode: 'adpod_1', + auctionId: 'no_defer_123', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [[300, 300]], + adPodDurationSec: 300, + durationRangeSec: [15, 30, 45], + requireExactDuration: false + } + }, }; - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); // check if bid adsereverTargeting is setup expect(callbackResult).to.be.null; @@ -203,16 +214,22 @@ describe('adpod.js', function () { durationBucket: 30 } }; - let videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 120, - durationRangeSec: [15, 30], - requireExactDuration: false + let bidderRequest = { + adUnitCode: 'adpod_1', + auctionId: 'full_abc123', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [[300, 300]], + adPodDurationSec: 120, + durationRangeSec: [15, 30], + requireExactDuration: false + } + } }; - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); expect(callbackResult).to.be.null; expect(afterBidAddedSpy.calledTwice).to.equal(true); @@ -259,15 +276,21 @@ describe('adpod.js', function () { durationBucket: 30 } }; - let videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 120, - durationRangeSec: [15, 30], - requireExactDuration: true + let bidderRequest = { + adUnitCode: 'adpod_2', + auctionId: 'timer_abc234', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [[300, 300]], + adPodDurationSec: 120, + durationRangeSec: [15, 30], + requireExactDuration: true + } + } }; - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse, afterBidAddedSpy, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse, afterBidAddedSpy, bidderRequest); clock.tick(31); expect(callbackResult).to.be.null; @@ -347,17 +370,23 @@ describe('adpod.js', function () { } }; - let videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 45, - durationRangeSec: [15, 30], - requireExactDuration: false + let bidderRequest = { + adUnitCode: 'adpod_3', + auctionId: 'multi_call_abc345', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [[300, 300]], + adPodDurationSec: 45, + durationRangeSec: [15, 30], + requireExactDuration: false + } + } }; - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse3, afterBidAddedSpy, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse3, afterBidAddedSpy, bidderRequest); clock.next(); expect(callbackResult).to.be.null; @@ -430,16 +459,22 @@ describe('adpod.js', function () { } }; - let videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 45, - durationRangeSec: [15, 30], - requireExactDuration: false + let bidderRequest = { + adUnitCode: 'adpod_4', + auctionId: 'no_category_abc345', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [[300, 300]], + adPodDurationSec: 45, + durationRangeSec: [15, 30], + requireExactDuration: false + } + } }; - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); expect(callbackResult).to.be.null; expect(afterBidAddedSpy.calledTwice).to.equal(true); @@ -484,15 +519,21 @@ describe('adpod.js', function () { } }; - let videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 45, - durationRangeSec: [15, 30], - requireExactDuration: false + let bidderRequest = { + adUnitCode: 'adpod_5', + auctionId: 'missing_category_abc345', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [[300, 300]], + adPodDurationSec: 45, + durationRangeSec: [15, 30], + requireExactDuration: false + } + } }; - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); expect(callbackResult).to.be.null; expect(afterBidAddedSpy.calledOnce).to.equal(true); @@ -555,16 +596,22 @@ describe('adpod.js', function () { durationBucket: 45 } }; - let videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 120, - durationRangeSec: [15, 30, 45], - requireExactDuration: false + let bidderRequest = { + adUnitCode: 'adpod_4', + auctionId: 'duplicate_def123', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [[300, 300]], + adPodDurationSec: 120, + durationRangeSec: [15, 30, 45], + requireExactDuration: false + } + } }; - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); expect(callbackResult).to.be.null; expect(afterBidAddedSpy.calledTwice).to.equal(true); @@ -622,16 +669,22 @@ describe('adpod.js', function () { durationBucket: 30 } }; - let videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 120, - durationRangeSec: [15, 30, 45], - requireExactDuration: false + let bidderRequest = { + adUnitCode: 'adpod_5', + auctionId: 'error_xyz123', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [[300, 300]], + adPodDurationSec: 120, + durationRangeSec: [15, 30, 45], + requireExactDuration: false + } + } }; - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); expect(doCallbacksIfTimedoutStub.calledTwice).to.equal(true); expect(logWarnStub.calledOnce).to.equal(true); @@ -689,15 +742,21 @@ describe('adpod.js', function () { } }; - let videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 45, - durationRangeSec: [15, 30], - requireExactDuration: false + let bidderRequest = { + adUnitCode: 'adpod_5', + auctionId: 'test_category_abc345', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [[300, 300]], + adPodDurationSec: 45, + durationRangeSec: [15, 30], + requireExactDuration: false + } + } }; - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); expect(callbackResult).to.be.null; expect(afterBidAddedSpy.calledOnce).to.equal(true); @@ -761,16 +820,22 @@ describe('adpod.js', function () { } }; - let videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 300, - durationRangeSec: [15, 30, 45], - requireExactDuration: false + let bidderRequest = { + adUnitCode: 'adpod_1', + auctionId: 'no_defer_123', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [[300, 300]], + adPodDurationSec: 300, + durationRangeSec: [15, 30, 45], + requireExactDuration: false + } + }, }; - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('tier7_test_15s'); expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('12.00_value_15s'); @@ -920,7 +985,7 @@ describe('adpod.js', function () { }, vastXml: 'test XML here' }; - const adUnitNoExact = { + const bidderRequestNoExact = { mediaTypes: { video: { context: ADPOD, @@ -931,7 +996,7 @@ describe('adpod.js', function () { } } }; - const adUnitWithExact = { + const bidderRequestWithExact = { mediaTypes: { video: { context: ADPOD, @@ -986,7 +1051,7 @@ describe('adpod.js', function () { let goodBid = utils.deepClone(adpodTestBid); goodBid.meta.primaryCatId = undefined; - checkVideoBidSetupHook(callbackFn, goodBid, adUnitNoExact, adUnitNoExact.mediaTypes.video, ADPOD); + checkVideoBidSetupHook(callbackFn, goodBid, bidderRequestNoExact, {}, ADPOD); expect(callbackResult).to.be.null; expect(bailResult).to.equal(true); expect(logErrorStub.called).to.equal(false); @@ -994,7 +1059,7 @@ describe('adpod.js', function () { it('returns true when adpod bid is missing iab category while brandCategoryExclusion in config is false', function() { let goodBid = utils.deepClone(adpodTestBid); - checkVideoBidSetupHook(callbackFn, goodBid, adUnitNoExact, adUnitNoExact.mediaTypes.video, ADPOD); + checkVideoBidSetupHook(callbackFn, goodBid, bidderRequestNoExact, {}, ADPOD); expect(callbackResult).to.be.null; expect(bailResult).to.equal(true); expect(logErrorStub.called).to.equal(false); @@ -1002,7 +1067,7 @@ describe('adpod.js', function () { it('returns false when a required property from an adpod bid is missing', function() { function testInvalidAdpodBid(badTestBid, shouldErrorBeLogged) { - checkVideoBidSetupHook(callbackFn, badTestBid, adUnitNoExact, adUnitNoExact.mediaTypes.video, ADPOD); + checkVideoBidSetupHook(callbackFn, badTestBid, bidderRequestNoExact, {}, ADPOD); expect(callbackResult).to.be.null; expect(bailResult).to.equal(false); expect(logErrorStub.called).to.equal(shouldErrorBeLogged); @@ -1043,7 +1108,7 @@ describe('adpod.js', function () { it('when requireExactDuration is true', function() { let goodBid = utils.deepClone(basicBid); - checkVideoBidSetupHook(callbackFn, goodBid, adUnitWithExact, adUnitWithExact.mediaTypes.video, ADPOD); + checkVideoBidSetupHook(callbackFn, goodBid, bidderRequestWithExact, {}, ADPOD); expect(callbackResult).to.be.null; expect(goodBid.video.durationBucket).to.equal(30); @@ -1052,7 +1117,7 @@ describe('adpod.js', function () { let badBid = utils.deepClone(basicBid); badBid.video.durationSeconds = 14; - checkVideoBidSetupHook(callbackFn, badBid, adUnitWithExact, adUnitWithExact.mediaTypes.video, ADPOD); + checkVideoBidSetupHook(callbackFn, badBid, bidderRequestWithExact, {}, ADPOD); expect(callbackResult).to.be.null; expect(badBid.video.durationBucket).to.be.undefined; @@ -1062,7 +1127,7 @@ describe('adpod.js', function () { it('when requireExactDuration is false and bids are bucketed properly', function() { function testRoundingForGoodBId(bid, bucketValue) { - checkVideoBidSetupHook(callbackFn, bid, adUnitNoExact, adUnitNoExact.mediaTypes.video, ADPOD); + checkVideoBidSetupHook(callbackFn, bid, bidderRequestNoExact, {}, ADPOD); expect(callbackResult).to.be.null; expect(bid.video.durationBucket).to.equal(bucketValue); expect(bailResult).to.equal(true); @@ -1092,7 +1157,7 @@ describe('adpod.js', function () { it('when requireExactDuration is false and bid duration exceeds listed buckets', function() { function testRoundingForBadBid(bid) { - checkVideoBidSetupHook(callbackFn, bid, adUnitNoExact, adUnitNoExact.mediaTypes.video, ADPOD); + checkVideoBidSetupHook(callbackFn, bid, bidderRequestNoExact, {}, ADPOD); expect(callbackResult).to.be.null; expect(bid.video.durationBucket).to.be.undefined; expect(bailResult).to.equal(false); diff --git a/test/spec/modules/adprimeBidAdapter_spec.js b/test/spec/modules/adprimeBidAdapter_spec.js index 5efed4ec5ab..53f41a6be4e 100644 --- a/test/spec/modules/adprimeBidAdapter_spec.js +++ b/test/spec/modules/adprimeBidAdapter_spec.js @@ -293,29 +293,14 @@ describe('AdprimebBidAdapter', function () { expect(serverResponses).to.be.an('array').that.is.empty; }); }); - describe('getUserSyncs', function() { - it('Should return array of objects with proper sync config , include GDPR', function() { - const syncData = spec.getUserSyncs({}, {}, { - consentString: 'ALL', - gdprApplies: true, - }, {}); - expect(syncData).to.be.an('array').which.is.not.empty; - expect(syncData[0]).to.be.an('object') - expect(syncData[0].type).to.be.a('string') - expect(syncData[0].type).to.equal('image') - expect(syncData[0].url).to.be.a('string') - expect(syncData[0].url).to.equal('https://sync.adprime.com/image?pbjs=1&gdpr=1&gdpr_consent=ALL&coppa=0') - }); - it('Should return array of objects with proper sync config , include CCPA', function() { - const syncData = spec.getUserSyncs({}, {}, {}, { - consentString: '1---' - }); - expect(syncData).to.be.an('array').which.is.not.empty; - expect(syncData[0]).to.be.an('object') - expect(syncData[0].type).to.be.a('string') - expect(syncData[0].type).to.equal('image') - expect(syncData[0].url).to.be.a('string') - expect(syncData[0].url).to.equal('https://sync.adprime.com/image?pbjs=1&ccpa_consent=1---&coppa=0') + describe('getUserSyncs', function () { + let userSync = spec.getUserSyncs(); + it('Returns valid URL and type', function () { + expect(userSync).to.be.an('array').with.lengthOf(1); + expect(userSync[0].type).to.exist; + expect(userSync[0].url).to.exist; + expect(userSync[0].type).to.be.equal('image'); + expect(userSync[0].url).to.be.equal('https://delta.adprime.com'); }); }); }); diff --git a/test/spec/modules/adqueryBidAdapter_spec.js b/test/spec/modules/adqueryBidAdapter_spec.js deleted file mode 100644 index 4285377e8a7..00000000000 --- a/test/spec/modules/adqueryBidAdapter_spec.js +++ /dev/null @@ -1,185 +0,0 @@ -import { expect } from 'chai' -import { spec } from 'modules/adqueryBidAdapter.js' -import { newBidder } from 'src/adapters/bidderFactory.js' -import * as utils from '../../../src/utils'; - -describe('adqueryBidAdapter', function () { - const adapter = newBidder(spec) - let bidRequest = { - bidder: 'adquery', - params: { - placementId: '6d93f2a0e5f0fe2cc3a6e9e3ade964b43b07f897', - type: 'banner300x250' - }, - mediaTypes: { - banner: { - sizes: [[300, 250]], - } - } - } - - let expectedResponse = { - 'body': { - 'data': - { - 'requestId': 1, - 'emission_id': 1, - 'eventTracker': 'https://example.com', - 'externalEmissionCodes': 'https://example.com', - 'impressionTracker': 'https://example.com', - 'viewabilityTracker': 'https://example.com', - 'clickTracker': 'https://example.com', - 'link': 'https://example.com', - 'logo': 'https://example.com', - 'medias': [ - { - 'src': 'banner/2021-04-09/938', - 'ext': 'zip', - 'type': 3, - } - ], - 'domain': 'https://example.com', - 'urlAdq': 'https://example.com', - 'creationId': 1, - 'currency': 'PLN', - 'adDomains': ['https://example.com'], - 'tag': ' ', - 'adqLib': 'https://example.com/js/example.js', - 'mediaType': {'width': 300, 'height': 250, 'name': 'banner', 'type': 'banner300x250'}, - 'cpm': 2.5, - 'meta': { - 'advertiserDomains': ['example.com'], - 'mediaType': 'banner', - } - } - } - } - describe('codes', function () { - it('should return a bidder code of adquery', function () { - expect(spec.code).to.equal('adquery') - }) - }) - - describe('isBidRequestValid', function () { - let inValidBid = Object.assign({}, bidRequest) - delete inValidBid.params - it('should return true if all params present', function () { - expect(spec.isBidRequestValid(bidRequest)).to.equal(true) - }) - - it('should return false if any parameter missing', function () { - expect(spec.isBidRequestValid(inValidBid)).to.be.false - }) - }) - - describe('buildRequests', function () { - let req = spec.buildRequests([ bidRequest ], { refererInfo: { } })[0] - let rdata - - it('should return request object', function () { - expect(req).to.not.be.null - }) - - it('should build request data', function () { - expect(req.data).to.not.be.null - }) - - it('should include one request', function () { - rdata = req.data; - expect(rdata.data).to.not.be.null - }) - - it('should include placementCode', function () { - expect(rdata.placementCode).not.be.null - }) - - it('should include qid', function () { - expect(rdata.qid).not.be.null - }) - - it('should include type', function () { - expect(rdata.type !== null).not.be.null - }) - - it('should include all publisher params', function () { - expect(rdata.type !== null && rdata.placementCode !== null).to.be.true - }) - - it('should include bidder', function () { - expect(rdata.bidder !== null).to.be.true - }) - }) - - describe('interpretResponse', function () { - it('should get the correct bid response', function () { - let result = spec.interpretResponse(expectedResponse) - expect(result).to.be.an('array') - }) - - it('validate response params', function() { - const newResponse = spec.interpretResponse(expectedResponse, bidRequest); - expect(newResponse[0].requestId).to.be.equal(1) - }); - it('handles empty bid response', function () { - let response = { - body: {} - }; - let result = spec.interpretResponse(response); - expect(result.length).to.equal(0); - }) - }) - - describe('getUserSyncs', function () { - it('should return iframe sync', function () { - let sync = spec.getUserSyncs() - expect(sync.length).to.equal(1) - expect(sync[0].type === 'iframe') - expect(typeof sync[0].url === 'string') - }) - - it('Should return array of objects with proper sync config , include GDPR', function() { - const syncData = spec.getUserSyncs({}, {}, { - consentString: 'ALL', - gdprApplies: true, - }, {}); - expect(syncData).to.be.an('array').which.is.not.empty; - expect(syncData[0]).to.be.an('object') - expect(syncData[0].type).to.be.a('string') - expect(syncData[0].type).to.equal('image') - }); - }) - - describe('test onBidWon function', function () { - beforeEach(function() { - sinon.stub(utils, 'triggerPixel'); - }); - afterEach(function() { - utils.triggerPixel.restore(); - }); - it('exists and is a function', () => { - expect(spec.onBidWon).to.exist.and.to.be.a('function'); - }); - it('should return nothing', function () { - var response = spec.onBidWon({}); - expect(response).to.be.an('undefined') - expect(utils.triggerPixel.called).to.equal(true); - }); - }) - - describe('onTimeout', function () { - const timeoutData = [{ - timeout: null - }]; - - it('should exists and be a function', () => { - expect(spec.onTimeout).to.exist.and.to.be.a('function'); - }); - it('should include timeoutData', function () { - expect(spec.onTimeout(timeoutData)).to.be.undefined; - }) - }); - - it(`onSetTargeting is present and type function`, function () { - expect(spec.onSetTargeting).to.exist.and.to.be.a('function') - }); -}) diff --git a/test/spec/modules/adqueryIdSystem_spec.js b/test/spec/modules/adqueryIdSystem_spec.js deleted file mode 100644 index ab98b253b33..00000000000 --- a/test/spec/modules/adqueryIdSystem_spec.js +++ /dev/null @@ -1,74 +0,0 @@ -import { adqueryIdSubmodule, storage } from 'modules/adqueryIdSystem.js'; -import { server } from 'test/mocks/xhr.js'; -import {amxIdSubmodule} from '../../../modules/amxIdSystem'; -import * as utils from '../../../src/utils'; - -const config = { - storage: { - type: 'html5', - }, -}; - -describe('AdqueryIdSystem', function () { - describe('qid submodule', () => { - it('should expose a "name" property containing qid', () => { - expect(adqueryIdSubmodule.name).to.equal('qid'); - }); - - it('should expose a "gvlid" property containing the GVL ID 902', () => { - expect(adqueryIdSubmodule.gvlid).to.equal(902); - }); - }); - - describe('getId', function() { - let getDataFromLocalStorageStub; - - beforeEach(function() { - getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); - }); - - afterEach(function () { - getDataFromLocalStorageStub.restore(); - }); - - it('gets a adqueryId', function() { - const config = { - params: {} - }; - const callbackSpy = sinon.spy(); - const callback = adqueryIdSubmodule.getId(config).callback; - callback(callbackSpy); - const request = server.requests[0]; - expect(request.url).to.eq(`https://bidder.adquery.io/prebid/qid`); - request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ qid: 'qid' })); - expect(callbackSpy.lastCall.lastArg).to.deep.equal({qid: 'qid'}); - }); - - it('gets a cached adqueryId', function() { - const config = { - params: {} - }; - getDataFromLocalStorageStub.withArgs('qid').returns('qid'); - - const callbackSpy = sinon.spy(); - const callback = adqueryIdSubmodule.getId(config).callback; - callback(callbackSpy); - expect(callbackSpy.lastCall.lastArg).to.deep.equal({qid: 'qid'}); - }); - - it('allows configurable id url', function() { - const config = { - params: { - url: 'https://bidder.adquery.io' - } - }; - const callbackSpy = sinon.spy(); - const callback = adqueryIdSubmodule.getId(config).callback; - callback(callbackSpy); - const request = server.requests[0]; - expect(request.url).to.eq('https://bidder.adquery.io'); - request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ qid: 'testqid' })); - expect(callbackSpy.lastCall.lastArg).to.deep.equal({qid: 'testqid'}); - }); - }); -}); diff --git a/test/spec/modules/adrelevantisBidAdapter_spec.js b/test/spec/modules/adrelevantisBidAdapter_spec.js index d25fdaf86d7..b87f9d6b86c 100644 --- a/test/spec/modules/adrelevantisBidAdapter_spec.js +++ b/test/spec/modules/adrelevantisBidAdapter_spec.js @@ -228,9 +228,7 @@ describe('AdrelevantisAdapter', function () { .returns({ site: { keywords: 'US Open', - ext: { - data: {category: 'sports/tennis'} - } + category: 'sports/tennis' } }); diff --git a/test/spec/modules/adrinoBidAdapter_spec.js b/test/spec/modules/adrinoBidAdapter_spec.js deleted file mode 100644 index 52b2796e6db..00000000000 --- a/test/spec/modules/adrinoBidAdapter_spec.js +++ /dev/null @@ -1,204 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/adrinoBidAdapter.js'; -import * as utils from '../../../src/utils'; - -describe('adrinoBidAdapter', function () { - describe('isBidRequestValid', function () { - const validBid = { - bidder: 'adrino', - params: { - hash: 'abcdef123456' - }, - mediaTypes: { - native: { - title: { - required: true - }, - image: { - required: true, - sizes: [[300, 150], [300, 210]] - } - } - }, - adUnitCode: 'adunit-code', - bidId: '12345678901234', - bidderRequestId: '98765432109876', - auctionId: '01234567891234', - }; - - it('should return true when all mandatory parameters are there', function () { - expect(spec.isBidRequestValid(validBid)).to.equal(true); - }); - - it('should return false when there are no params', function () { - const bid = { ...validBid }; - delete bid.params; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when unsupported media type is requested', function () { - const bid = { ...validBid }; - bid.mediaTypes = { banner: { sizes: [[300, 250]] } }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when hash is not a string', function () { - const bid = { ...validBid }; - bid.params.hash = 123; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - const bidRequest = { - bidder: 'adrino', - params: { - hash: 'abcdef123456' - }, - mediaTypes: { - native: { - title: { - required: true - }, - image: { - required: true, - sizes: [[300, 150], [300, 210]] - } - } - }, - adUnitCode: 'adunit-code', - bidId: '12345678901234', - bidderRequestId: '98765432109876', - auctionId: '01234567891234', - }; - - it('should build the request correctly with gdpr', function () { - const result = spec.buildRequests( - [ bidRequest ], - { gdprConsent: { gdprApplies: true, consentString: 'abc123' }, refererInfo: { referer: 'http://example.com/' } } - ); - expect(result.length).to.equal(1); - expect(result[0].method).to.equal('POST'); - expect(result[0].url).to.equal('https://prd-prebid-bidder.adrino.io/bidder/bid/'); - expect(result[0].data.bidId).to.equal('12345678901234'); - expect(result[0].data.placementHash).to.equal('abcdef123456'); - expect(result[0].data.referer).to.equal('http://example.com/'); - expect(result[0].data.userAgent).to.equal(navigator.userAgent); - expect(result[0].data).to.have.property('nativeParams'); - expect(result[0].data).to.have.property('gdprConsent'); - }); - - it('should build the request correctly without gdpr', function () { - const result = spec.buildRequests( - [ bidRequest ], - { refererInfo: { referer: 'http://example.com/' } } - ); - expect(result.length).to.equal(1); - expect(result[0].method).to.equal('POST'); - expect(result[0].url).to.equal('https://prd-prebid-bidder.adrino.io/bidder/bid/'); - expect(result[0].data.bidId).to.equal('12345678901234'); - expect(result[0].data.placementHash).to.equal('abcdef123456'); - expect(result[0].data.referer).to.equal('http://example.com/'); - expect(result[0].data.userAgent).to.equal(navigator.userAgent); - expect(result[0].data).to.have.property('nativeParams'); - expect(result[0].data).not.to.have.property('gdprConsent'); - }); - }); - - describe('interpretResponse', function () { - it('should interpret the response correctly', function () { - const response = { - requestId: '31662c69728811', - mediaType: 'native', - cpm: 0.53, - currency: 'PLN', - creativeId: '859115', - netRevenue: true, - ttl: 600, - width: 1, - height: 1, - noAd: false, - testAd: false, - native: { - title: 'Ad Title', - body: 'Ad Body', - image: { - url: 'http://emisja.contentstream.pl/_/getImageII/?vid=17180728299&typ=cs_300_150&element=IMAGE&scale=1&prefix=adart&nc=1643878278955', - height: 150, - width: 300 - }, - clickUrl: 'http://emisja.contentstream.pl/_/ctr2/?u=https%3A%2F%2Fonline.efortuna.pl%2Fpage%3Fkey%3Dej0xMzUzMTM1NiZsPTE1Mjc1MzY1JnA9NTMyOTA%253D&e=znU3tABN8K4N391dmUxYfte5G9tBaDXELJVo1_-kvaTJH2XwWRw77fmfL2YjcEmrbqRQ3M0GcJ0vPWcLtZlsrf8dWrAEHNoZKAC6JMnZF_65IYhTPbQIJ-zn3ac9TU7gEZftFKksH1al7rMuieleVv9r6_DtrOk_oZcYAe4rMRQM-TiWvivJRPBchAAblE0cqyG7rCunJFpal43sxlYm4GvcBJaYHzErn5PXjEzNbd3xHjkdiap-xU9y6BbfkUZ1xIMS8QZLvwNrTXMFCSfSRN2tgVfEj7KyGdLCITHSaFtuIKT2iW2pxC7f2RtPHnzsEPXH0SgAfhA3OxZ5jkQjOZy0PsO7MiCv3sJai5ezUAOjFgayU91ZhI0Y9r2YpB1tTGIjnO23wot8PvRENlThHQ%3D%3D&ref=https%3A%2F%2Fbox.adrino.cloud%2Ftmielcarz%2Fadrino_prebid%2Ftest_page3.html%3Fpbjs_debug%3Dtrue', - privacyLink: 'https://adrino.pl/wp-content/uploads/2021/01/POLITYKA-PRYWATNOS%CC%81CI-Adrino-Mobile.pdf', - impressionTrackers: [ - 'https://prd-impression-tracker-producer.adrino.io/impression/eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ7XCJpbXByZXNzaW9uSWRcIjpcIjMxNjYyYzY5NzI4ODExXCIsXCJkYXRlXCI6WzIwMjIsMiwzXSxcInBsYWNlbWVudEhhc2hcIjpcIjk0NTVjMDQxYzlkMTI1ZmIwNDE4MWVhMGVlZTJmMmFlXCIsXCJjYW1wYWlnbklkXCI6MTc5MjUsXCJhZHZlcnRpc2VtZW50SWRcIjo5MjA3OSxcInZpc3VhbGlzYXRpb25JZFwiOjg1OTExNSxcImNwbVwiOjUzLjB9IiwiZXhwIjoxNjQzOTE2MjUxLCJpYXQiOjE2NDM5MTU2NTF9.0Y_HvInGl6Xo5xP6rDLC8lzQRGvy-wKe0blk1o8ebWyVRFiUY1JGLUeE0k3sCsPNxgdHAv-o6EcbogpUuqlMJA' - ] - } - }; - - const serverResponse = { - body: response - }; - - const result = spec.interpretResponse(serverResponse, {}); - expect(result.length).to.equal(1); - expect(result[0]).to.equal(response); - }); - - it('should return empty array of responses', function () { - const response = { - requestId: '31662c69728811', - noAd: true, - testAd: false - }; - - const serverResponse = { - body: response - }; - - const result = spec.interpretResponse(serverResponse, {}); - expect(result.length).to.equal(0); - }); - }); - - describe('onBidWon', function () { - beforeEach(function() { - sinon.stub(utils, 'triggerPixel'); - }); - afterEach(function() { - utils.triggerPixel.restore(); - }); - - it('should trigger pixel', function () { - const response = { - requestId: '31662c69728811', - mediaType: 'native', - cpm: 0.53, - currency: 'PLN', - creativeId: '859115', - netRevenue: true, - ttl: 600, - width: 1, - height: 1, - noAd: false, - testAd: false, - native: { - title: 'Ad Title', - body: 'Ad Body', - image: { - url: 'http://emisja.contentstream.pl/_/getImageII/?vid=17180728299&typ=cs_300_150&element=IMAGE&scale=1&prefix=adart&nc=1643878278955', - height: 150, - width: 300 - }, - clickUrl: 'http://emisja.contentstream.pl/_/ctr2/?u=https%3A%2F%2Fonline.efortuna.pl%2Fpage%3Fkey%3Dej0xMzUzMTM1NiZsPTE1Mjc1MzY1JnA9NTMyOTA%253D&e=znU3tABN8K4N391dmUxYfte5G9tBaDXELJVo1_-kvaTJH2XwWRw77fmfL2YjcEmrbqRQ3M0GcJ0vPWcLtZlsrf8dWrAEHNoZKAC6JMnZF_65IYhTPbQIJ-zn3ac9TU7gEZftFKksH1al7rMuieleVv9r6_DtrOk_oZcYAe4rMRQM-TiWvivJRPBchAAblE0cqyG7rCunJFpal43sxlYm4GvcBJaYHzErn5PXjEzNbd3xHjkdiap-xU9y6BbfkUZ1xIMS8QZLvwNrTXMFCSfSRN2tgVfEj7KyGdLCITHSaFtuIKT2iW2pxC7f2RtPHnzsEPXH0SgAfhA3OxZ5jkQjOZy0PsO7MiCv3sJai5ezUAOjFgayU91ZhI0Y9r2YpB1tTGIjnO23wot8PvRENlThHQ%3D%3D&ref=https%3A%2F%2Fbox.adrino.cloud%2Ftmielcarz%2Fadrino_prebid%2Ftest_page3.html%3Fpbjs_debug%3Dtrue', - privacyLink: 'https://adrino.pl/wp-content/uploads/2021/01/POLITYKA-PRYWATNOS%CC%81CI-Adrino-Mobile.pdf', - impressionTrackers: [ - 'https://prd-impression-tracker-producer.adrino.io/impression/eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ7XCJpbXByZXNzaW9uSWRcIjpcIjMxNjYyYzY5NzI4ODExXCIsXCJkYXRlXCI6WzIwMjIsMiwzXSxcInBsYWNlbWVudEhhc2hcIjpcIjk0NTVjMDQxYzlkMTI1ZmIwNDE4MWVhMGVlZTJmMmFlXCIsXCJjYW1wYWlnbklkXCI6MTc5MjUsXCJhZHZlcnRpc2VtZW50SWRcIjo5MjA3OSxcInZpc3VhbGlzYXRpb25JZFwiOjg1OTExNSxcImNwbVwiOjUzLjB9IiwiZXhwIjoxNjQzOTE2MjUxLCJpYXQiOjE2NDM5MTU2NTF9.0Y_HvInGl6Xo5xP6rDLC8lzQRGvy-wKe0blk1o8ebWyVRFiUY1JGLUeE0k3sCsPNxgdHAv-o6EcbogpUuqlMJA' - ] - } - }; - - spec.onBidWon(response); - expect(utils.triggerPixel.callCount).to.equal(1) - }); - }); -}); diff --git a/test/spec/modules/adriverBidAdapter_spec.js b/test/spec/modules/adriverBidAdapter_spec.js index 12c0a15fb06..9d410090885 100644 --- a/test/spec/modules/adriverBidAdapter_spec.js +++ b/test/spec/modules/adriverBidAdapter_spec.js @@ -79,9 +79,6 @@ describe('adriverAdapter', function () { bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', transactionId: '04f2659e-c005-4eb1-a57c-fa93145e3843', - userId: { - adrcid: 'testCookieValue', - }, userIdAsEids: [ { source: 'id5-sync.com', @@ -292,34 +289,6 @@ describe('adriverAdapter', function () { expect(payload.imp[0].pmp.deals[0].bidfloorcur).to.deep.equal('RUB'); }); - const cookieValues = [ - { adrcid: 'adrcidValue' }, - { adrcid: undefined } - ] - cookieValues.forEach(cookieValue => describe('test cookie exist or not behavior', function () { - let expectedValues = { - adrcid: cookieValue.adrcid, - at: '', - cur: '', - tmax: '', - site: '', - id: '', - user: '', - device: '', - imp: '' - } - - it('check adrcid if it exists', function () { - bidRequests[0].userId.adrcid = cookieValue.adrcid; - const payload = JSON.parse(spec.buildRequests(bidRequests).data); - if (cookieValue.adrcid) { - expect(Object.keys(payload)).to.have.members(Object.keys(expectedValues)); - } else { - expect(payload.adrcid).to.equal(undefined); - } - }); - })); - it('sends bid request to ENDPOINT via POST', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.equal(ENDPOINT); @@ -429,9 +398,6 @@ describe('adriverAdapter', function () { bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', transactionId: '04f2659e-c005-4eb1-a57c-fa93145e3843', - userId: { - adrcid: 'testCookieValue', - }, userIdAsEids: [ { source: 'id5-sync.com', @@ -569,9 +535,6 @@ describe('adriverAdapter', function () { bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', transactionId: '04f2659e-c005-4eb1-a57c-fa93145e3843', - userId: { - adrcid: 'testCookieValue', - }, userIdAsEids: [ { source: 'id5-sync.com', diff --git a/test/spec/modules/adriverIdSystem_spec.js b/test/spec/modules/adriverIdSystem_spec.js deleted file mode 100644 index 8780c79f719..00000000000 --- a/test/spec/modules/adriverIdSystem_spec.js +++ /dev/null @@ -1,84 +0,0 @@ -import { adriverIdSubmodule, storage } from 'modules/adriverIdSystem.js'; -import { server } from 'test/mocks/xhr.js'; -import * as utils from '../../../src/utils.js'; - -describe('AdriverIdSystem', function () { - describe('getId', function() { - let setCookieStub, setLocalStorageStub, removeFromLocalStorageStub, logErrorStub; - - beforeEach(function() { - setCookieStub = sinon.stub(storage, 'setCookie'); - setLocalStorageStub = sinon.stub(storage, 'setDataInLocalStorage'); - removeFromLocalStorageStub = sinon.stub(storage, 'removeDataFromLocalStorage'); - logErrorStub = sinon.stub(utils, 'logError'); - }); - - afterEach(function () { - setCookieStub.restore(); - setLocalStorageStub.restore(); - removeFromLocalStorageStub.restore(); - logErrorStub.restore(); - }); - - it('should log an error and continue to callback if request errors', function () { - const config = { - params: {} - }; - - const callbackSpy = sinon.spy(); - const callback = adriverIdSubmodule.getId(config).callback; - callback(callbackSpy); - const request = server.requests[0]; - expect(request.url).to.include('https://ad.adriver.ru/cgi-bin/json.cgi'); - request.respond(503, null, 'Unavailable'); - expect(logErrorStub.calledOnce).to.be.true; - expect(callbackSpy.calledOnce).to.be.true; - }); - - it('test call user sync url with the right params', function() { - const config = { - params: {} - }; - - const callbackSpy = sinon.spy(); - const callback = adriverIdSubmodule.getId(config).callback; - callback(callbackSpy); - const request = server.requests[0]; - expect(request.url).to.include('https://ad.adriver.ru/cgi-bin/json.cgi'); - request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ adrcid: 'testAdriverId' })); - expect(callbackSpy.lastCall.lastArg).to.deep.equal('testAdriverId'); - }); - - const responses = [ - { adrcid: 'adrcidValue' }, - { adrcid: undefined } - ] - - responses.forEach(response => describe('test user sync response behavior', function () { - const config = { - params: {} - }; - it('should save adrcid if it exists', function () { - const result = adriverIdSubmodule.getId(config); - result.callback((id) => { - expect(id).to.be.deep.equal(response.adrcid ? response.adrcid : undefined); - }); - - let request = server.requests[0]; - request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ adrcid: response.adrcid })); - - let now = new Date(); - now.setTime(now.getTime() + 86400 * 1825 * 1000); - const minimalDate = new Date(0).toString(); - - if (response.adrcid) { - expect(setCookieStub.calledWith('adrcid', response.adrcid, now.toUTCString())).to.be.true; - expect(setLocalStorageStub.calledWith('adrcid', response.adrcid)).to.be.true; - } else { - expect(setCookieStub.calledWith('adrcid', '', minimalDate)).to.be.false; - expect(removeFromLocalStorageStub.calledWith('adrcid')).to.be.false; - } - }); - })); - }); -}); diff --git a/test/spec/modules/adtelligentBidAdapter_spec.js b/test/spec/modules/adtelligentBidAdapter_spec.js index 117a6d5966a..4cfb367efb3 100644 --- a/test/spec/modules/adtelligentBidAdapter_spec.js +++ b/test/spec/modules/adtelligentBidAdapter_spec.js @@ -14,10 +14,9 @@ const aliasEP = { appaloosa: 'https://ghb.hb.appaloosa.media/v2/auction/', appaloosa_publisherSuffix: 'https://ghb.hb.appaloosa.media/v2/auction/', onefiftytwomedia: 'https://ghb.ads.152media.com/v2/auction/', + mediafuse: 'https://ghb.hbmp.mediafuse.com/v2/auction/', navelix: 'https://ghb.hb.navelix.com/v2/auction/', bidsxchange: 'https://ghb.hbd.bidsxchange.com/v2/auction/', - streamkey: 'https://ghb.hb.streamkey.net/v2/auction/', - janet: 'https://ghb.bidder.jmgads.com/v2/auction/', }; const DEFAULT_ADATPER_REQ = { bidderCode: 'adtelligent' }; diff --git a/test/spec/modules/advangelistsBidAdapter_spec.js b/test/spec/modules/advangelistsBidAdapter_spec.js deleted file mode 100755 index e1cd6977c5d..00000000000 --- a/test/spec/modules/advangelistsBidAdapter_spec.js +++ /dev/null @@ -1,139 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/advangelistsBidAdapter'; -import { BANNER, VIDEO } from 'src/mediaTypes'; - -describe('advangelistsBidAdapter', function () { - let bidRequests; - let bidRequestsVid; - - beforeEach(function () { - bidRequests = [{'bidder': 'advangelists', 'params': {'pubid': '0cf8d6d643e13d86a5b6374148a4afac', 'placement': 1234}, 'crumbs': {'pubcid': '979fde13-c71e-4ac2-98b7-28c90f99b449'}, 'mediaTypes': {'banner': {'sizes': [[300, 250]]}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': 'f72931e6-2b0e-4e37-a2bc-1ea912141f81', 'sizes': [[300, 250]], 'bidId': '2aa73f571eaf29', 'bidderRequestId': '1bac84515a7af3', 'auctionId': '5dbc60fa-1aa1-41ce-9092-e6bbd4d478f7', 'src': 'client', 'bidRequestsCount': 1, 'pageurl': 'http://google.com'}]; - - bidRequestsVid = [{'bidder': 'advangelists', 'params': {'pubid': '8537f00948fc37cc03c5f0f88e198a76', 'placement': 1234}, 'crumbs': {'pubcid': '979fde13-c71e-4ac2-98b7-28c90f99b449'}, 'mediaTypes': {'video': {'playerSize': [[320, 480]], 'context': 'instream', 'skip': 1, 'mimes': ['video/mp4', 'application/javascript'], 'playbackmethod': [2, 6], 'maxduration': 30}}, 'adUnitCode': 'video1', 'transactionId': '8b060952-93f7-4863-af44-bb8796b97c42', 'sizes': [], 'bidId': '25c6ab92aa0e81', 'bidderRequestId': '1d420b73a013fc', 'auctionId': '9a69741c-34fb-474c-83e1-cfa003aaee17', 'src': 'client', 'bidRequestsCount': 1, 'pageurl': 'http://google.com'}]; - }); - - describe('spec.isBidRequestValid', function () { - it('should return true when the required params are passed for banner', function () { - const bidRequest = bidRequests[0]; - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return true when the required params are passed for video', function () { - const bidRequests = bidRequestsVid[0]; - expect(spec.isBidRequestValid(bidRequests)).to.equal(true); - }); - - it('should return false when no pub id params are passed', function () { - const bidRequest = bidRequests[0]; - bidRequest.params.pubid = ''; - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false when no placement params are passed', function () { - const bidRequest = bidRequests[0]; - bidRequest.params.placement = ''; - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false when a bid request is not passed', function () { - expect(spec.isBidRequestValid()).to.equal(false); - expect(spec.isBidRequestValid({})).to.equal(false); - }); - }); - - describe('spec.buildRequests', function () { - it('should create a POST request for each bid', function () { - const bidRequest = bidRequests[0]; - const requests = spec.buildRequests([ bidRequest ]); - expect(requests[0].method).to.equal('POST'); - }); - - it('should create a POST request for each bid in video request', function () { - const bidRequest = bidRequestsVid[0]; - const requests = spec.buildRequests([ bidRequest ]); - expect(requests[0].method).to.equal('POST'); - }); - - it('should have domain in request', function () { - const bidRequest = bidRequests[0]; - const requests = spec.buildRequests([ bidRequest ]); - expect(requests[0].data.site.domain).length !== 0; - }); - }); - - describe('spec.interpretResponse', function () { - describe('for banner bids', function () { - it('should return no bids if the response is not valid', function () { - const bidRequest = bidRequests[0]; - bidRequest.mediaTypes = { banner: {} }; - const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); - - if (typeof bidResponse !== 'undefined') { - expect(bidResponse.length).to.equal(0); - } else { - expect(true).to.equal(true); - } - }); - - it('should return no bids if the response is empty', function () { - const bidRequest = bidRequests[0]; - bidRequest.mediaTypes = { banner: {} }; - const bidResponse = spec.interpretResponse({ body: [] }, { bidRequest }); - if (typeof bidResponse !== 'undefined') { - expect(bidResponse.length).to.equal(0); - } else { expect(true).to.equal(true); } - }); - - it('should return valid video bid responses', function () { - let _mediaTypes = VIDEO; - const advangelistsbidreqVid = {'bidRequest': {'mediaTypes': {'video': {'w': 320, 'h': 480}}}}; - const serverResponseVid = {'cur': 'USD', 'id': '25c6ab92aa0e81', 'seatbid': [{'seat': '3', 'bid': [{'crid': '1855', 'h': 480, 'protocol': 2, 'nurl': 'http://nep.advangelists.com/xp/evt?pp=1MO1wiaMhhq7wLRzZZwwwPkJxxKpYEnM5k5MH4qSGm1HR8rp3Nl7vDocvzZzSAvE4pnREL9mQ1kf5PDjk6E8em6DOk7vVrYUH1TYQyqCucd58PFpJNN7h30RXKHHFg3XaLuQ3PKfMuI1qZATBJ6WHcu875y0hqRdiewn0J4JsCYF53M27uwmcV0HnQxARQZZ72mPqrW95U6wgkZljziwKrICM3aBV07TU6YK5R5AyzJRuD6mtrQ2xtHlQ3jXVYKE5bvWFiUQd90t0jOGhPtYBNoOfP7uQ4ZZj4pyucxbr96orHe9PSOn9UpCSWArdx7s8lOfDpwOvbMuyGxynbStDWm38sDgd4bMHnIt762m5VMDNJfiUyX0vWzp05OsufJDVEaWhAM62i40lQZo7mWP4ipoOWLkmlaAzFIMsTcNaHAHiKKqGEOZLkCEhFNM0SLcvgN2HFRULOOIZvusq7TydOKxuXgCS91dLUDxDDDFUK83BFKlMkTxnCzkLbIR1bd9GKcr1TRryOrulyvRWAKAIhEsUzsc5QWFUhmI2dZ1eqnBQJ0c89TaPcnoaP2WipF68UgyiOstf2CBy0M34858tC5PmuQwQYwXscg6zyqDwR0i9MzGH4FkTyU5yeOlPcsA0ht6UcoCdFpHpumDrLUwAaxwGk1Nj8S6YlYYT5wNuTifDGbg22QKXzZBkUARiyVvgPn9nRtXnrd7WmiMYq596rya9RQj7LC0auQW8bHVQLEe49shsZDnAwZTWr4QuYKqgRGZcXteG7RVJe0ryBZezOq11ha9C0Lv0siNVBahOXE35Wzoq4c4BDaGpqvhaKN7pjeWLGlQR04ufWekwxiMWAvjmfgAfexBJ7HfbYNZpq__', 'adid': '61_1855', 'adomain': ['chevrolet.com'], 'price': 2, 'w': 320, 'iurl': 'https://daf37cpxaja7f.cloudfront.net/c61/creative_url_14922301369663_1.png', 'cat': ['IAB2'], 'id': '7f570b40-aca1-4806-8ea8-818ea679c82b_0', 'attr': [], 'impid': '0', 'cid': '61'}]}], 'bidid': '7f570b40-aca1-4806-8ea8-818ea679c82b'}; - const bidResponseVid = spec.interpretResponse({ body: serverResponseVid }, advangelistsbidreqVid); - delete bidResponseVid['vastUrl']; - delete bidResponseVid['ad']; - expect(bidResponseVid).to.deep.equal({ - requestId: bidRequestsVid[0].bidId, - bidderCode: 'advangelists', - creativeId: serverResponseVid.seatbid[0].bid[0].crid, - cpm: serverResponseVid.seatbid[0].bid[0].price, - width: serverResponseVid.seatbid[0].bid[0].w, - height: serverResponseVid.seatbid[0].bid[0].h, - mediaType: 'video', - meta: { 'advertiserDomains': serverResponseVid.seatbid[0].bid[0].adomain }, - currency: 'USD', - netRevenue: true, - ttl: 60 - }); - }); - - it('should return valid banner bid responses', function () { - const advangelistsbidreq = {bids: {}}; - bidRequests.forEach(bid => { - let _mediaTypes = (bid.mediaTypes && bid.mediaTypes.video ? VIDEO : BANNER); - advangelistsbidreq.bids[bid.bidId] = {mediaTypes: _mediaTypes, - w: _mediaTypes == BANNER ? bid.mediaTypes[_mediaTypes].sizes[0][0] : bid.mediaTypes[_mediaTypes].playerSize[0], - h: _mediaTypes == BANNER ? bid.mediaTypes[_mediaTypes].sizes[0][1] : bid.mediaTypes[_mediaTypes].playerSize[1] - - }; - }); - const serverResponse = {'id': '2aa73f571eaf29', 'seatbid': [{'bid': [{'id': '2c5e8a1a84522d', 'impid': '2c5e8a1a84522d', 'price': 0.81, 'adid': 'abcde-12345', 'nurl': '', 'adm': '
', 'iurl': '', 'cid': 'campaign1', 'crid': 'abcde-12345', 'adomain': ['chevrolet.com'], 'w': 300, 'h': 250}], 'seat': '19513bcfca8006'}], 'bidid': '19513bcfca8006', 'cur': 'USD', 'w': 300, 'h': 250}; - - const bidResponse = spec.interpretResponse({ body: serverResponse }, advangelistsbidreq); - expect(bidResponse).to.deep.equal({ - requestId: bidRequests[0].bidId, - ad: serverResponse.seatbid[0].bid[0].adm, - bidderCode: 'advangelists', - creativeId: serverResponse.seatbid[0].bid[0].crid, - cpm: serverResponse.seatbid[0].bid[0].price, - width: serverResponse.seatbid[0].bid[0].w, - height: serverResponse.seatbid[0].bid[0].h, - mediaType: 'banner', - meta: { 'advertiserDomains': serverResponse.seatbid[0].bid[0].adomain }, - currency: 'USD', - netRevenue: true, - ttl: 60 - }); - }); - }); - }); -}); diff --git a/test/spec/modules/adxcgBidAdapter_spec.js b/test/spec/modules/adxcgBidAdapter_spec.js index 7721295572c..551d50b60e7 100644 --- a/test/spec/modules/adxcgBidAdapter_spec.js +++ b/test/spec/modules/adxcgBidAdapter_spec.js @@ -1,902 +1,653 @@ -// jshint esversion: 6, es3: false, node: true -import {assert} from 'chai'; +import {expect} from 'chai'; import {spec} from 'modules/adxcgBidAdapter.js'; -import {config} from 'src/config.js'; -import {createEidsArray} from 'modules/userId/eids.js'; -const utils = require('src/utils'); - -describe('Adxcg adapter', function () { - let bids = []; - - describe('isBidRequestValid', function () { - let bid = { - 'bidder': 'adxcg', - 'params': { - 'adzoneid': '19910113' +import {deepClone, parseUrl} from 'src/utils.js'; +import * as utils from '../../../src/utils.js'; + +describe('AdxcgAdapter', function () { + let bidBanner = { + bidder: 'adxcg', + params: { + adzoneid: '1' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [640, 360], + [1, 1] + ] } - }; - - it('should return true when required params found', function () { - assert(spec.isBidRequestValid(bid)); + }, + bidId: '84ab500420319d', + bidderRequestId: '7101db09af0db2', + auctionId: '1d1a030790a475' + }; + + let bidVideo = { + bidder: 'adxcg', + params: { + adzoneid: '20', + video: { + api: [2], + maxduration: 30 + } + }, + mediaTypes: { + video: { + context: 'instream', + playerSize: [[640, 480]], + protocols: [1, 2], + mimes: ['video/mp4'], + } + }, + adUnitCode: 'adunit-code', + bidId: '84ab500420319d', + bidderRequestId: '7101db09af0db2', + auctionId: '1d1a030790a475' + }; + + let bidNative = { + bidder: 'adxcg', + params: { + adzoneid: '2379' + }, + mediaTypes: { + native: { + image: { + sendId: false, + required: true, + sizes: [80, 80] + }, + title: { + required: true, + len: 75 + }, + body: { + required: true, + len: 200 + }, + sponsoredBy: { + required: false, + len: 20 + } + } + }, + adUnitCode: 'adunit-code', + bidId: '84ab500420319d', + bidderRequestId: '7101db09af0db2', + auctionId: '1d1a030790a475' + }; - bid.params = { - adzoneid: 4332, - }; - assert(spec.isBidRequestValid(bid)); + describe('isBidRequestValid', function () { + it('should return true when required params found bidNative', function () { + expect(spec.isBidRequestValid(bidNative)).to.equal(true); }); - it('should return false when required params are missing', function () { - bid.params = {}; - assert.isFalse(spec.isBidRequestValid(bid)); - - bid.params = { - mname: 'some-placement' - }; - assert.isFalse(spec.isBidRequestValid(bid)); - - bid.params = { - inv: 1234 - }; - assert.isFalse(spec.isBidRequestValid(bid)); + it('should return true when required params found bidVideo', function () { + expect(spec.isBidRequestValid(bidVideo)).to.equal(true); }); - }); - describe('buildRequests', function () { - beforeEach(function () { - config.resetConfig(); + it('should return true when required params found bidBanner', function () { + expect(spec.isBidRequestValid(bidBanner)).to.equal(true); }); - it('should send request with correct structure', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: { - adzoneid: '19910113' - } - }]; - let request = spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}); - assert.equal(request.method, 'POST'); - assert.equal(request.url, 'https://pbc.adxcg.net/rtb/ortb/pbc?adExchangeId=1'); - assert.deepEqual(request.options, {contentType: 'application/json'}); - assert.ok(request.data); + it('should return false when required params not found', function () { + expect(spec.isBidRequestValid({})).to.be.false; }); - describe('user privacy', function () { - it('should send GDPR Consent data to exchange if gdprApplies', function () { - let validBidRequests = [{bidId: 'bidId', params: {test: 1}}]; - let bidderRequest = { - gdprConsent: {gdprApplies: true, consentString: 'consentDataString'}, - refererInfo: {referer: 'page'} - }; - let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data); - - assert.equal(request.user.ext.consent, bidderRequest.gdprConsent.consentString); - assert.equal(request.regs.ext.gdpr, bidderRequest.gdprConsent.gdprApplies); - assert.equal(typeof request.regs.ext.gdpr, 'number'); - }); - - it('should send gdpr as number', function () { - let validBidRequests = [{bidId: 'bidId', params: {test: 1}}]; - let bidderRequest = { - gdprConsent: {gdprApplies: true, consentString: 'consentDataString'}, - refererInfo: {referer: 'page'} - }; - let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data); - - assert.equal(typeof request.regs.ext.gdpr, 'number'); - assert.equal(request.regs.ext.gdpr, 1); - }); - - it('should send CCPA Consent data to exchange', function () { - let validBidRequests = [{bidId: 'bidId', params: {test: 1}}]; - let bidderRequest = {uspConsent: '1YA-', refererInfo: {referer: 'page'}}; - let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data); - - assert.equal(request.regs.ext.us_privacy, '1YA-'); - - bidderRequest = { - uspConsent: '1YA-', - gdprConsent: {gdprApplies: true, consentString: 'consentDataString'}, - refererInfo: {referer: 'page'} - }; - request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data); - - assert.equal(request.regs.ext.us_privacy, '1YA-'); - assert.equal(request.user.ext.consent, 'consentDataString'); - assert.equal(request.regs.ext.gdpr, 1); - }); - - it('should not send GDPR Consent data to adxcg if gdprApplies is undefined', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {siteId: 'siteId'} - }]; - let bidderRequest = { - gdprConsent: {gdprApplies: false, consentString: 'consentDataString'}, - refererInfo: {referer: 'page'} - }; - let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data); - - assert.equal(request.user.ext.consent, 'consentDataString'); - assert.equal(request.regs.ext.gdpr, 0); - - bidderRequest = {gdprConsent: {consentString: 'consentDataString'}, refererInfo: {referer: 'page'}}; - request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data); - - assert.equal(request.user, undefined); - assert.equal(request.regs, undefined); - }); - it('should send default GDPR Consent data to exchange', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {siteId: 'siteId'} - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data); - - assert.equal(request.user, undefined); - assert.equal(request.regs, undefined); - }); + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bidBanner); + delete bid.params; + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should add test and is_debug to request, if test is set in parameters', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {test: 1} - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data); - - assert.ok(request.is_debug); - assert.equal(request.test, 1); + it('should return true when required video params not found', function () { + const simpleVideo = JSON.parse(JSON.stringify(bidVideo)); + simpleVideo.params.adzoneid = 123; + expect(spec.isBidRequestValid(simpleVideo)).to.be.false; }); + }); - it('should have default request structure', function () { - let keys = 'site,geo,device,source,ext,imp'.split(','); - let validBidRequests = [{ - bidId: 'bidId', - params: {siteId: 'siteId'} - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data); - let data = Object.keys(request); - - assert.deepEqual(keys, data); + describe('request function http', function () { + it('creates a valid adxcg request url bidBanner', function () { + let request = spec.buildRequests([bidBanner]); + expect(request).to.exist; + expect(request.method).to.equal('GET'); + let parsedRequestUrl = parseUrl(request.url); + expect(parsedRequestUrl.hostname).to.equal('hbps.adxcg.net'); + expect(parsedRequestUrl.pathname).to.equal('/get/adi'); + + let query = parsedRequestUrl.search; + expect(query.renderformat).to.equal('javascript'); + expect(query.ver).to.equal('r20210330PB40'); + expect(query.source).to.equal('pbjs10'); + expect(query.pbjs).to.equal('$prebid.version$'); + expect(query.adzoneid).to.equal('1'); + expect(query.format).to.equal('300x250|640x360|1x1'); + expect(query.jsonp).to.be.undefined; + expect(query.prebidBidIds).to.equal('84ab500420319d'); + expect(query.bidfloors).to.equal('0'); + + expect(query).to.have.property('secure'); + expect(query).to.have.property('uw'); + expect(query).to.have.property('uh'); + expect(query).to.have.property('dpr'); + expect(query).to.have.property('bt'); + expect(query).to.have.property('cookies'); + expect(query).to.have.property('tz'); + expect(query).to.have.property('dt'); + expect(query).to.have.property('iob'); + expect(query).to.have.property('rndid'); + expect(query).to.have.property('ref'); + expect(query).to.have.property('url'); }); - it('should set request keys correct values', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {siteId: 'siteId'}, - transactionId: 'transactionId' - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data); - - assert.equal(request.source.tid, validBidRequests[0].transactionId); - assert.equal(request.source.fd, 1); + it('creates a valid adxcg request url bidVideo', function () { + let request = spec.buildRequests([bidVideo]); + expect(request).to.exist; + expect(request.method).to.equal('GET'); + let parsedRequestUrl = parseUrl(request.url); + expect(parsedRequestUrl.hostname).to.equal('hbps.adxcg.net'); + expect(parsedRequestUrl.pathname).to.equal('/get/adi'); + + let query = parsedRequestUrl.search; + // general part + expect(query.renderformat).to.equal('javascript'); + expect(query.ver).to.equal('r20210330PB40'); + expect(query.source).to.equal('pbjs10'); + expect(query.pbjs).to.equal('$prebid.version$'); + expect(query.adzoneid).to.equal('20'); + expect(query.format).to.equal('640x480'); + expect(query.jsonp).to.be.undefined; + expect(query.prebidBidIds).to.equal('84ab500420319d'); + expect(query.bidfloors).to.equal('0'); + + expect(query).to.have.property('secure'); + expect(query).to.have.property('uw'); + expect(query).to.have.property('uh'); + expect(query).to.have.property('dpr'); + expect(query).to.have.property('bt'); + expect(query).to.have.property('cookies'); + expect(query).to.have.property('tz'); + expect(query).to.have.property('dt'); + expect(query).to.have.property('iob'); + expect(query).to.have.property('rndid'); + expect(query).to.have.property('ref'); + expect(query).to.have.property('url'); + + // video specific part + expect(query['video.maxduration.0']).to.equal('30'); + expect(query['video.mimes.0']).to.equal('video/mp4'); + expect(query['video.context.0']).to.equal('instream'); }); - it('should send info about device', function () { - config.setConfig({ - device: {w: 100, h: 100} - }); - let validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: '1000'} - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data); - - assert.equal(request.device.ua, navigator.userAgent); - assert.equal(request.device.w, 100); - assert.equal(request.device.h, 100); + it('creates a valid adxcg request url bidNative', function () { + let request = spec.buildRequests([bidNative]); + expect(request).to.exist; + expect(request.method).to.equal('GET'); + let parsedRequestUrl = parseUrl(request.url); + expect(parsedRequestUrl.hostname).to.equal('hbps.adxcg.net'); + expect(parsedRequestUrl.pathname).to.equal('/get/adi'); + + let query = parsedRequestUrl.search; + expect(query.renderformat).to.equal('javascript'); + expect(query.ver).to.equal('r20210330PB40'); + expect(query.source).to.equal('pbjs10'); + expect(query.pbjs).to.equal('$prebid.version$'); + expect(query.adzoneid).to.equal('2379'); + expect(query.format).to.equal('0x0'); + expect(query.jsonp).to.be.undefined; + expect(query.prebidBidIds).to.equal('84ab500420319d'); + expect(query.bidfloors).to.equal('0'); + + expect(query).to.have.property('secure'); + expect(query).to.have.property('uw'); + expect(query).to.have.property('uh'); + expect(query).to.have.property('dpr'); + expect(query).to.have.property('bt'); + expect(query).to.have.property('cookies'); + expect(query).to.have.property('tz'); + expect(query).to.have.property('dt'); + expect(query).to.have.property('iob'); + expect(query).to.have.property('rndid'); + expect(query).to.have.property('ref'); + expect(query).to.have.property('url'); }); + }); - it('should send app info', function () { - config.setConfig({ - app: {id: 'appid'}, - ortb2: {app: {name: 'appname'}} + describe('gdpr compliance', function () { + it('should send GDPR Consent data if gdprApplies', function () { + let request = spec.buildRequests([bidBanner], { + gdprConsent: { + gdprApplies: true, + consentString: 'consentDataString' + } }); - let validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: '1000'} - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data); - - assert.equal(request.app.id, 'appid'); - assert.equal(request.app.name, 'appname'); - assert.equal(request.site, undefined); + let parsedRequestUrl = parseUrl(request.url); + let query = parsedRequestUrl.search; + + expect(query.gdpr).to.equal('1'); + expect(query.gdpr_consent).to.equal('consentDataString'); }); - it('should send info about the site', function () { - config.setConfig({ - site: { - id: '123123', - publisher: { - domain: 'publisher.domain.com' - } - }, - ortb2: { - site: { - publisher: { - id: 4441, - name: 'publisher\'s name' - } - } + it('should not send GDPR Consent data if gdprApplies is false or undefined', function () { + let request = spec.buildRequests([bidBanner], { + gdprConsent: { + gdprApplies: false, + consentString: 'consentDataString' } }); - let validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: '1000'} - }]; - let refererInfo = {referer: 'page'}; - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo}).data); - - assert.deepEqual(request.site, { - domain: 'localhost', - id: '123123', - page: refererInfo.referer, - publisher: { - domain: 'publisher.domain.com', - id: 4441, - name: 'publisher\'s name' - } - }); - }); + let parsedRequestUrl = parseUrl(request.url); + let query = parsedRequestUrl.search; - it('should pass extended ids', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {}, - userIdAsEids: createEidsArray({ - tdid: 'TTD_ID_FROM_USER_ID_MODULE', - pubcid: 'pubCommonId_FROM_USER_ID_MODULE' - }) - }]; - - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data); - assert.deepEqual(request.user.ext.eids, [ - {source: 'adserver.org', uids: [{id: 'TTD_ID_FROM_USER_ID_MODULE', atype: 1, ext: {rtiPartner: 'TDID'}}]}, - {source: 'pubcid.org', uids: [{id: 'pubCommonId_FROM_USER_ID_MODULE', atype: 1}]} - ]); + expect(query.gdpr).to.be.undefined; + expect(query.gdpr_consent).to.be.undefined; }); + }); - it('should send currency if defined', function () { - config.setConfig({currency: {adServerCurrency: 'EUR'}}); - let validBidRequests = [{params: {}}]; - let refererInfo = {referer: 'page'}; - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo}).data); + describe('userid pubcid should be passed to querystring', function () { + let bidderRequests = {}; + let bid = deepClone([bidBanner]); + bid[0].userId = {pubcid: 'pubcidabcd'}; - assert.deepEqual(request.cur, ['EUR']); + it('should send pubcid if available', function () { + let request = spec.buildRequests(bid, bidderRequests); + let parsedRequestUrl = parseUrl(request.url); + let query = parsedRequestUrl.search; + expect(query.pubcid).to.equal('pubcidabcd'); }); + }); - it('should pass supply chain object', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {}, - schain: { - validation: 'strict', - config: { - ver: '1.0' - } - } - }]; + describe('userid tdid should be passed to querystring', function () { + let bid = deepClone([bidBanner]); + let bidderRequests = {}; - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data); - assert.deepEqual(request.source.ext.schain, { - validation: 'strict', - config: { - ver: '1.0' - } - }); + bid[0].userId = {tdid: 'tdidabcd'}; + + it('should send pubcid if available', function () { + let request = spec.buildRequests(bid, bidderRequests); + let parsedRequestUrl = parseUrl(request.url); + let query = parsedRequestUrl.search; + expect(query.tdid).to.equal('tdidabcd'); }); + }); - describe('bids', function () { - it('should add more than one bid to the request', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {siteId: 'siteId'} - }, { - bidId: 'bidId2', - params: {siteId: 'siteId'} - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data); - - assert.equal(request.imp.length, 2); - }); - it('should add incrementing values of id', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: '1000'}, - mediaTypes: {video: {}} - }, { - bidId: 'bidId2', - params: {adzoneid: '1000'}, - mediaTypes: {video: {}} - }, { - bidId: 'bidId3', - params: {adzoneid: '1000'}, - mediaTypes: {video: {}} - }]; - let imps = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp; - - for (let i = 0; i < 3; i++) { - assert.equal(imps[i].id, i + 1); - } - }); + describe('userid id5id should be passed to querystring', function () { + let bid = deepClone([bidBanner]); + let bidderRequests = {}; - it('should add adzoneid', function () { - let validBidRequests = [{bidId: 'bidId', params: {adzoneid: 1000}, mediaTypes: {video: {}}}, - {bidId: 'bidId2', params: {adzoneid: 1001}, mediaTypes: {video: {}}}, - {bidId: 'bidId3', params: {adzoneid: 1002}, mediaTypes: {video: {}}}]; - let imps = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp; - for (let i = 0; i < 3; i++) { - assert.equal(imps[i].tagid, validBidRequests[i].params.adzoneid); - } - }); + bid[0].userId = {id5id: {uid: 'id5idsample'}}; - describe('price floors', function () { - it('should not add if floors module not configured', function () { - const validBidRequests = [{bidId: 'bidId', params: {adzoneid: 1000}, mediaTypes: {video: {}}}]; - let imp = getRequestImps(validBidRequests)[0]; - - assert.equal(imp.bidfloor, undefined); - assert.equal(imp.bidfloorcur, undefined); - }); - - it('should not add if floor price not defined', function () { - const validBidRequests = [getBidWithFloor()]; - let imp = getRequestImps(validBidRequests)[0]; - - assert.equal(imp.bidfloor, undefined); - assert.equal(imp.bidfloorcur, 'USD'); - }); - - it('should request floor price in adserver currency', function () { - config.setConfig({currency: {adServerCurrency: 'DKK'}}); - const validBidRequests = [getBidWithFloor()]; - let imp = getRequestImps(validBidRequests)[0]; - - assert.equal(imp.bidfloor, undefined); - assert.equal(imp.bidfloorcur, 'DKK'); - }); - - it('should add correct floor values', function () { - const expectedFloors = [1, 1.3, 0.5]; - const validBidRequests = expectedFloors.map(getBidWithFloor); - let imps = getRequestImps(validBidRequests); - - expectedFloors.forEach((floor, index) => { - assert.equal(imps[index].bidfloor, floor); - assert.equal(imps[index].bidfloorcur, 'USD'); - }); - }); - - function getBidWithFloor(floor) { - return { - params: {adzoneid: 1}, - mediaTypes: {video: {}}, - getFloor: ({currency}) => { - return { - currency: currency, - floor - }; - } - }; - } - }); + it('should send pubcid if available', function () { + let request = spec.buildRequests(bid, bidderRequests); + let parsedRequestUrl = parseUrl(request.url); + let query = parsedRequestUrl.search; + expect(query.id5id).to.equal('id5idsample'); + }); + }); - describe('multiple media types', function () { - it('should use all configured media types for bidding', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: 1000}, - mediaTypes: { - banner: { - sizes: [[100, 100], [200, 300]] - }, - video: {} - } - }, { - bidId: 'bidId1', - params: {adzoneid: 1000}, - mediaTypes: { - video: {}, - native: {} - } - }, { - bidId: 'bidId2', - params: {adzoneid: 1000}, - nativeParams: { - title: {required: true, len: 140} - }, - mediaTypes: { - banner: { - sizes: [[100, 100], [200, 300]] - }, - native: {}, - video: {} - } - }]; - let [first, second, third] = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp; + describe('userid idl_env should be passed to querystring', function () { + let bid = deepClone([bidBanner]); + let bidderRequests = {}; - assert.ok(first.banner); - assert.ok(first.video); - assert.equal(first.native, undefined); + bid[0].userId = {idl_env: 'idl_envsample'}; - assert.ok(second.video); - assert.equal(second.banner, undefined); - assert.equal(second.native, undefined); + it('should send pubcid if available', function () { + let request = spec.buildRequests(bid, bidderRequests); + let parsedRequestUrl = parseUrl(request.url); + let query = parsedRequestUrl.search; + expect(query.idl_env).to.equal('idl_envsample'); + }); + }); - assert.ok(third.native); - assert.ok(third.video); - assert.ok(third.banner); - }); - }); + describe('response handler', function () { + let BIDDER_REQUEST = { + bidder: 'adxcg', + params: { + adzoneid: '1' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [640, 360], + [1, 1] + ] + } + }, + bidId: '84ab500420319d', + bidderRequestId: '7101db09af0db2', + auctionId: '1d1a030790a475' + }; - describe('banner', function () { - it('should convert sizes to openrtb format', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: 1000}, - mediaTypes: { - banner: { - sizes: [[100, 100], [200, 300]] + let BANNER_RESPONSE = { + body: { + id: 'auctionid', + bidid: '84ab500420319d', + seatbid: [{ + bid: [ + { + impid: '84ab500420319d', + price: 0.45, + crid: '42', + adm: '', + w: 300, + h: 250, + adomain: ['adomain.com'], + cat: ['IAB1-4', 'IAB8-16', 'IAB25-5'], + ext: { + crType: 'banner', + advertiser_id: '777', + advertiser_name: 'advertiser', + agency_name: 'agency' } } - }]; - let {banner} = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0]; - assert.deepEqual(banner, { - format: [{w: 100, h: 100}, {w: 200, h: 300}] - }); - }); - }); + ] + }], + cur: 'USD' + }, + headers: {someheader: 'fakedata'} + }; - describe('video', function () { - it('should pass video mediatype config', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: 1000}, - mediaTypes: { - video: { - playerSize: [640, 480], - context: 'outstream', - mimes: ['video/mp4'] + let BANNER_RESPONSE_WITHDEALID = { + body: { + id: 'auctionid', + bidid: '84ab500420319d', + seatbid: [{ + bid: [ + { + impid: '84ab500420319d', + price: 0.45, + crid: '42', + dealid: '7722', + adm: '', + w: 300, + h: 250, + adomain: ['adomain.com'], + ext: { + crType: 'banner' } } - }]; - let {video} = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0]; - assert.deepEqual(video, { - playerSize: [640, 480], - context: 'outstream', - mimes: ['video/mp4'] - }); - }); - }); + ] + }], + cur: 'USD' + } + }; - describe('native', function () { - describe('assets', function () { - it('should set correct asset id', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: 1000}, - nativeParams: { - title: {required: true, len: 140}, - image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']}, - body: {len: 140} - } - }]; - let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request; - let assets = JSON.parse(nativeRequest).assets; - - assert.equal(assets[0].id, 0); - assert.equal(assets[1].id, 3); - assert.equal(assets[2].id, 4); - }); - it('should add required key if it is necessary', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: 1000}, - nativeParams: { - title: {required: true, len: 140}, - image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']}, - body: {len: 140}, - sponsoredBy: {required: true, len: 140} - } - }]; - - let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request; - let assets = JSON.parse(nativeRequest).assets; - - assert.equal(assets[0].required, 1); - assert.ok(!assets[1].required); - assert.ok(!assets[2].required); - assert.equal(assets[3].required, 1); - }); - - it('should map img and data assets', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: 1000}, - nativeParams: { - title: {required: true, len: 140}, - image: {required: true, sizes: [150, 50]}, - icon: {required: false, sizes: [50, 50]}, - body: {required: false, len: 140}, - sponsoredBy: {required: true}, - cta: {required: false}, - clickUrl: {required: false} - } - }]; - - let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request; - let assets = JSON.parse(nativeRequest).assets; - assert.ok(assets[0].title); - assert.equal(assets[0].title.len, 140); - assert.deepEqual(assets[1].img, {type: 3, w: 150, h: 50}); - assert.deepEqual(assets[2].img, {type: 1, w: 50, h: 50}); - assert.deepEqual(assets[3].data, {type: 2, len: 140}); - assert.deepEqual(assets[4].data, {type: 1}); - assert.deepEqual(assets[5].data, {type: 12}); - assert.ok(!assets[6]); - }); - - describe('icon/image sizing', function () { - it('should flatten sizes and utilise first pair', function () { - const validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: 1000}, - nativeParams: { - image: { - sizes: [[200, 300], [100, 200]] - }, - } - }]; - - let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request; - let assets = JSON.parse(nativeRequest).assets; - assert.ok(assets[0].img); - assert.equal(assets[0].img.w, 200); - assert.equal(assets[0].img.h, 300); - }); - }); - - it('should utilise aspect_ratios', function () { - const validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: 1000}, - nativeParams: { - image: { - aspect_ratios: [{ - min_width: 100, - ratio_height: 3, - ratio_width: 1 - }] - }, - icon: { - aspect_ratios: [{ - min_width: 10, - ratio_height: 5, - ratio_width: 2 - }] - } - } - }]; - - let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request; - let assets = JSON.parse(nativeRequest).assets; - assert.ok(assets[0].img); - assert.equal(assets[0].img.wmin, 100); - assert.equal(assets[0].img.hmin, 300); - - assert.ok(assets[1].img); - assert.equal(assets[1].img.wmin, 10); - assert.equal(assets[1].img.hmin, 25); - }); - - it('should not throw error if aspect_ratios config is not defined', function () { - const validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: 1000}, - nativeParams: { - image: { - aspect_ratios: [] - }, - icon: { - aspect_ratios: [] - } - } - }]; - - assert.doesNotThrow(() => spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}})); - }); - }); - - it('should expect any dimensions if min_width not passed', function () { - const validBidRequests = [{ - bidId: 'bidId', - params: {adzoneid: 1000}, - nativeParams: { - image: { - aspect_ratios: [{ - ratio_height: 3, - ratio_width: 1 - }] + let VIDEO_RESPONSE = { + body: { + id: 'auctionid', + bidid: '84ab500420319d', + seatbid: [{ + bid: [ + { + impid: '84ab500420319d', + price: 0.45, + crid: '42', + nurl: 'vastContentUrl', + adomain: ['adomain.com'], + w: 640, + h: 360, + ext: { + crType: 'video' } } - }]; - - let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request; - let assets = JSON.parse(nativeRequest).assets; - assert.ok(assets[0].img); - assert.equal(assets[0].img.wmin, 0); - assert.equal(assets[0].img.hmin, 0); - assert.ok(!assets[1]); - }); - }); - }); + ] + }], + cur: 'USD' + }, + headers: {someheader: 'fakedata'} + }; - function getRequestImps(validBidRequests) { - return JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp; + let NATIVE_RESPONSEob = { + assets: [ + { + id: 1, + required: 0, + title: { + text: 'titleContent' + } + }, + { + id: 2, + required: 0, + img: { + url: 'imageContent', + w: 600, + h: 600 + } + }, + { + id: 3, + required: 0, + data: { + label: 'DESC', + value: 'descriptionContent' + } + }, + { + id: 0, + required: 0, + data: { + label: 'SPONSORED', + value: 'sponsoredByContent' + } + }, + { + id: 5, + required: 0, + icon: { + url: 'iconContent', + w: 400, + h: 400 + } + } + ], + link: { + url: 'linkContent' + }, + imptrackers: ['impressionTracker1', 'impressionTracker2'] } - }); - - describe('interpretResponse', function () { - it('should return if no body in response', function () { - let serverResponse = {}; - let bidRequest = {}; - assert.ok(!spec.interpretResponse(serverResponse, bidRequest)); - }); - it('should return more than one bids', function () { - let serverResponse = { - body: { - seatbid: [{ - bid: [{ - impid: '1', - native: {ver: '1.1', link: {url: 'link'}, assets: [{id: 1, title: {text: 'Asset title text'}}]} - }] - }, { - bid: [{ - impid: '2', - native: {ver: '1.1', link: {url: 'link'}, assets: [{id: 1, data: {value: 'Asset title text'}}]} - }] - }] - } - }; - let bidRequest = { - data: {}, - bids: [ - { - bidId: 'bidId1', - params: {adzoneid: 1000}, - nativeParams: { - title: {required: true, len: 140}, - image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']}, - body: {len: 140} - } - }, - { - bidId: 'bidId2', - params: {adzoneid: 1000}, - nativeParams: { - title: {required: true, len: 140}, - image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']}, - body: {len: 140} + let NATIVE_RESPONSE = { + body: { + id: 'auctionid', + bidid: '84ab500420319d', + seatbid: [{ + bid: [ + { + impid: '84ab500420319d', + price: 0.45, + crid: '42', + w: 0, + h: 0, + adm: JSON.stringify(NATIVE_RESPONSEob), + adomain: ['adomain.com'], + ext: { + crType: 'native' + } } - } - ] - }; + ] + }], + cur: 'USD' + }, + headers: {someheader: 'fakedata'} + }; - bids = spec.interpretResponse(serverResponse, bidRequest); - assert.equal(spec.interpretResponse(serverResponse, bidRequest).length, 2); + it('handles regular responses', function () { + expect(BANNER_RESPONSE).to.exist; + expect(BANNER_RESPONSE.body).to.exist; + expect(BANNER_RESPONSE.body.id).to.exist; + expect(BANNER_RESPONSE.body.seatbid[0]).to.exist; + let result = spec.interpretResponse(BANNER_RESPONSE, BIDDER_REQUEST); + + expect(result).to.have.lengthOf(1); + + expect(result[0]).to.exist; + expect(result[0].width).to.equal(300); + expect(result[0].height).to.equal(250); + expect(result[0].creativeId).to.equal(42); + expect(result[0].cpm).to.be.within(0.45, 0.46); + expect(result[0].ad).to.equal(''); + expect(result[0].currency).to.equal('USD'); + expect(result[0].netRevenue).to.equal(true); + expect(result[0].ttl).to.equal(300); + expect(result[0].dealId).to.not.exist; + expect(result[0].meta.advertiserDomains[0]).to.equal('adomain.com'); + expect(result[0].meta.advertiserId).to.be.eql('777'); + expect(result[0].meta.advertiserName).to.be.eql('advertiser'); + expect(result[0].meta.agencyName).to.be.eql('agency'); + expect(result[0].meta.advertiserDomains).to.be.eql(['adomain.com']); + expect(result[0].meta.secondaryCatIds).to.be.eql(['IAB1-4', 'IAB8-16', 'IAB25-5']); }); - it('should set correct values to bid', function () { - let nativeExample1 = { - assets: [], - link: {url: 'link'}, - imptrackers: ['imptrackers url1', 'imptrackers url2'] - } + it('handles regular responses with dealid', function () { + let result = spec.interpretResponse(BANNER_RESPONSE_WITHDEALID); - let serverResponse = { - body: { - id: null, - bidid: null, - seatbid: [{ - bid: [ - { - impid: '1', - price: 93.1231, - crid: '12312312', - adm: JSON.stringify(nativeExample1), - dealid: 'deal-id', - adomain: ['demo.com'], - ext: { - crType: 'native', - advertiser_id: 'adv1', - advertiser_name: 'advname', - agency_name: 'agname', - mediaType: 'native' - } - } - ] - }], - cur: 'EUR' - } - }; - let bidRequest = { - data: {}, - bids: [ - { - bidId: 'bidId1', - params: {adzoneid: 1000}, - nativeParams: { - title: {required: true, len: 140}, - image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']}, - body: {len: 140} - } - } - ] - }; + expect(result).to.have.lengthOf(1); - const bids = spec.interpretResponse(serverResponse, bidRequest); - const bid = serverResponse.body.seatbid[0].bid[0]; - assert.deepEqual(bids[0].requestId, bidRequest.bids[0].bidId); - assert.deepEqual(bids[0].cpm, bid.price); - assert.deepEqual(bids[0].creativeId, bid.crid); - assert.deepEqual(bids[0].ttl, 300); - assert.deepEqual(bids[0].netRevenue, false); - assert.deepEqual(bids[0].currency, serverResponse.body.cur); - assert.deepEqual(bids[0].mediaType, 'native'); - assert.deepEqual(bids[0].meta.mediaType, 'native'); - assert.deepEqual(bids[0].meta.advertiserDomains, ['demo.com']); - - assert.deepEqual(bids[0].meta.advertiserName, 'advname'); - assert.deepEqual(bids[0].meta.agencyName, 'agname'); - - assert.deepEqual(bids[0].dealId, 'deal-id'); + expect(result[0].width).to.equal(300); + expect(result[0].height).to.equal(250); + expect(result[0].creativeId).to.equal(42); + // expect(result[0].cpm).to.equal(0.45); + expect(result[0].cpm).to.be.within(0.45, 0.46); + expect(result[0].ad).to.equal(''); + expect(result[0].currency).to.equal('USD'); + expect(result[0].netRevenue).to.equal(true); + expect(result[0].ttl).to.equal(300); }); - it('should return empty when there is no bids in response', function () { - const serverResponse = { - body: { - id: null, - bidid: null, - seatbid: [{bid: []}], - cur: 'EUR' - } - }; - let bidRequest = { - data: {}, - bids: [{bidId: 'bidId1'}] - }; - const result = spec.interpretResponse(serverResponse, bidRequest)[0]; - assert.ok(!result); + it('handles video responses', function () { + let result = spec.interpretResponse(VIDEO_RESPONSE); + expect(result).to.have.lengthOf(1); + + expect(result[0].width).to.equal(640); + expect(result[0].height).to.equal(360); + expect(result[0].mediaType).to.equal('video'); + expect(result[0].creativeId).to.equal(42); + expect(result[0].cpm).to.equal(0.45); + expect(result[0].vastUrl).to.equal('vastContentUrl'); + expect(result[0].currency).to.equal('USD'); + expect(result[0].netRevenue).to.equal(true); + expect(result[0].ttl).to.equal(300); }); - describe('banner', function () { - it('should set ad content on response', function () { - let serverResponse = { - body: { - seatbid: [{ - bid: [{impid: '1', adm: '', ext: {crType: 'banner'}}] - }] - } - }; - let bidRequest = { - data: {}, - bids: [ - { - bidId: 'bidId1', - params: {adzoneid: 1000} - } - ] - }; + it('handles native responses', function () { + let result = spec.interpretResponse(NATIVE_RESPONSE); - bids = spec.interpretResponse(serverResponse, bidRequest); - assert.equal(bids.length, 1); - assert.equal(bids[0].ad, ''); - assert.equal(bids[0].mediaType, 'banner'); - assert.equal(bids[0].meta.mediaType, 'banner'); - }); + expect(result[0].width).to.equal(0); + expect(result[0].height).to.equal(0); + + expect(result[0].creativeId).to.equal(42); + expect(result[0].cpm).to.equal(0.45); + expect(result[0].currency).to.equal('USD'); + expect(result[0].netRevenue).to.equal(true); + expect(result[0].ttl).to.equal(300); + + expect(result[0].mediaType).to.equal('native'); + + expect(result[0].native.clickUrl).to.equal('linkContent'); + expect(result[0].native.impressionTrackers).to.deep.equal([ + 'impressionTracker1', + 'impressionTracker2' + ]); + expect(result[0].native.title).to.equal('titleContent'); + + expect(result[0].native.image.url).to.equal('imageContent'); + expect(result[0].native.image.height).to.equal(600); + expect(result[0].native.image.width).to.equal(600); + + expect(result[0].native.icon.url).to.equal('iconContent'); + expect(result[0].native.icon.height).to.equal(400); + expect(result[0].native.icon.width).to.equal(400); + + expect(result[0].native.body).to.equal('descriptionContent'); + expect(result[0].native.sponsoredBy).to.equal('sponsoredByContent'); }); - describe('video', function () { - it('should set vastXml on response', function () { - let serverResponse = { - body: { - seatbid: [{ - bid: [{impid: '1', adm: '', ext: {crType: 'video'}}] - }] - } - }; - let bidRequest = { - data: {}, - bids: [ - { - bidId: 'bidId1', - params: {adzoneid: 1000} - } - ] - }; + it('handles nobid responses', function () { + let response = []; + let bidderRequest = BIDDER_REQUEST; - bids = spec.interpretResponse(serverResponse, bidRequest); - assert.equal(bids.length, 1); - assert.equal(bids[0].vastXml, ''); - assert.equal(bids[0].mediaType, 'video'); - assert.equal(bids[0].meta.mediaType, 'video'); - }); + let result = spec.interpretResponse(response, bidderRequest); + expect(result.length).to.equal(0); }); }); describe('getUserSyncs', function () { - const usersyncUrl = 'https://usersync-url.com'; - beforeEach(() => { - config.setConfig( - { - adxcg: { - usersyncUrl: usersyncUrl, - } - } - ) - }) - after(() => { - config.resetConfig() - }) - - it('should return user sync if pixel enabled with adxcg config', function () { - const ret = spec.getUserSyncs({pixelEnabled: true}) - expect(ret).to.deep.equal([{type: 'image', url: usersyncUrl}]) - }) - - it('should not return user sync if pixel disabled', function () { - const ret = spec.getUserSyncs({pixelEnabled: false}) - expect(ret).to.be.an('array').that.is.empty - }) - - it('should not return user sync if url is not set', function () { - config.resetConfig() - const ret = spec.getUserSyncs({pixelEnabled: true}) - expect(ret).to.be.an('array').that.is.empty - }) - - it('should pass GDPR consent', function() { - expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'foo'}, undefined)).to.deep.equal([{ - type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=foo` - }]); - expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: false, consentString: 'foo'}, undefined)).to.deep.equal([{ - type: 'image', url: `${usersyncUrl}?gdpr=0&gdpr_consent=foo` - }]); - expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: undefined}, undefined)).to.deep.equal([{ - type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=` - }]); - }); - - it('should pass US consent', function() { - expect(spec.getUserSyncs({ pixelEnabled: true }, {}, undefined, '1NYN')).to.deep.equal([{ - type: 'image', url: `${usersyncUrl}?us_privacy=1NYN` - }]); - }); + let syncoptionsIframe = { + iframeEnabled: 'true' + }; - it('should pass GDPR and US consent', function() { - expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'foo'}, '1NYN')).to.deep.equal([{ - type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=foo&us_privacy=1NYN` - }]); + it('should return iframe sync option', function () { + expect(spec.getUserSyncs(syncoptionsIframe)[0].type).to.equal('iframe'); + expect(spec.getUserSyncs(syncoptionsIframe)[0].url).to.equal( + 'https://cdn.adxcg.net/pb-sync.html' + ); }); }); - describe('onBidWon', function() { - beforeEach(function() { + describe('on bidWon', function () { + beforeEach(function () { sinon.stub(utils, 'triggerPixel'); }); - afterEach(function() { + afterEach(function () { utils.triggerPixel.restore(); }); - - it('Should trigger pixel if bid nurl', function() { + it('should replace burl for banner', function () { + const burl = 'burl=${' + 'AUCTION_PRICE}'; const bid = { - nurl: 'http://example.com/win/${AUCTION_PRICE}', - cpm: 2.1, - originalCpm: 1.1, - } + 'bidderCode': 'adxcg', + 'width': 0, + 'height': 0, + 'statusMessage': 'Bid available', + 'adId': '3d0b6ff1dda89', + 'requestId': '2a423489e058a1', + 'mediaType': 'banner', + 'source': 'client', + 'ad': burl, + 'cpm': 0.66, + 'creativeId': '353538_591471', + 'currency': 'USD', + 'dealId': '', + 'netRevenue': true, + 'ttl': 300, + // 'nurl': nurl, + 'burl': burl, + 'isBurl': true, + 'auctionId': 'a92bffce-14d2-4f8f-a78a-7b9b5e4d28fa', + 'responseTimestamp': 1556867386065, + 'requestTimestamp': 1556867385916, + 'bidder': 'adxcg', + 'adUnitCode': 'div-gpt-ad-1555415275793-0', + 'timeToRespond': 149, + 'pbLg': '0.50', + 'pbMg': '0.60', + 'pbHg': '0.66', + 'pbAg': '0.65', + 'pbDg': '0.66', + 'pbCg': '', + 'size': '0x0', + 'adserverTargeting': { + 'hb_bidder': 'mgid', + 'hb_adid': '3d0b6ff1dda89', + 'hb_pb': '0.66', + 'hb_size': '0x0', + 'hb_source': 'client', + 'hb_format': 'banner', + 'hb_banner_title': 'TITLE', + 'hb_banner_image': 'hb_banner_image:3d0b6ff1dda89', + 'hb_banner_icon': 'IconURL', + 'hb_banner_linkurl': 'hb_banner_linkurl:3d0b6ff1dda89' + }, + 'status': 'targetingSet', + 'params': [{'adzoneid': '20'}] + }; spec.onBidWon(bid); - expect(utils.triggerPixel.callCount).to.equal(1) - }) - }) + expect(bid.burl).to.deep.equal(burl); + }); + }); }); diff --git a/test/spec/modules/adyoulikeBidAdapter_spec.js b/test/spec/modules/adyoulikeBidAdapter_spec.js index 3e68a10f56e..befc95e5f24 100644 --- a/test/spec/modules/adyoulikeBidAdapter_spec.js +++ b/test/spec/modules/adyoulikeBidAdapter_spec.js @@ -95,60 +95,6 @@ describe('Adyoulike Adapter', function () { } ]; - const bidRequestWithMultipleMediatype = [ - { - 'bidId': 'bid_id_0', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-0', - 'params': { - 'placement': 'placement_0' - }, - 'sizes': '300x250', - 'mediaTypes': { - 'banner': { - 'sizes': ['640x480'] - }, - 'video': { - 'playerSize': [640, 480], - 'context': 'outstream' - }, - 'native': { - 'image': { - 'required': true, - }, - 'title': { - 'required': true, - 'len': 80 - }, - 'cta': { - 'required': false - }, - } - }, - 'transactionId': 'bid_id_0_transaction_id' - } - ]; - - const bidRequestWithVideo = [ - { - 'bidId': 'bid_id_0', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-0', - 'params': { - 'placement': 'placement_0' - }, - 'sizes': '300x250', - 'mediaTypes': - { - 'video': { - 'context': 'instream', - 'playerSize': [[ 640, 480 ]] - } - }, - 'transactionId': 'bid_id_0_transaction_id' - } - ]; - const bidRequestWithNativeImageType = [ { 'bidId': 'bid_id_0', @@ -367,7 +313,7 @@ describe('Adyoulike Adapter', function () { 'secondaryCatIds': ['IAB-222', 'IAB-333'], 'mediaType': 'banner' }; - const admSample = "\u003cscript id=\"ayl-prebid-a11a121205932e75e622af275681965d\"\u003e\n(function(){\n\twindow.isPrebid = true\n\tvar prebidResults = /*PREBID*/{\"OnEvents\": {\"CLICK\": [{\"Kind\": \"PIXEL_URL\",\"Url\": \"https://testPixelCLICK.com/fake\"}],\"IMPRESSION\": [{\"Kind\": \"PIXEL_URL\",\"Url\": \"https://testPixelIMP.com/fake\"}, {\"Kind\": \"JAVASCRIPT_URL\",\"Url\": \"https://testJsIMP.com/fake.js\"}]},\"Disabled\": false,\"Attempt\": \"a11a121205932e75e622af275681965d\",\"ApiPrefix\": \"https://fo-api.omnitagjs.com/fo-api\",\"TrackingPrefix\": \"https://tracking.omnitagjs.com/tracking\",\"DynamicPrefix\": \"https://tag-dyn.omnitagjs.com/fo-dyn\",\"StaticPrefix\": \"https://fo-static.omnitagjs.com/fo-static\",\"BlobPrefix\": \"https://fo-api.omnitagjs.com/fo-api/blobs\",\"SspPrefix\": \"https://fo-ssp.omnitagjs.com/fo-ssp\",\"VisitorPrefix\": \"https://visitor.omnitagjs.com/visitor\",\"Trusted\": true,\"Placement\": \"e622af275681965d3095808561a1e510\",\"PlacementAccess\": \"ALL\",\"Site\": \"6e2df7a92203c3c7a25561ed63f25a27\",\"Lang\": \"EN\",\"SiteLogo\": null,\"HasSponsorImage\": true,\"ResizeIframe\": true,\"IntegrationConfig\": {\"Kind\": \"WIDGET\",\"Widget\": {\"ExtraStyleSheet\": \"\",\"Placeholders\": {\"Body\": {\"Color\": {\"R\": 77,\"G\": 21,\"B\": 82,\"A\": 100},\"BackgroundColor\": {\"R\": 255,\"G\": 255,\"B\": 255,\"A\": 100},\"FontFamily\": \"Lato\",\"Width\": \"100%\",\"Align\": \"\",\"BoxShadow\": true},\"CallToAction\": {\"Color\": {\"R\": 26,\"G\": 157,\"B\": 212,\"A\": 100}},\"Description\": {\"Length\": 130},\"Image\": {\"Width\": 600,\"Height\": 600,\"Lowres\": false,\"Raw\": false},\"Size\": {\"Height\": \"250px\",\"Width\": \"300px\"},\"Title\": {\"Color\": {\"R\": 219,\"G\": 181,\"B\": 255,\"A\": 100}}},\"Selector\": {\"Kind\": \"CSS\",\"Css\": \"#ayl-prebid-a11a121205932e75e622af275681965d\"},\"Insertion\": \"AFTER\",\"ClickFormat\": true,\"Creative20\": true,\"WidgetKind\": \"CREATIVE_TEMPLATE_4\"}},\"Legal\": \"Sponsored\",\"ForcedCampaign\": \"f1c80d4bb5643c222ae8de75e9b2f991\",\"ForcedTrack\": \"\",\"ForcedCreative\": \"\",\"ForcedSource\": \"\",\"DisplayMode\": \"DEFAULT\",\"Campaign\": \"f1c80d4bb5643c222ae8de75e9b2f991\",\"CampaignAccess\": \"ALL\",\"CampaignKind\": \"AD_TRAFFIC\",\"DataSource\": \"LOCAL\",\"DataSourceUrl\": \"\",\"DataSourceOnEventsIsolated\": false,\"DataSourceWithoutCookie\": false,\"Content\": {\"Preview\": {\"Thumbnail\": {\"Image\": {\"Kind\": \"EXTERNAL\",\"Data\": {\"External\": {\"Url\": \"https://tag-dyn.omnitagjs.com/fo-dyn/native/preview/image?key=fd4362d35bb174d6f1c80d4bb5643c22\\u0026kind=INTERNAL\\u0026ztop=0.000000\\u0026zleft=0.000000\\u0026zwidth=0.333333\\u0026zheight=1.000000\\u0026width=[width]\\u0026height=[height]\"}},\"ZoneTop\": 0,\"ZoneLeft\": 0,\"ZoneWidth\": 1,\"ZoneHeight\": 1,\"Smart\": false,\"NoTransform\": false,\"Quality\": \"NORMAL\"}},\"Text\": {\"CALLTOACTION\": \"Click here to learn more\",\"DESCRIPTION\": \"Considérant l'extrémité conjoncturelle, il serait bon d'anticiper toutes les voies de bon sens.\",\"SPONSOR\": \"Tested by\",\"TITLE\": \"Adserver Traffic Redirect Internal\"},\"Sponsor\": {\"Name\": \"QA Team\",\"Logo\": {\"Resource\": {\"Kind\": \"EXTERNAL\",\"Data\": {\"External\": {\"Url\": \"https://fo-static.omnitagjs.com/fo-static/native/images/info-ayl.svg\"}},\"ZoneTop\": 0,\"ZoneLeft\": 0,\"ZoneWidth\": 1,\"ZoneHeight\": 1,\"Smart\": false,\"NoTransform\": false,\"Quality\": \"NORMAL\"}}},\"Credit\": {\"Logo\": {\"Resource\": {\"Kind\": \"EXTERNAL\",\"Data\": {\"External\": {\"Url\": \"https://fo-static.omnitagjs.com/fo-static/native/images/info-ayl.png\"}},\"ZoneTop\": 0,\"ZoneLeft\": 0,\"ZoneWidth\": 1,\"ZoneHeight\": 1,\"Smart\": false,\"NoTransform\": false,\"Quality\": \"NORMAL\"}},\"Url\": \"https://blobs.omnitagjs.com/adchoice/\"}},\"Landing\": {\"Url\": \"https://www.w3.org/People/mimasa/test/xhtml/entities/entities-11.xhtml#lat1\",\"LegacyTracking\": false},\"ViewButtons\": {\"Close\": {\"Skip\": 6000}},\"InternalContentFields\": {\"AnimatedImage\": false}},\"AdDomain\": \"adyoulike.com\",\"Opener\": \"REDIRECT\",\"PerformUITriggers\": [\"CLICK\"],\"RedirectionTarget\": \"TAB\"}/*PREBID*/;\n\tvar insertAds = function insertAds() {\insertAds();\n\t}\n})();\n\u003c/script\u003e"; + const admSample = "\u003cscript id=\"ayl-prebid-a11a121205932e75e622af275681965d\"\u003e\n(function(){\n\twindow.isPrebid = true\n\tvar prebidResults = /*PREBID*/{\"OnEvents\":{\"CLICK\":[{\"Kind\":\"PIXEL_URL\",\"Url\":\"https://testPixelCLICK.com/fake\"}],\"IMPRESSION\":[{\"Kind\":\"PIXEL_URL\",\"Url\":\"https://testPixelIMP.com/fake\"},{\"Kind\":\"JAVASCRIPT_URL\",\"Url\":\"https://testJsIMP.com/fake.js\"}]},\"Disabled\":false,\"Attempt\":\"a11a121205932e75e622af275681965d\",\"ApiPrefix\":\"https://fo-api.omnitagjs.com/fo-api\",\"TrackingPrefix\":\"https://tracking.omnitagjs.com/tracking\",\"DynamicPrefix\":\"https://tag-dyn.omnitagjs.com/fo-dyn\",\"StaticPrefix\":\"https://fo-static.omnitagjs.com/fo-static\",\"BlobPrefix\":\"https://fo-api.omnitagjs.com/fo-api/blobs\",\"SspPrefix\":\"https://fo-ssp.omnitagjs.com/fo-ssp\",\"VisitorPrefix\":\"https://visitor.omnitagjs.com/visitor\",\"Trusted\":true,\"Placement\":\"e622af275681965d3095808561a1e510\",\"PlacementAccess\":\"ALL\",\"Site\":\"6e2df7a92203c3c7a25561ed63f25a27\",\"Lang\":\"EN\",\"SiteLogo\":null,\"HasSponsorImage\":false,\"ResizeIframe\":true,\"IntegrationConfig\":{\"Kind\":\"WIDGET\",\"Widget\":{\"ExtraStyleSheet\":\"\",\"Placeholders\":{\"Body\":{\"Color\":{\"R\":77,\"G\":21,\"B\":82,\"A\":100},\"BackgroundColor\":{\"R\":255,\"G\":255,\"B\":255,\"A\":100},\"FontFamily\":\"Lato\",\"Width\":\"100%\",\"Align\":\"\",\"BoxShadow\":true},\"CallToAction\":{\"Color\":{\"R\":26,\"G\":157,\"B\":212,\"A\":100}},\"Description\":{\"Length\":130},\"Image\":{\"Width\":600,\"Height\":600,\"Lowres\":false,\"Raw\":false},\"Size\":{\"Height\":\"250px\",\"Width\":\"300px\"},\"Sponsor\":{\"Color\":{\"R\":35,\"G\":35,\"B\":35,\"A\":100},\"Label\":true,\"WithoutLogo\":false},\"Title\":{\"Color\":{\"R\":219,\"G\":181,\"B\":255,\"A\":100}}},\"Selector\":{\"Kind\":\"CSS\",\"Css\":\"#ayl-prebid-a11a121205932e75e622af275681965d\"},\"Insertion\":\"AFTER\",\"ClickFormat\":true,\"Creative20\":true,\"WidgetKind\":\"CREATIVE_TEMPLATE_4\"}},\"Legal\":\"Sponsored\",\"ForcedCampaign\":\"f1c80d4bb5643c222ae8de75e9b2f991\",\"ForcedTrack\":\"\",\"ForcedCreative\":\"\",\"ForcedSource\":\"\",\"DisplayMode\":\"DEFAULT\",\"Campaign\":\"f1c80d4bb5643c222ae8de75e9b2f991\",\"CampaignAccess\":\"ALL\",\"CampaignKind\":\"AD_TRAFFIC\",\"DataSource\":\"LOCAL\",\"DataSourceUrl\":\"\",\"DataSourceOnEventsIsolated\":false,\"DataSourceWithoutCookie\":false,\"Content\":{\"Preview\":{\"Thumbnail\":{\"Image\":{\"Kind\":\"EXTERNAL\",\"Data\":{\"External\":{\"Url\":\"https://tag-dyn.omnitagjs.com/fo-dyn/native/preview/image?key=fd4362d35bb174d6f1c80d4bb5643c22\\u0026kind=INTERNAL\\u0026ztop=0.000000\\u0026zleft=0.000000\\u0026zwidth=0.333333\\u0026zheight=1.000000\\u0026width=[width]\\u0026height=[height]\"}},\"ZoneTop\":0,\"ZoneLeft\":0,\"ZoneWidth\":1,\"ZoneHeight\":1,\"Smart\":false,\"NoTransform\":false,\"Quality\":\"NORMAL\"}},\"Text\":{\"CALLTOACTION\":\"Click here to learn more\",\"DESCRIPTION\":\"Considérant l'extrémité conjoncturelle, il serait bon d'anticiper toutes les voies de bon sens.\",\"SPONSOR\":\"Tested by\",\"TITLE\":\"Adserver Traffic Redirect Internal\"},\"Sponsor\":{\"Name\":\"QA Team\"},\"Credit\":{\"Logo\":{\"Resource\":{\"Kind\":\"EXTERNAL\",\"Data\":{\"External\":{\"Url\":\"https://fo-static.omnitagjs.com/fo-static/native/images/info-ayl.png\"}},\"ZoneTop\":0,\"ZoneLeft\":0,\"ZoneWidth\":1,\"ZoneHeight\":1,\"Smart\":false,\"NoTransform\":false,\"Quality\":\"NORMAL\"}},\"Url\":\"https://blobs.omnitagjs.com/adchoice/\"}},\"Landing\":{\"Url\":\"https://www.w3.org/People/mimasa/test/xhtml/entities/entities-11.xhtml#lat1\",\"LegacyTracking\":false},\"ViewButtons\":{\"Close\":{\"Skip\":6000}},\"InternalContentFields\":{\"AnimatedImage\":false}},\"AdDomain\":\"adyoulike.com\",\"Opener\":\"REDIRECT\",\"PerformUITriggers\":[\"CLICK\"],\"RedirectionTarget\":\"TAB\"}/*PREBID*/;\n\tvar insertAds = function insertAds() {\insertAds();\n\t}\n})();\n\u003c/script\u003e"; const responseWithSinglePlacement = [ { 'BidID': 'bid_id_0', @@ -391,11 +337,6 @@ describe('Adyoulike Adapter', function () { 'url': 'https://blobs.omnitagjs.com/blobs/f1/f1c80d4bb5643c22/fd4362d35bb174d6f1c80d4bb5643c22', 'width': 300 }, - 'icon': { - 'height': 50, - 'url': 'https://fo-static.omnitagjs.com/fo-static/native/images/info-ayl.svg', - 'width': 50, - }, 'privacyIcon': 'https://fo-static.omnitagjs.com/fo-static/native/images/info-ayl.png', 'privacyLink': 'https://blobs.omnitagjs.com/adchoice/', 'sponsoredBy': 'QA Team', @@ -436,11 +377,6 @@ describe('Adyoulike Adapter', function () { url: 'https://blobs.omnitagjs.com/blobs/f1/f1c80d4bb5643c22/fd4362d35bb174d6f1c80d4bb5643c22', width: 300, }, - icon: { - height: 50, - url: 'https://fo-static.omnitagjs.com/fo-static/native/images/info-ayl.svg', - width: 50, - }, impressionTrackers: [ 'https://testPixelIMP.com/fake', 'https://tracking.omnitagjs.com/tracking/pixel?event_kind=IMPRESSION&attempt=a11a121205932e75e622af275681965d&campaign=f1c80d4bb5643c222ae8de75e9b2f991', @@ -462,15 +398,13 @@ describe('Adyoulike Adapter', function () { 'Placement': 'placement_0', 'Vast': 'PFZBU1Q+RW1wdHkgc2FtcGxlPC92YXN0Pg==', 'Price': 0.5, - 'Height': 300, - 'Width': 530 + 'Height': 600, }]; const videoResult = [{ cpm: 0.5, creativeId: undefined, currency: 'USD', - height: 300, netRevenue: true, requestId: 'bid_id_0', ttl: 3600, @@ -478,8 +412,7 @@ describe('Adyoulike Adapter', function () { meta: { advertiserDomains: [] }, - vastXml: 'Empty sample', - width: 530 + vastXml: 'Empty sample' }]; const responseWithMultiplePlacements = [ @@ -609,11 +542,6 @@ describe('Adyoulike Adapter', function () { expect(payload.Bids['bid_id_0'].Native).deep.equal(sentNativeImageType); }); - it('Should target video enpoint for video mediatype', function() { - const request = spec.buildRequests(bidRequestWithVideo, bidderRequest); - expect(request.url).to.contain(getEndpoint()); - }); - it('should add gdpr/usp consent information to the request', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; let uspConsentData = '1YCC'; @@ -662,32 +590,6 @@ describe('Adyoulike Adapter', function () { expect(payload.gdprConsent.consentRequired).to.be.null; }); - it('should add userid eids information to the request', function () { - let bidderRequest = { - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000, - 'userId': { - pubcid: '01EAJWWNEPN3CYMM5N8M5VXY22', - unsuported: '666' - } - }; - - bidderRequest.bids = bidRequestWithSinglePlacement; - - const request = spec.buildRequests(bidRequestWithSinglePlacement, bidderRequest); - const payload = JSON.parse(request.data); - - expect(payload.userId).to.exist; - expect(payload.userId).to.deep.equal([{ - 'source': 'pubcid.org', - 'uids': [{ - 'atype': 1, - 'id': '01EAJWWNEPN3CYMM5N8M5VXY22' - }] - }]); - }); - it('sends bid request to endpoint with single placement', function () { const request = spec.buildRequests(bidRequestWithSinglePlacement, bidderRequest); const payload = JSON.parse(request.data); @@ -719,21 +621,6 @@ describe('Adyoulike Adapter', function () { expect(payload.Bids['bid_id_0'].TransactionID).to.be.equal('bid_id_0_transaction_id'); }); - it('sends bid request to endpoint with single placement multiple mediatype', function () { - canonicalQuery.restore(); - const request = spec.buildRequests(bidRequestWithMultipleMediatype, bidderRequest); - const payload = JSON.parse(request.data); - - expect(request.url).to.contain(getEndpoint()); - expect(request.method).to.equal('POST'); - - expect(request.url).to.not.contains('CanonicalUrl=' + encodeURIComponent(canonicalUrl)); - expect(payload.Version).to.equal('1.0'); - expect(payload.Bids['bid_id_0'].PlacementID).to.be.equal('placement_0'); - expect(payload.PageRefreshed).to.equal(false); - expect(payload.Bids['bid_id_0'].TransactionID).to.be.equal('bid_id_0_transaction_id'); - }); - it('sends bid request to endpoint with multiple placements', function () { const request = spec.buildRequests(bidRequestMultiPlacements, bidderRequest); const payload = JSON.parse(request.data); @@ -843,9 +730,5 @@ describe('Adyoulike Adapter', function () { expect(result.length).to.equal(1); expect(result).to.deep.equal(videoResult); }); - - it('should expose gvlid', function() { - expect(spec.gvlid).to.equal(259) - }) }); }); diff --git a/test/spec/modules/afpBidAdapter_spec.js b/test/spec/modules/afpBidAdapter_spec.js deleted file mode 100644 index 5b658a66351..00000000000 --- a/test/spec/modules/afpBidAdapter_spec.js +++ /dev/null @@ -1,306 +0,0 @@ -import {includes} from 'src/polyfill.js' -import cloneDeep from 'lodash/cloneDeep' -import unset from 'lodash/unset' -import { expect } from 'chai' -import { BANNER, VIDEO } from '../../../src/mediaTypes.js' -import { - spec, - IN_IMAGE_BANNER_TYPE, - IN_IMAGE_MAX_BANNER_TYPE, - IN_CONTENT_BANNER_TYPE, - IN_CONTENT_VIDEO_TYPE, - OUT_CONTENT_VIDEO_TYPE, - IN_CONTENT_STORY_TYPE, - ACTION_SCROLLER_TYPE, - ACTION_SCROLLER_LIGHT_TYPE, - JUST_BANNER_TYPE, - BIDDER_CODE, - SSP_ENDPOINT, - REQUEST_METHOD, - TEST_PAGE_URL, - IS_DEV, mediaTypeByPlaceType -} from 'modules/afpBidAdapter.js' - -const placeId = '613221112871613d1517d181' -const bidId = '2a67c5577ff6a5' -const transactionId = '7e8515a2-2ed9-4733-b976-6c2596a03287' -const imageUrl = 'https://rtbinsight.ru/content/images/size/w1000/2021/05/ximage-30.png.pagespeed.ic.IfuX4zAEPP.png' -const placeContainer = '#container' -const imageWidth = 600 -const imageHeight = 400 -const pageUrl = IS_DEV ? TEST_PAGE_URL : 'referer' -const sizes = [[imageWidth, imageHeight]] -const bidderRequest = { - refererInfo: { referer: pageUrl }, -} -const mediaTypeBanner = { [BANNER]: {sizes: [[imageWidth, imageHeight]]} } -const mediaTypeVideo = { [VIDEO]: {playerSize: [[imageWidth, imageHeight]]} } -const commonParams = { - placeId, - placeContainer, -} -const commonParamsForInImage = Object.assign({}, commonParams, { - imageUrl, - imageWidth, - imageHeight, -}) -const configByPlaceType = { - get [IN_IMAGE_BANNER_TYPE]() { - return cloneDeep({ - mediaTypes: mediaTypeBanner, - params: Object.assign({}, commonParamsForInImage, { - placeType: IN_IMAGE_BANNER_TYPE - }), - }) - }, - get [IN_IMAGE_MAX_BANNER_TYPE]() { - return cloneDeep({ - mediaTypes: mediaTypeBanner, - params: Object.assign({}, commonParamsForInImage, { - placeType: IN_IMAGE_MAX_BANNER_TYPE - }), - }) - }, - get [IN_CONTENT_BANNER_TYPE]() { - return cloneDeep({ - mediaTypes: mediaTypeBanner, - params: Object.assign({}, commonParams, { - placeType: IN_CONTENT_BANNER_TYPE - }), - }) - }, - get [IN_CONTENT_VIDEO_TYPE]() { - return cloneDeep({ - mediaTypes: mediaTypeVideo, - params: Object.assign({}, commonParams, { - placeType: IN_CONTENT_VIDEO_TYPE - }), - }) - }, - get [OUT_CONTENT_VIDEO_TYPE]() { - return cloneDeep({ - mediaTypes: mediaTypeVideo, - params: Object.assign({}, commonParams, { - placeType: OUT_CONTENT_VIDEO_TYPE - }), - }) - }, - get [IN_CONTENT_STORY_TYPE]() { - return cloneDeep({ - mediaTypes: mediaTypeBanner, - params: Object.assign({}, commonParams, { - placeType: IN_CONTENT_STORY_TYPE - }), - }) - }, - get [ACTION_SCROLLER_TYPE]() { - return cloneDeep({ - mediaTypes: mediaTypeBanner, - params: Object.assign({}, commonParams, { - placeType: ACTION_SCROLLER_TYPE - }), - }) - }, - get [ACTION_SCROLLER_LIGHT_TYPE]() { - return cloneDeep({ - mediaTypes: mediaTypeBanner, - params: Object.assign({}, commonParams, { - placeType: ACTION_SCROLLER_LIGHT_TYPE - }), - }) - }, - get [JUST_BANNER_TYPE]() { - return cloneDeep({ - mediaTypes: mediaTypeBanner, - params: Object.assign({}, commonParams, { - placeType: JUST_BANNER_TYPE - }), - }) - }, -} -const getTransformedConfig = ({mediaTypes, params}) => { - return { - params: params, - sizes, - bidId, - bidder: BIDDER_CODE, - mediaTypes: mediaTypes, - transactionId, - } -} -const validBidRequests = Object.keys(configByPlaceType).map(key => getTransformedConfig(configByPlaceType[key])) - -describe('AFP Adapter', function() { - describe('isBidRequestValid method', function() { - describe('returns true', function() { - describe('when config has all mandatory params', () => { - Object.keys(configByPlaceType).forEach(placeType => { - it(`and ${placeType} config has the correct value`, function() { - const isBidRequestValid = spec.isBidRequestValid(configByPlaceType[placeType]) - expect(isBidRequestValid).to.equal(true) - }) - }) - }) - }) - describe('returns false', function() { - const checkMissingParams = (placesTypes, missingParams) => - placesTypes.forEach(placeType => - missingParams.forEach(missingParam => { - const config = configByPlaceType[placeType] - it(`${placeType} does not have the ${missingParam}.`, function() { - unset(config, missingParam) - const isBidRequestValid = spec.isBidRequestValid(config) - expect(isBidRequestValid).to.equal(false) - }) - }) - ) - - describe('when params are not correct', function() { - checkMissingParams(Object.keys(configByPlaceType), ['params.placeId', 'params.placeType']) - checkMissingParams([IN_IMAGE_BANNER_TYPE, IN_IMAGE_MAX_BANNER_TYPE], - ['params.imageUrl', 'params.imageWidth', 'params.imageHeight']) - - it('does not have a the correct placeType.', function() { - const config = configByPlaceType[IN_IMAGE_BANNER_TYPE] - config.params.placeType = 'something' - const isBidRequestValid = spec.isBidRequestValid(config) - expect(isBidRequestValid).to.equal(false) - }) - }) - describe('when video mediaType object is not correct.', function() { - checkMissingParams([IN_CONTENT_VIDEO_TYPE, OUT_CONTENT_VIDEO_TYPE], - [`mediaTypes.${VIDEO}.playerSize`, `mediaTypes.${VIDEO}`]) - checkMissingParams([ - IN_IMAGE_BANNER_TYPE, - IN_IMAGE_MAX_BANNER_TYPE, - IN_CONTENT_BANNER_TYPE, - IN_CONTENT_STORY_TYPE, - ACTION_SCROLLER_TYPE, - ACTION_SCROLLER_LIGHT_TYPE, - JUST_BANNER_TYPE - ], [`mediaTypes.${BANNER}.sizes`, `mediaTypes.${BANNER}`]) - }) - }) - }) - - describe('buildRequests method', function() { - const request = spec.buildRequests(validBidRequests, bidderRequest) - - it('Url should be correct', function() { - expect(request.url).to.equal(SSP_ENDPOINT) - }) - - it('Method should be correct', function() { - expect(request.method).to.equal(REQUEST_METHOD) - }) - - describe('Common data request should be correct', function() { - it('pageUrl should be correct', function() { - expect(request.data.pageUrl).to.equal(pageUrl) - }) - it('bidRequests should be array', function() { - expect(Array.isArray(request.data.bidRequests)).to.equal(true) - }) - - request.data.bidRequests.forEach((bid, index) => { - describe(`bid with ${validBidRequests[index].params.placeType} should be correct`, function() { - it('bidId should be correct', function() { - expect(bid.bidId).to.equal(bidId) - }) - it('placeId should be correct', function() { - expect(bid.placeId).to.equal(placeId) - }) - it('transactionId should be correct', function() { - expect(bid.transactionId).to.equal(transactionId) - }) - it('sizes should be correct', function() { - expect(bid.sizes).to.equal(sizes) - }) - - if (includes([IN_IMAGE_BANNER_TYPE, IN_IMAGE_MAX_BANNER_TYPE], validBidRequests[index].params.placeType)) { - it('imageUrl should be correct', function() { - expect(bid.imageUrl).to.equal(imageUrl) - }) - it('imageWidth should be correct', function() { - expect(bid.imageWidth).to.equal(Math.floor(imageWidth)) - }) - it('imageHeight should be correct', function() { - expect(bid.imageHeight).to.equal(Math.floor(imageHeight)) - }) - } - }) - }) - }) - }) - - describe('interpretResponse method', function() { - it('should return a void array, when the server response are not correct.', function() { - const request = { data: JSON.stringify({}) } - const serverResponse = { - body: {} - } - const bids = spec.interpretResponse(serverResponse, request) - expect(Array.isArray(bids)).to.equal(true) - expect(bids.length).to.equal(0) - }) - it('should return a void array, when the server response have not got bids.', function() { - const request = { data: JSON.stringify({}) } - const serverResponse = { body: { bids: [] } } - const bids = spec.interpretResponse(serverResponse, request) - expect(Array.isArray(bids)).to.equal(true) - expect(bids.length).to.equal(0) - }) - describe('when the server response return a bids', function() { - Object.keys(configByPlaceType).forEach(placeType => { - it(`should return a bid with ${placeType} placeType`, function() { - const cpm = 10 - const currency = 'RUB' - const creativeId = '123' - const netRevenue = true - const width = sizes[0][0] - const height = sizes[0][1] - const adSettings = { - content: 'html' - } - const placeSettings = { - placeType, - } - const request = spec.buildRequests([validBidRequests[0]], bidderRequest) - const serverResponse = { - body: { - bids: [ - { - bidId, - cpm, - currency, - creativeId, - netRevenue, - width, - height, - adSettings, - placeSettings, - } - ] - } - } - const bids = spec.interpretResponse(serverResponse, request) - expect(bids.length).to.equal(1) - expect(bids[0].requestId).to.equal(bidId) - expect(bids[0].meta.mediaType).to.equal(mediaTypeByPlaceType[placeSettings.placeType]) - expect(bids[0].cpm).to.equal(cpm) - expect(bids[0].width).to.equal(width) - expect(bids[0].height).to.equal(height) - expect(bids[0].currency).to.equal(currency) - expect(bids[0].netRevenue).to.equal(netRevenue) - - if (mediaTypeByPlaceType[placeSettings.placeType] === BANNER) { - expect(typeof bids[0].ad).to.equal('string') - } else if (mediaTypeByPlaceType[placeSettings.placeType] === VIDEO) { - expect(typeof bids[0].vastXml).to.equal('string') - expect(typeof bids[0].renderer).to.equal('object') - } - }) - }) - }) - }) -}) diff --git a/test/spec/modules/ajaBidAdapter_spec.js b/test/spec/modules/ajaBidAdapter_spec.js index 9bb77520212..ccc2ab7de99 100644 --- a/test/spec/modules/ajaBidAdapter_spec.js +++ b/test/spec/modules/ajaBidAdapter_spec.js @@ -34,21 +34,21 @@ describe('AjaAdapter', function () { }); describe('buildRequests', function () { - const bidRequests = [ + let bidRequests = [ { - bidder: 'aja', - params: { - asi: '123456' + 'bidder': 'aja', + 'params': { + 'asi': '123456' }, - adUnitCode: 'adunit', - sizes: [[300, 250]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', + 'adUnitCode': 'adunit', + 'sizes': [[300, 250]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', } ]; - const bidderRequest = { + let bidderRequest = { refererInfo: { referer: 'https://hoge.com' } @@ -62,44 +62,6 @@ describe('AjaAdapter', function () { }); }); - describe('buildRequests with UserModule', function () { - const bidRequests = [ - { - bidder: 'aja', - params: { - asi: '123456' - }, - adUnitCode: 'adunit', - sizes: [[300, 250]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - userIdAsEids: [ - { - source: 'pubcid.org', - uids: [{ - id: 'some-random-id-value', - atype: 1 - }] - } - ] - } - ]; - - const bidderRequest = { - refererInfo: { - referer: 'https://hoge.com' - } - }; - - it('sends bid request to ENDPOINT via GET', function () { - const requests = spec.buildRequests(bidRequests, bidderRequest); - expect(requests[0].url).to.equal(ENDPOINT); - expect(requests[0].method).to.equal('GET'); - expect(requests[0].data).to.equal('asi=123456&skt=5&prebid_id=30b31c1838de1e&prebid_ver=$prebid.version$&page_url=https%3A%2F%2Fhoge.com&eids=%7B%22eids%22%3A%5B%7B%22source%22%3A%22pubcid.org%22%2C%22uids%22%3A%5B%7B%22id%22%3A%22some-random-id-value%22%2C%22atype%22%3A1%7D%5D%7D%5D%7D&'); - }); - }); - describe('interpretResponse', function () { it('should get correct banner bid response', function () { let response = { diff --git a/test/spec/modules/akamaiDapRtdProvider_spec.js b/test/spec/modules/akamaiDapRtdProvider_spec.js deleted file mode 100644 index b350c2bb529..00000000000 --- a/test/spec/modules/akamaiDapRtdProvider_spec.js +++ /dev/null @@ -1,246 +0,0 @@ -import {config} from 'src/config.js'; -import {SEGMENTS_STORAGE_KEY, TOKEN_STORAGE_KEY, dapUtils, addRealTimeData, getRealTimeData, akamaiDapRtdSubmodule, storage} from 'modules/akamaiDapRtdProvider.js'; -import {server} from 'test/mocks/xhr.js'; -import logMessage from 'src/utils.js' -const responseHeader = {'Content-Type': 'application/json'}; - -describe('akamaiDapRtdProvider', function() { - let getDataFromLocalStorageStub; - let getDapTokenStub; - - const testReqBidsConfigObj = { - adUnits: [ - { - bids: ['bid1', 'bid2'] - } - ] - }; - - const onDone = function() { return true }; - - const onSuccess = function() { return ('request', 200, 'success') }; - - const cmoduleConfig = { - 'name': 'dap', - 'waitForIt': true, - 'params': { - 'apiHostname': 'prebid.dap.akadns.net', - 'apiVersion': 'x1', - 'domain': 'prebid.org', - 'identityType': 'dap-signature:1.0.0', - 'segtax': 503, - 'tokenTtl': 5 - } - } - - const sampleConfig = { - 'api_hostname': 'prebid.dap.akadns.net', - 'api_version': 'x1', - 'domain': 'prebid.org', - 'segtax': 503 - } - const sampleIdentity = { - type: 'dap-signature:1.0.0' - }; - - beforeEach(function() { - config.resetConfig(); - getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage') - }); - - afterEach(function () { - getDataFromLocalStorageStub.restore(); - }); - - describe('akamaiDapRtdSubmodule', function() { - it('successfully instantiates', function () { - expect(akamaiDapRtdSubmodule.init()).to.equal(true); - }); - }); - - describe('Get Real-Time Data', function() { - it('gets rtd from local storage cache', function() { - const rtdConfig = { - params: { - segmentCache: true - } - }; - - const bidConfig = {}; - - const rtdUserObj1 = { - name: 'www.dataprovider3.com', - ext: { - taxonomyname: 'iab_audience_taxonomy' - }, - segment: [ - { - id: '1918' - }, - { - id: '1939' - } - ] - }; - - const cachedRtd = { - rtd: { - ortb2: { - user: { - data: [rtdUserObj1] - } - } - } - }; - - getDataFromLocalStorageStub.withArgs(SEGMENTS_STORAGE_KEY).returns(JSON.stringify(cachedRtd)); - - expect(config.getConfig().ortb2).to.be.undefined; - getRealTimeData(bidConfig, () => {}, rtdConfig, {}); - expect(config.getConfig().ortb2.user.data).to.deep.include.members([rtdUserObj1]); - }); - - it('should initalise and return with config', function () { - expect(getRealTimeData(testReqBidsConfigObj, onDone, cmoduleConfig)).to.equal(undefined) - }); - }); - - describe('dapTokenize', function () { - it('dapTokenize error callback', function () { - let configAsync = JSON.parse(JSON.stringify(sampleConfig)); - let submoduleCallback = dapUtils.dapTokenize(configAsync, sampleIdentity, - function(token, status, xhr) { - }, - function(xhr, status, error) { - } - ); - let request = server.requests[0]; - request.respond(400, responseHeader, JSON.stringify('error')); - expect(submoduleCallback).to.equal(undefined); - }); - - it('dapTokenize success callback', function () { - let configAsync = JSON.parse(JSON.stringify(sampleConfig)); - let submoduleCallback = dapUtils.dapTokenize(configAsync, sampleIdentity, - function(token, status, xhr) { - }, - function(xhr, status, error) { - } - ); - let request = server.requests[0]; - request.respond(200, responseHeader, JSON.stringify('success')); - expect(submoduleCallback).to.equal(undefined); - }); - }); - - describe('dapTokenize and dapMembership incorrect params', function () { - it('Onerror and config are null', function () { - expect(dapUtils.dapTokenize(null, 'identity', null, null)).to.be.equal(undefined); - expect(dapUtils.dapMembership(null, 'identity', null, null)).to.be.equal(undefined); - const config = { - 'api_hostname': 'prebid.dap.akadns.net', - 'api_version': 1, - 'domain': '', - 'segtax': 503 - }; - let identity = { - type: 'dap-signature:1.0.0' - }; - expect(dapUtils.dapTokenize(config, identity, null, null)).to.be.equal(undefined); - expect(dapUtils.dapMembership(config, 'token', null, null)).to.be.equal(undefined); - }); - - it('dapGetToken success', function () { - let dapTokenizeStub = sinon.stub(dapUtils, 'dapTokenize').returns(onSuccess); - expect(dapUtils.dapGetToken(sampleConfig, 'token', - function(token, status, xhr) { - }, - function(xhr, status, error) { - } - )).to.be.equal(null); - dapTokenizeStub.restore(); - }); - }); - - describe('dapMembership', function () { - it('dapMembership success callback', function () { - let configAsync = JSON.parse(JSON.stringify(sampleConfig)); - let submoduleCallback = dapUtils.dapMembership(configAsync, 'token', - function(token, status, xhr) { - }, - function(xhr, status, error) { - } - ); - let request = server.requests[0]; - request.respond(200, responseHeader, JSON.stringify('success')); - expect(submoduleCallback).to.equal(undefined); - }); - - it('dapMembership error callback', function () { - let configAsync = JSON.parse(JSON.stringify(sampleConfig)); - let submoduleCallback = dapUtils.dapMembership(configAsync, 'token', - function(token, status, xhr) { - }, - function(xhr, status, error) { - } - ); - let request = server.requests[0]; - request.respond(400, responseHeader, JSON.stringify('error')); - expect(submoduleCallback).to.equal(undefined); - }); - }); - - describe('dapMembership', function () { - it('should invoke the getDapToken and getDapMembership', function () { - let config = { - api_hostname: cmoduleConfig.params.apiHostname, - api_version: cmoduleConfig.params.apiVersion, - domain: cmoduleConfig.params.domain, - segtax: cmoduleConfig.params.segtax - }; - let identity = { - type: cmoduleConfig.params.identityType - }; - - let membership = { - said: 'item.said1', - cohorts: 'item.cohorts', - attributes: null - }; - - let getDapTokenStub = sinon.stub(dapUtils, 'dapGetToken').returns('token3'); - let getDapMembershipStub = sinon.stub(dapUtils, 'dapGetMembership').returns(membership); - let dapTokenizeStub = sinon.stub(dapUtils, 'dapTokenize').returns('response', 200, 'request'); - getRealTimeData(testReqBidsConfigObj, onDone, cmoduleConfig); - expect(getDapTokenStub.calledOnce).to.be.equal(true); - expect(getDapMembershipStub.calledOnce).to.be.equal(true); - getDapTokenStub.restore(); - getDapMembershipStub.restore(); - dapTokenizeStub.restore(); - }); - }); - - describe('dapMembershipToRtbSegment', function () { - it('dapMembershipToRtbSegment', function () { - let membership1 = { - said: 'item.said1', - cohorts: 'item.cohorts', - attributes: null - }; - const config = { - apiHostname: 'prebid.dap.akadns.net', - apiVersion: 'x1', - domain: 'prebid.org', - tokenTtl: 5, - segtax: 503 - }; - let identity = { - type: 'dap-signature:1.0.0' - }; - - expect(dapUtils.dapGetMembership(config, 'token')).to.equal(null) - const membership = {cohorts: ['1', '5', '7']} - expect(dapUtils.dapMembershipToRtbSegment(membership, config)).to.not.equal(undefined); - }); - }); -}); diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js deleted file mode 100644 index 58a5a3b54ab..00000000000 --- a/test/spec/modules/alkimiBidAdapter_spec.js +++ /dev/null @@ -1,164 +0,0 @@ -import { expect } from 'chai' -import { ENDPOINT, spec } from 'modules/alkimiBidAdapter.js' -import { newBidder } from 'src/adapters/bidderFactory.js' - -const REQUEST = { - 'bidId': '456', - 'bidder': 'alkimi', - 'sizes': [[300, 250]], - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250]] - } - }, - 'params': { - bidFloor: 0.1, - token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', - pos: 7 - } -} - -const BIDDER_BANNER_RESPONSE = { - 'prebidResponse': [{ - 'ad': '
test
', - 'requestId': 'e64782a4-8e68-4c38-965b-80ccf115d46d', - 'cpm': 900.5, - 'currency': 'USD', - 'width': 640, - 'height': 480, - 'ttl': 300, - 'creativeId': 1, - 'netRevenue': true, - 'winUrl': 'http://test.com', - 'mediaType': 'banner', - 'adomain': ['test.com'] - }] -} - -const BIDDER_VIDEO_RESPONSE = { - 'prebidResponse': [{ - 'ad': 'vast', - 'requestId': 'e64782a4-8e68-4c38-965b-80ccf115d46z', - 'cpm': 800.4, - 'currency': 'USD', - 'width': 1024, - 'height': 768, - 'ttl': 200, - 'creativeId': 2, - 'netRevenue': true, - 'winUrl': 'http://test.com', - 'mediaType': 'video', - 'adomain': ['test.com'] - }] -} - -const BIDDER_NO_BID_RESPONSE = '' - -describe('alkimiBidAdapter', function () { - const adapter = newBidder(spec) - - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(adapter.callBids).to.exist.and.to.be.a('function') - }) - }) - - describe('isBidRequestValid', function () { - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(REQUEST)).to.equal(true) - }) - - it('should return false when required params are not passed', function () { - let bid = Object.assign({}, REQUEST) - delete bid.params.token - expect(spec.isBidRequestValid(bid)).to.equal(false) - - bid = Object.assign({}, REQUEST) - delete bid.params.bidFloor - expect(spec.isBidRequestValid(bid)).to.equal(false) - - bid = Object.assign({}, REQUEST) - delete bid.params - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - }) - - describe('buildRequests', function () { - let bidRequests = [REQUEST] - const bidderRequest = spec.buildRequests(bidRequests, { - auctionId: '123', - refererInfo: { - referer: 'http://test.com/path.html' - } - }) - - it('sends bid request to ENDPOINT via POST', function () { - expect(bidderRequest.method).to.equal('POST') - expect(bidderRequest.data.requestId).to.equal('123') - expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') - expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner' }) - expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined) - expect(bidderRequest.data.bidIds).to.deep.contains('456') - expect(bidderRequest.data.signature).to.equal(undefined) - expect(bidderRequest.options.customHeaders).to.deep.equal({ 'Rtb-Direct': true }) - expect(bidderRequest.options.contentType).to.equal('application/json') - expect(bidderRequest.url).to.equal(ENDPOINT) - }) - }) - - describe('interpretResponse', function () { - it('handles banner request : should get correct bid response', function () { - const result = spec.interpretResponse({ body: BIDDER_BANNER_RESPONSE }, {}) - - expect(result[0]).to.have.property('ad').equal('
test
') - expect(result[0]).to.have.property('requestId').equal('e64782a4-8e68-4c38-965b-80ccf115d46d') - expect(result[0]).to.have.property('cpm').equal(900.5) - expect(result[0]).to.have.property('currency').equal('USD') - expect(result[0]).to.have.property('width').equal(640) - expect(result[0]).to.have.property('height').equal(480) - expect(result[0]).to.have.property('ttl').equal(300) - expect(result[0]).to.have.property('creativeId').equal(1) - expect(result[0]).to.have.property('netRevenue').equal(true) - expect(result[0]).to.have.property('winUrl').equal('http://test.com') - expect(result[0]).to.have.property('mediaType').equal('banner') - expect(result[0].meta).to.exist.property('advertiserDomains') - expect(result[0].meta).to.have.property('advertiserDomains').lengthOf(1) - }) - - it('handles video request : should get correct bid response', function () { - const result = spec.interpretResponse({ body: BIDDER_VIDEO_RESPONSE }, {}) - - expect(result[0]).to.have.property('ad').equal('vast') - expect(result[0]).to.have.property('requestId').equal('e64782a4-8e68-4c38-965b-80ccf115d46z') - expect(result[0]).to.have.property('cpm').equal(800.4) - expect(result[0]).to.have.property('currency').equal('USD') - expect(result[0]).to.have.property('width').equal(1024) - expect(result[0]).to.have.property('height').equal(768) - expect(result[0]).to.have.property('ttl').equal(200) - expect(result[0]).to.have.property('creativeId').equal(2) - expect(result[0]).to.have.property('netRevenue').equal(true) - expect(result[0]).to.have.property('winUrl').equal('http://test.com') - expect(result[0]).to.have.property('mediaType').equal('video') - expect(result[0]).to.have.property('vastXml').equal('vast') - expect(result[0].meta).to.exist.property('advertiserDomains') - expect(result[0].meta).to.have.property('advertiserDomains').lengthOf(1) - }) - - it('handles no bid response : should get empty array', function () { - let result = spec.interpretResponse({ body: undefined }, {}) - expect(result).to.deep.equal([]) - - result = spec.interpretResponse({ body: BIDDER_NO_BID_RESPONSE }, {}) - expect(result).to.deep.equal([]) - }) - }) - - describe('onBidWon', function () { - it('handles banner win: should get true', function () { - const win = BIDDER_BANNER_RESPONSE.prebidResponse[0] - const bidWonResult = spec.onBidWon(win) - - expect(bidWonResult).to.equal(true) - }) - }) -}) diff --git a/test/spec/modules/apacdexBidAdapter_spec.js b/test/spec/modules/apacdexBidAdapter_spec.js index ff1d3b813ce..9b75481ada9 100644 --- a/test/spec/modules/apacdexBidAdapter_spec.js +++ b/test/spec/modules/apacdexBidAdapter_spec.js @@ -252,14 +252,14 @@ describe('ApacdexBidAdapter', function () { it('should return a properly formatted request', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests) - expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/pbjs') + expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/apacdex') expect(bidRequests.method).to.equal('POST') expect(bidRequests.bidderRequests).to.eql(bidRequest); }) it('should return a properly formatted request with GDPR applies set to true', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests) - expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/pbjs') + expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/apacdex') expect(bidRequests.method).to.equal('POST') expect(bidRequests.data.gdpr.gdprApplies).to.equal(true) expect(bidRequests.data.gdpr.consentString).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A==') @@ -268,7 +268,7 @@ describe('ApacdexBidAdapter', function () { it('should return a properly formatted request with GDPR applies set to false', function () { bidderRequests.gdprConsent.gdprApplies = false; const bidRequests = spec.buildRequests(bidRequest, bidderRequests) - expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/pbjs') + expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/apacdex') expect(bidRequests.method).to.equal('POST') expect(bidRequests.data.gdpr.gdprApplies).to.equal(false) expect(bidRequests.data.gdpr.consentString).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A==') @@ -288,7 +288,7 @@ describe('ApacdexBidAdapter', function () { } }; const bidRequests = spec.buildRequests(bidRequest, bidderRequests) - expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/pbjs') + expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/apacdex') expect(bidRequests.method).to.equal('POST') expect(bidRequests.data.gdpr.gdprApplies).to.equal(false) expect(bidRequests.data.gdpr).to.not.include.keys('consentString') @@ -308,7 +308,7 @@ describe('ApacdexBidAdapter', function () { } }; const bidRequests = spec.buildRequests(bidRequest, bidderRequests) - expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/pbjs') + expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/apacdex') expect(bidRequests.method).to.equal('POST') expect(bidRequests.data.gdpr.gdprApplies).to.equal(true) expect(bidRequests.data.gdpr).to.not.include.keys('consentString') @@ -384,7 +384,7 @@ describe('ApacdexBidAdapter', function () { describe('.interpretResponse', function () { const bidRequests = { 'method': 'POST', - 'url': 'https://useast.quantumdex.io/auction/pbjs', + 'url': 'https://useast.quantumdex.io/auction/apacdex', 'withCredentials': true, 'data': { 'device': { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 76d18c43e9d..9396c1e1928 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -100,55 +100,6 @@ describe('AppNexusAdapter', function () { expect(payload.tags[0].private_sizes).to.deep.equal([{width: 300, height: 250}]); }); - it('should add position in request', function() { - // set from bid.params - let bidRequest = deepClone(bidRequests[0]); - bidRequest.params.position = 'above'; - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].position).to.exist; - expect(payload.tags[0].position).to.deep.equal(1); - - // set from mediaTypes.banner.pos = 1 - bidRequest = deepClone(bidRequests[0]); - bidRequest.mediaTypes = { - banner: { pos: 1 } - }; - - const request2 = spec.buildRequests([bidRequest]); - const payload2 = JSON.parse(request2.data); - - expect(payload2.tags[0].position).to.exist; - expect(payload2.tags[0].position).to.deep.equal(1); - - // set from mediaTypes.video.pos = 3 - bidRequest = deepClone(bidRequests[0]); - bidRequest.mediaTypes = { - video: { pos: 3 } - }; - - const request3 = spec.buildRequests([bidRequest]); - const payload3 = JSON.parse(request3.data); - - expect(payload3.tags[0].position).to.exist; - expect(payload3.tags[0].position).to.deep.equal(2); - - // bid.params trumps mediatypes - bidRequest = deepClone(bidRequests[0]); - bidRequest.params.position = 'above'; - bidRequest.mediaTypes = { - banner: { pos: 3 } - }; - - const request4 = spec.buildRequests([bidRequest]); - const payload4 = JSON.parse(request4.data); - - expect(payload4.tags[0].position).to.exist; - expect(payload4.tags[0].position).to.deep.equal(1); - }); - it('should add publisher_id in request', function() { let bidRequest = Object.assign({}, bidRequests[0], @@ -165,7 +116,7 @@ describe('AppNexusAdapter', function () { expect(payload.tags[0].publisher_id).to.deep.equal(1231234); expect(payload.publisher_id).to.exist; expect(payload.publisher_id).to.deep.equal(1231234); - }); + }) it('should add source and verison to the tag', function () { const request = spec.buildRequests(bidRequests); @@ -605,33 +556,6 @@ describe('AppNexusAdapter', function () { config.getConfig.restore(); }); - it('adds auction level keywords to request when set', function() { - let bidRequest = Object.assign({}, bidRequests[0]); - sinon - .stub(config, 'getConfig') - .withArgs('appnexusAuctionKeywords') - .returns({ - gender: 'm', - music: ['rock', 'pop'], - test: '' - }); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.keywords).to.deep.equal([{ - 'key': 'gender', - 'value': ['m'] - }, { - 'key': 'music', - 'value': ['rock', 'pop'] - }, { - 'key': 'test' - }]); - - config.getConfig.restore(); - }); - it('should attach native params to the request', function () { let bidRequest = Object.assign({}, bidRequests[0], @@ -868,7 +792,7 @@ describe('AppNexusAdapter', function () { }); it('should add referer info to payload', function () { - const bidRequest = Object.assign({}, bidRequests[0]); + const bidRequest = Object.assign({}, bidRequests[0]) const bidderRequest = { refererInfo: { referer: 'https://example.com/page.html', @@ -893,40 +817,6 @@ describe('AppNexusAdapter', function () { }); }); - it('if defined, should include publisher pageUrl to normal referer info in payload', function () { - const bidRequest = Object.assign({}, bidRequests[0]); - sinon - .stub(config, 'getConfig') - .withArgs('pageUrl') - .returns('https://mypub.override.com/test/page.html'); - - const bidderRequest = { - refererInfo: { - referer: 'https://example.com/page.html', - reachedTop: true, - numIframes: 2, - stack: [ - 'https://example.com/page.html', - 'https://example.com/iframe1.html', - 'https://example.com/iframe2.html' - ] - } - } - const request = spec.buildRequests([bidRequest], bidderRequest); - const payload = JSON.parse(request.data); - - expect(payload.referrer_detection).to.exist; - expect(payload.referrer_detection).to.deep.equal({ - rd_ref: 'https%3A%2F%2Fexample.com%2Fpage.html', - rd_top: true, - rd_ifs: 2, - rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(','), - rd_can: 'https://mypub.override.com/test/page.html' - }); - - config.getConfig.restore(); - }); - it('should populate schain if available', function () { const bidRequest = Object.assign({}, bidRequests[0], { schain: { @@ -1026,22 +916,7 @@ describe('AppNexusAdapter', function () { flocId: { id: 'sample-flocid-value', version: 'chrome.1.0' - }, - pubProvidedId: [{ - source: 'puburl.com', - uids: [{ - id: 'pubid1', - atype: 1, - ext: { - stype: 'ppuid' - } - }] - }, { - source: 'puburl2.com', - uids: [{ - id: 'pubid2' - }] - }] + } } }); @@ -1078,16 +953,6 @@ describe('AppNexusAdapter', function () { id: 'sample-uid2-value', rti_partner: 'UID2' }); - - expect(payload.eids).to.deep.include({ - source: 'puburl.com', - id: 'pubid1' - }); - - expect(payload.eids).to.deep.include({ - source: 'puburl2.com', - id: 'pubid2' - }); }); it('should populate iab_support object at the root level if omid support is detected', function () { @@ -1139,16 +1004,12 @@ describe('AppNexusAdapter', function () { describe('interpretResponse', function () { let bfStub; - let bidderSettingsStorage; - before(function() { bfStub = sinon.stub(bidderFactory, 'getIabSubCategory'); - bidderSettingsStorage = $$PREBID_GLOBAL$$.bidderSettings; }); after(function() { bfStub.restore(); - $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsStorage; }); let response = { @@ -1186,8 +1047,7 @@ describe('AppNexusAdapter', function () { 'trackers': [ { 'impression_urls': [ - 'https://lax1-ib.adnxs.com/impression', - 'https://www.test.com/tracker' + 'https://lax1-ib.adnxs.com/impression' ], 'video_events': {} } @@ -1216,15 +1076,6 @@ describe('AppNexusAdapter', function () { 'adUnitCode': 'code', 'appnexus': { 'buyerMemberId': 958 - }, - 'meta': { - 'dchain': { - 'ver': '1.0', - 'complete': 0, - 'nodes': [{ - 'bsid': '958' - }] - } } } ]; @@ -1233,46 +1084,11 @@ describe('AppNexusAdapter', function () { bidId: '3db3773286ee59', adUnitCode: 'code' }] - }; + } let result = spec.interpretResponse({ body: response }, {bidderRequest}); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('should reject 0 cpm bids', function () { - let zeroCpmResponse = deepClone(response); - zeroCpmResponse.tags[0].ads[0].cpm = 0; - - let bidderRequest = { - bidderCode: 'appnexus' - }; - - let result = spec.interpretResponse({ body: zeroCpmResponse }, { bidderRequest }); - expect(result.length).to.equal(0); - }); - - it('should allow 0 cpm bids if allowZeroCpmBids setConfig is true', function () { - $$PREBID_GLOBAL$$.bidderSettings = { - appnexus: { - allowZeroCpmBids: true - } - }; - - let zeroCpmResponse = deepClone(response); - zeroCpmResponse.tags[0].ads[0].cpm = 0; - - let bidderRequest = { - bidderCode: 'appnexus', - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code' - }] - }; - - let result = spec.interpretResponse({ body: zeroCpmResponse }, { bidderRequest }); - expect(result.length).to.equal(1); - expect(result[0].cpm).to.equal(0); - }); - it('handles nobid responses', function () { let response = { 'version': '0.0.1', @@ -1518,20 +1334,6 @@ describe('AppNexusAdapter', function () { expect(Object.keys(result[0].meta)).to.include.members(['advertiserId']); }); - it('should add brand id', function() { - let responseBrandId = deepClone(response); - responseBrandId.tags[0].ads[0].brand_id = 123; - - let bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code' - }] - } - let result = spec.interpretResponse({ body: responseBrandId }, {bidderRequest}); - expect(Object.keys(result[0].meta)).to.include.members(['brandId']); - }); - it('should add advertiserDomains', function() { let responseAdvertiserId = deepClone(response); responseAdvertiserId.tags[0].ads[0].adomain = ['123']; @@ -1547,28 +1349,4 @@ describe('AppNexusAdapter', function () { expect(Object.keys(result[0].meta.advertiserDomains)).to.deep.equal([]); }); }); - - describe('transformBidParams', function () { - it('convert keywords param differently for psp endpoint', function () { - sinon.stub(config, 'getConfig') - .withArgs('s2sConfig') - .returns({ - endpoint: { - p1Consent: 'https://ib.adnxs.com/openrtb2/prebid' - } - }); - - const oldParams = { - keywords: { - genre: ['rock', 'pop'], - pets: 'dog' - } - }; - - const newParams = spec.transformBidParams(oldParams, true); - expect(newParams.keywords).to.equal('genre=rock,genre=pop,pets=dog'); - - config.getConfig.restore(); - }); - }); }); diff --git a/test/spec/modules/asealBidAdapter_spec.js b/test/spec/modules/asealBidAdapter_spec.js deleted file mode 100644 index 2dc1b47b7d0..00000000000 --- a/test/spec/modules/asealBidAdapter_spec.js +++ /dev/null @@ -1,213 +0,0 @@ -import { expect } from 'chai'; -import { - spec, - BIDDER_CODE, - API_ENDPOINT, - HEADER_AOTTER_VERSION, - WEB_SESSION_ID_KEY, -} from 'modules/asealBidAdapter.js'; -import { getRefererInfo } from 'src/refererDetection.js'; -import { newBidder } from 'src/adapters/bidderFactory.js'; -import { config } from 'src/config.js'; -import * as utils from 'src/utils.js'; -import { storage } from 'modules/asealBidAdapter.js'; - -const TEST_CLIENT_ID = 'TEST_CLIENT_ID'; -const TEST_WEB_SESSION_ID = 'TEST_WEB_SESSION_ID'; - -describe('asealBidAdapter', () => { - const adapter = newBidder(spec); - - let localStorageIsEnabledStub; - let getDataFromLocalStorageStub; - let sandbox; - let w; - - beforeEach((done) => { - localStorageIsEnabledStub = sinon.stub(storage, 'localStorageIsEnabled'); - getDataFromLocalStorageStub = sinon.stub( - storage, - 'getDataFromLocalStorage' - ); - - w = { - document: { - title: 'Aseal', - referrer: 'https://aseal.in/', - href: 'https://aseal.in/', - }, - location: { - href: 'https://aseal.in/', - }, - }; - - sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getWindowTop').returns(w); - sandbox.stub(utils, 'getWindowSelf').returns(w); - done(); - }); - - afterEach(() => { - localStorageIsEnabledStub.restore(); - getDataFromLocalStorageStub.restore(); - sandbox.restore(); - config.resetConfig(); - }); - - describe('inherited functions', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', () => { - const bid = { - bidder: 'aseal', - params: { - placeUid: '123', - }, - }; - - it('should return true when required params found', () => { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when required param placeUid is not passed', () => { - bid.params = { - placeUid: '', - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when required param placeUid is wrong type', () => { - bid.params = { - placeUid: null, - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when required params are not passed', () => { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {}; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', () => { - it('should return an empty array when there are no bid requests', () => { - const bidRequests = []; - const request = spec.buildRequests(bidRequests); - - expect(request).to.be.an('array').that.is.empty; - }); - - it('should send `x-aotter-clientid` header as empty string when user not set config `clientId`', () => { - const bidRequests = [ - { - bidder: BIDDER_CODE, - params: { - placeUid: '123', - }, - }, - ]; - - const bidderRequest = {}; - const request = spec.buildRequests(bidRequests, bidderRequest)[0]; - - expect(request.options.customHeaders['x-aotter-clientid']).equal(''); - }); - - it('should send bid requests to ENDPOINT via POST', () => { - const bidRequests = [ - { - bidder: BIDDER_CODE, - params: { - placeUid: '123', - }, - }, - ]; - - const bidderRequest = { - refererInfo: getRefererInfo(), - }; - - config.setConfig({ - aseal: { - clientId: TEST_CLIENT_ID, - }, - }); - - localStorageIsEnabledStub.returns(true); - getDataFromLocalStorageStub - .withArgs(WEB_SESSION_ID_KEY) - .returns(TEST_WEB_SESSION_ID); - - const request = spec.buildRequests(bidRequests, bidderRequest)[0]; - - utils.getWindowTop.restore(); - utils.getWindowSelf.restore(); - - sandbox.stub(utils, 'getWindowTop').returns(w); - sandbox.stub(utils, 'getWindowSelf').returns(w); - - const payload = { - meta: { - dr: w.document.referrer, - drs: w.document.referrer, - drt: w.document.referrer, - dt: w.document.title, - dl: w.location.href, - }, - }; - - expect(request.url).to.equal(API_ENDPOINT); - expect(request.method).to.equal('POST'); - expect(request.options).deep.equal({ - contentType: 'application/json', - withCredentials: true, - customHeaders: { - 'x-aotter-clientid': TEST_CLIENT_ID, - 'x-aotter-version': HEADER_AOTTER_VERSION, - }, - }); - expect(request.data.bids).deep.equal(bidRequests); - expect(request.data.payload).deep.equal(payload); - expect(request.data.device).deep.equal({ - webSessionId: TEST_WEB_SESSION_ID, - }); - }); - }); - - describe('interpretResponse', () => { - it('should return an empty array when there are no bids', () => { - const serverResponse = {}; - const response = spec.interpretResponse(serverResponse); - - expect(response).is.an('array').that.is.empty; - }); - - it('should get correct bid response', () => { - const serverResponse = { - body: [ - { - requestId: '2ef08f145b7a4f', - cpm: 3, - width: 300, - height: 250, - creativeId: '123abc', - dealId: '123abc', - currency: 'USD', - netRevenue: false, - mediaType: 'banner', - ttl: 300, - ad: '', - }, - ], - }; - const response = spec.interpretResponse(serverResponse); - - expect(response).deep.equal(serverResponse.body); - }); - }); -}); diff --git a/test/spec/modules/atsAnalyticsAdapter_spec.js b/test/spec/modules/atsAnalyticsAdapter_spec.js index cae90a19223..e2dd4747199 100644 --- a/test/spec/modules/atsAnalyticsAdapter_spec.js +++ b/test/spec/modules/atsAnalyticsAdapter_spec.js @@ -5,22 +5,16 @@ import {server} from '../../mocks/xhr.js'; import {parseBrowser} from '../../../modules/atsAnalyticsAdapter.js'; import {getStorageManager} from '../../../src/storageManager.js'; import {analyticsUrl} from '../../../modules/atsAnalyticsAdapter.js'; -let utils = require('src/utils'); let events = require('src/events'); let constants = require('src/constants.json'); export const storage = getStorageManager(); -let sandbox; -let clock; -let now = new Date(); describe('ats analytics adapter', function () { beforeEach(function () { sinon.stub(events, 'getEvents').returns([]); storage.setCookie('_lr_env_src_ats', 'true', 'Thu, 01 Jan 1970 00:00:01 GMT'); - sandbox = sinon.sandbox.create(); - clock = sandbox.useFakeTimers(now.getTime()); }); afterEach(function () { @@ -28,21 +22,18 @@ describe('ats analytics adapter', function () { atsAnalyticsAdapter.getUserAgent.restore(); atsAnalyticsAdapter.disableAnalytics(); Math.random.restore(); - sandbox.restore(); - clock.restore(); }); describe('track', function () { it('builds and sends request and response data', function () { sinon.stub(Math, 'random').returns(0.99); + sinon.stub(atsAnalyticsAdapter, 'shouldFireRequest').returns(true); sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25'); - + let now = new Date(); now.setTime(now.getTime() + 3600000); storage.setCookie('_lr_env_src_ats', 'true', now.toUTCString()); storage.setCookie('_lr_sampling_rate', '10', now.toUTCString()); - this.timeout(2100); - let initOptions = { pid: '10433394' }; @@ -68,7 +59,7 @@ describe('ats analytics adapter', function () { 'refererInfo': { 'referer': 'https://example.com/dev' }, - 'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7' + 'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7', }; // prepare general auction - response let bidResponse = { @@ -96,7 +87,7 @@ describe('ats analytics adapter', function () { let expectedAfterBid = { 'Data': [{ 'has_envelope': true, - 'adapter_version': 3, + 'adapter_version': 1, 'bidder': 'appnexus', 'bid_id': '30c77d079cdf17', 'auction_id': 'a5b849e5-87d7-4205-8300-d063084fcfb7', @@ -109,30 +100,10 @@ describe('ats analytics adapter', function () { 'response_time_stamp': '2020-02-03T14:23:11.978Z', 'currency': 'USD', 'cpm': 0.5, - 'net_revenue': true, - 'bid_won': true + 'net_revenue': true }] }; - let wonRequest = { - 'adId': '2eddfdc0c791dc', - 'mediaType': 'banner', - 'requestId': '30c77d079cdf17', - 'cpm': 0.5, - 'creativeId': 29681110, - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 300, - 'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7', - 'statusMessage': 'Bid available', - 'responseTimestamp': 1633525319061, - 'requestTimestamp': 1633525319258, - 'bidder': 'appnexus', - 'adUnitCode': 'div-gpt-ad-1438287399331-0', - 'size': '300x250', - 'status': 'rendered' - }; - // lets simulate that some bidders timeout let bidTimeoutArgsV1 = [ { @@ -174,14 +145,6 @@ describe('ats analytics adapter', function () { // Step 5: Send auction end event events.emit(constants.EVENTS.AUCTION_END, {}); - // Step 6: Send bid won event - events.emit(constants.EVENTS.BID_WON, wonRequest); - - sandbox.stub($$PREBID_GLOBAL$$, 'getAllWinningBids').callsFake((key) => { - return [wonRequest] - }); - - clock.tick(2000); let requests = server.requests.filter(req => { return req.url.indexOf(analyticsUrl) > -1; @@ -190,12 +153,13 @@ describe('ats analytics adapter', function () { expect(requests.length).to.equal(1); let realAfterBid = JSON.parse(requests[0].requestBody); - - // Step 7: assert real data after bid and expected data + // Step 6: assert real data after bid and expected data expect(realAfterBid['Data']).to.deep.equal(expectedAfterBid['Data']); // check that the publisher ID is configured via options expect(atsAnalyticsAdapter.context.pid).to.equal(initOptions.pid); + + atsAnalyticsAdapter.shouldFireRequest.restore(); }) it('check browser is safari', function () { sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25'); @@ -221,12 +185,6 @@ describe('ats analytics adapter', function () { let browser = parseBrowser(); expect(browser).to.equal('Firefox'); }) - it('check browser is unknown', function () { - sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns(undefined); - sinon.stub(Math, 'random').returns(0.99); - let browser = parseBrowser(); - expect(browser).to.equal('Unknown'); - }) it('should not fire analytics request if sampling rate is 0', function () { sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25'); sinon.stub(Math, 'random').returns(0.99); @@ -237,7 +195,7 @@ describe('ats analytics adapter', function () { sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25'); sinon.stub(Math, 'random').returns(0.99); // publisher can try to pass anything they want but we will set sampling rate to 100, which means we will have 1% of requests - let result = atsAnalyticsAdapter.shouldFireRequest(8); + let result = atsAnalyticsAdapter.shouldFireRequest(10); expect(result).to.equal(true); }) it('should not fire analytics request if math random is something other then 0.99', function () { @@ -247,31 +205,5 @@ describe('ats analytics adapter', function () { let result = atsAnalyticsAdapter.shouldFireRequest(10); expect(result).to.equal(false); }) - - it('should set cookie value to 10 for _lr_sampling_rate', function () { - sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25'); - sinon.stub(Math, 'random').returns(0.99); - atsAnalyticsAdapter.setSamplingCookie(10); - let samplingRate = storage.getCookie('_lr_sampling_rate'); - expect(samplingRate).to.equal('10'); - }) - - it('should set cookie value to 0 for _lr_sampling_rate', function () { - sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25'); - sinon.stub(Math, 'random').returns(0.99); - atsAnalyticsAdapter.setSamplingCookie(0); - let samplingRate = storage.getCookie('_lr_sampling_rate'); - expect(samplingRate).to.equal('0'); - }) - - it('enable analytics', function () { - sandbox.stub(utils, 'logError'); - sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25'); - sinon.stub(Math, 'random').returns(0.99); - atsAnalyticsAdapter.enableAnalytics({ - options: {} - }); - expect(utils.logError.called).to.equal(true); - }) }) }) diff --git a/test/spec/modules/audiencerunBidAdapter_spec.js b/test/spec/modules/audiencerunBidAdapter_spec.js index 7f1e059fa2a..7c1279f5073 100644 --- a/test/spec/modules/audiencerunBidAdapter_spec.js +++ b/test/spec/modules/audiencerunBidAdapter_spec.js @@ -8,68 +8,65 @@ const BID_SERVER_RESPONSE = { body: { bid: [ { - bidId: '51ef8751f9aead', - zoneId: '12345abcde', - crid: '5678', - cpm: 8.0219519, - currency: 'USD', - w: 728, - h: 90, - isNet: false, - buying_type: 'rtb', - syncUrl: 'https://ac.audiencerun.com/f/sync.html', - adm: '', - adomain: ['example.com'], - }, - ], - }, + 'bidId': '51ef8751f9aead', + 'zoneId': '12345abcde', + 'crid': '5678', + 'cpm': 8.021951999999999999, + 'currency': 'USD', + 'w': 728, + 'h': 90, + 'isNet': false, + 'buying_type': 'rtb', + 'syncUrl': 'https://ac.audiencerun.com/f/sync.html', + 'adm': '', + 'adomain': ['example.com'] + } + ] + } }; -describe('AudienceRun bid adapter tests', function () { +describe('AudienceRun bid adapter tests', function() { const adapter = newBidder(spec); - describe('inherited functions', function () { - it('exists and is a function', function () { + describe('inherited functions', function() { + it('exists and is a function', function() { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', function () { + describe('isBidRequestValid', function() { let bid = { - bidder: 'audiencerun', - params: { - zoneId: '12345abcde', + 'bidder': 'audiencerun', + 'params': { + 'zoneId': '12345abcde' }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [ - [300, 250], - [300, 600], - ], - }, + 'adUnitCode': 'adunit-code', + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } }, - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - creativeId: 'er2ee', + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'creativeId': 'er2ee' }; - it('should return true when required params found', function () { + it('should return true when required params found', function() { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when zoneId is valid', function () { + it('should return true when zoneId is valid', function() { let bid = Object.assign({}, bid); delete bid.params; bid.params = { - zoneId: '12345abcde', + 'zoneId': '12345abcde' }; expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', function () { + it('should return false when required params are not passed', function() { let bid = Object.assign({}, bid); delete bid.params; @@ -79,45 +76,38 @@ describe('AudienceRun bid adapter tests', function () { }); }); - describe('buildRequests', function () { + describe('buildRequests', function() { const bidRequests = [ { - bidder: 'audiencerun', - bidId: '51ef8751f9aead', - params: { - zoneId: '12345abcde', + 'bidder': 'audiencerun', + 'bidId': '51ef8751f9aead', + 'params': { + 'zoneId': '12345abcde' }, - adUnitCode: 'div-gpt-ad-1460505748561-0', - transactionId: 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', - mediaTypes: { - banner: { - sizes: [ - [320, 50], - [300, 250], - [300, 600], - ], - }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'mediaTypes': { + 'banner': { + 'sizes': [[320, 50], [300, 250], [300, 600]] + } }, - bidderRequestId: '418b37f85e772c', - auctionId: '18fd8b8b0bd757', - bidRequestsCount: 1, - }, + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1 + } ]; const bidRequest = bidRequests[0]; - it('sends a valid bid request to ENDPOINT via POST', function () { + it('sends a valid bid request to ENDPOINT via POST', function() { const request = spec.buildRequests(bidRequests, { gdprConsent: { - consentString: - 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA', - gdprApplies: true, + consentString: 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA', + gdprApplies: true }, refererInfo: { - canonicalUrl: undefined, - referer: 'https://example.com', - numIframes: 0, - reachedTop: true, - }, + canonicalUrl: 'https://example.com/canonical', + referer: 'https://example.com' + } }); expect(request.url).to.equal(ENDPOINT); @@ -126,9 +116,7 @@ describe('AudienceRun bid adapter tests', function () { const payload = JSON.parse(request.data); expect(payload.gdpr).to.exist; - expect(payload.bids) - .to.exist.and.to.be.an('array') - .and.to.have.lengthOf(1); + expect(payload.bids).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); expect(payload.referer).to.exist; const bid = payload.bids[0]; @@ -140,13 +128,13 @@ describe('AudienceRun bid adapter tests', function () { expect(bid.sizes[0].h).to.be.a('number'); }); - it('should send GDPR to endpoint and honor gdprApplies value', function () { + it('should send GDPR to endpoint and honor gdprApplies value', function() { let consentString = 'bogusConsent'; let bidderRequest = { - gdprConsent: { - consentString: consentString, - gdprApplies: true, - }, + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': true + } }; const request = spec.buildRequests(bidRequests, bidderRequest); @@ -156,10 +144,10 @@ describe('AudienceRun bid adapter tests', function () { expect(payload.gdpr.applies).to.equal(true); let bidderRequest2 = { - gdprConsent: { - consentString: consentString, - gdprApplies: false, - }, + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': false + } }; const request2 = spec.buildRequests(bidRequests, bidderRequest2); @@ -170,32 +158,19 @@ describe('AudienceRun bid adapter tests', function () { expect(payload2.gdpr.applies).to.equal(false); }); - it('should use the auctionUrl passed from bid params', function () { - const bid = Object.assign({}, bidRequest, { - params: { - zoneId: '12345abcde', - auctionUrl: 'https://auction.url.audiencerun.com', - }, - }); - const request = spec.buildRequests([bid]); - - expect(request.url).to.exist; - expect(request.url).to.equal('https://auction.url.audiencerun.com'); - }); - - it('should use a bidfloor with a 0 value', function () { + it('should use a bidfloor with a 0 value', function() { const bid = Object.assign({}, bidRequest); const request = spec.buildRequests([bid]); const payload = JSON.parse(request.data); expect(payload.bids[0].bidfloor).to.exist.and.to.equal(0); - }); + }) it('should use bidfloor param value', function () { const bid = Object.assign({}, bidRequest, { params: { - bidfloor: 0.2, - }, - }); + 'bidfloor': 0.2 + } + }) const request = spec.buildRequests([bid]); const payload = JSON.parse(request.data); expect(payload.bids[0].bidfloor).to.exist.and.to.equal(0.2); @@ -204,104 +179,43 @@ describe('AudienceRun bid adapter tests', function () { it('should use floors module value', function () { const bid = Object.assign({}, bidRequest, { params: { - bidfloor: 0.5, - }, - }); + 'bidfloor': 0.5 + } + }) bid.getFloor = () => { - return { floor: 1, currency: 'USD' }; - }; - const request = spec.buildRequests([bid]); - const payload = JSON.parse(request.data); - expect(payload.bids[0].bidfloor).to.exist.and.to.equal(1); - }); - - it('should add userid eids information to the request', function () { - const bid = Object.assign({}, bidRequest); - bid.userId = { - pubcid: '01EAJWWNEPN3CYMM5N8M5VXY22', - unsuported: '666', + return { floor: 1, currency: 'USD' } } - const request = spec.buildRequests([bid]); const payload = JSON.parse(request.data); - - expect(payload.userId).to.exist; - expect(payload.userId).to.deep.equal([ - { - source: 'pubcid.org', - uids: [ - { - atype: 1, - id: '01EAJWWNEPN3CYMM5N8M5VXY22', - }, - ], - }, - ]); + expect(payload.bids[0].bidfloor).to.exist.and.to.equal(1); }); - - it('should add schain object if available', function() { - const bid = Object.assign({}, bidRequest) - bid.schain = { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'directseller.com', - sid: '00001', - rid: 'BidRequest1', - hp: 1, - }, - ], - }; - - const request = spec.buildRequests([bid]); - const payload = JSON.parse(request.data); - - expect(payload.schain).to.exist; - expect(payload.schain).to.deep.equal({ - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'directseller.com', - sid: '00001', - rid: 'BidRequest1', - hp: 1, - }, - ], - }); - }) }); describe('interpretResponse', function () { - const expectedResponse = [ - { - requestId: '51ef8751f9aead', - cpm: 8.0219519, - width: '728', - height: '90', - creativeId: '5678', - currency: 'USD', - netRevenue: false, - ttl: 300, - ad: '', - mediaType: 'banner', - meta: { - advertiserDomains: ['example.com'], - }, - }, - ]; + const expectedResponse = [{ + 'requestId': '51ef8751f9aead', + 'cpm': 8.021951999999999999, + 'width': '728', + 'height': '90', + 'creativeId': '5678', + 'currency': 'USD', + 'netRevenue': false, + 'ttl': 300, + 'ad': '', + 'mediaType': 'banner', + 'meta': { + 'advertiserDomains': ['example.com'] + } + }]; it('should get the correct bid response by display ad', function () { let result = spec.interpretResponse(BID_SERVER_RESPONSE); - expect(Object.keys(result[0])).to.have.members( - Object.keys(expectedResponse[0]) - ); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); it('should handle empty bid response', function () { const response = { - body: {}, + body: {} }; let result = spec.interpretResponse(response); expect(result.length).to.equal(0); @@ -309,19 +223,17 @@ describe('AudienceRun bid adapter tests', function () { }); describe('getUserSyncs', function () { - const serverResponses = [BID_SERVER_RESPONSE]; + const serverResponses = [ BID_SERVER_RESPONSE ]; const syncOptions = { iframeEnabled: true }; - it('should return empty if no server responses', function () { + it('should return empty if no server responses', function() { const syncs = spec.getUserSyncs(syncOptions, []); - expect(syncs).to.deep.equal([]); + expect(syncs).to.deep.equal([]) }); it('should return user syncs', function () { const syncs = spec.getUserSyncs(syncOptions, serverResponses); - expect(syncs).to.deep.equal([ - { type: 'iframe', url: 'https://ac.audiencerun.com/f/sync.html' }, - ]); + expect(syncs).to.deep.equal([{type: 'iframe', url: 'https://ac.audiencerun.com/f/sync.html'}]) }); }); diff --git a/test/spec/modules/automatadBidAdapter_spec.js b/test/spec/modules/automatadBidAdapter_spec.js index 09bfb96e8b9..9d828bad4c3 100644 --- a/test/spec/modules/automatadBidAdapter_spec.js +++ b/test/spec/modules/automatadBidAdapter_spec.js @@ -5,25 +5,7 @@ import { newBidder } from 'src/adapters/bidderFactory.js' describe('automatadBidAdapter', function () { const adapter = newBidder(spec) - let bidRequestRequiredParams = { - bidder: 'automatad', - params: {siteId: '123ad'}, - mediaTypes: { - banner: { - sizes: [[300, 600]], - } - }, - adUnitCode: 'some-ad-unit-code', - transactionId: '1465569e-52cc-4c36-88a1-7174cfef4b44', - sizes: [[300, 600]], - bidId: '123abc', - bidderRequestId: '3213887463c059', - auctionId: 'abc-123', - src: 'client', - bidRequestsCount: 1 - } - - let bidRequestAllParams = { + let bidRequest = { bidder: 'automatad', params: {siteId: '123ad', placementId: '123abc345'}, mediaTypes: { @@ -48,7 +30,6 @@ describe('automatadBidAdapter', function () { { 'bid': [ { - 'bidId': '123', 'adm': '', 'adomain': [ 'someAdDomain' @@ -77,14 +58,10 @@ describe('automatadBidAdapter', function () { }) describe('isBidRequestValid', function () { - let inValidBid = Object.assign({}, bidRequestRequiredParams) + let inValidBid = Object.assign({}, bidRequest) delete inValidBid.params it('should return true if all params present', function () { - expect(spec.isBidRequestValid(bidRequestAllParams)).to.equal(true) - }) - - it('should return true if only required params present', function() { - expect(spec.isBidRequestValid(bidRequestRequiredParams)).to.equal(true) + expect(spec.isBidRequestValid(bidRequest)).to.equal(true) }) it('should return false if any parameter missing', function () { @@ -93,7 +70,7 @@ describe('automatadBidAdapter', function () { }) describe('buildRequests', function () { - let req = spec.buildRequests([ bidRequestRequiredParams ], { refererInfo: { } }) + let req = spec.buildRequests([ bidRequest ], { refererInfo: { } }) let rdata it('should return request object', function () { @@ -109,9 +86,9 @@ describe('automatadBidAdapter', function () { expect(rdata.imp.length).to.equal(1) }) - it('should include siteId', function () { + it('should include placement', function () { let r = rdata.imp[0] - expect(r.siteId !== null).to.be.true + expect(r.placement !== null).to.be.true }) it('should include media types', function () { @@ -119,6 +96,11 @@ describe('automatadBidAdapter', function () { expect(r.media_types !== null).to.be.true }) + it('should include all publisher params', function () { + let r = rdata.imp[0] + expect(r.siteID !== null && r.placementID !== null).to.be.true + }) + it('should include adunit code', function () { let r = rdata.imp[0] expect(r.adUnitCode !== null).to.be.true @@ -191,29 +173,14 @@ describe('automatadBidAdapter', function () { }) }) - describe('onTimeout', function () { - const timeoutData = { - 'bidId': '123', - 'bidder': 'automatad', - 'adUnitCode': 'div-13', - 'auctionId': '1232', - 'params': [ - { - 'siteId': 'test', - 'placementId': 'test123' - } - ], - 'timeout': 1000 - } - - it('should exists and be a function', function () { - expect(spec.onTimeout).to.exist.and.to.be.a('function'); - }); - - it('should include timeoutData', function () { - expect(spec.onTimeout(timeoutData)).to.be.undefined; + describe('getUserSyncs', function () { + it('should return iframe sync', function () { + let sync = spec.getUserSyncs() + expect(sync.length).to.equal(1) + expect(sync[0].type === 'iframe') + expect(typeof sync[0].url === 'string') }) - }); + }) describe('onBidWon', function () { let serverResponses = spec.interpretResponse(expectedResponse[0]) diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index d9b8cac10b4..e29994eba44 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -1,7 +1,6 @@ import { expect } from 'chai'; import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, OUTSTREAM_SRC, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter.js'; -import { config } from 'src/config.js'; -import { parseUrl, deepAccess } from 'src/utils.js'; +import { parseUrl } from 'src/utils.js'; describe('BeachfrontAdapter', function () { let bidRequests; @@ -557,69 +556,6 @@ describe('BeachfrontAdapter', function () { }); }); - describe('with first-party data', function () { - let sandbox - - beforeEach(function () { - sandbox = sinon.sandbox.create(); - }); - - afterEach(function () { - sandbox.restore(); - }); - - it('must add first-party data to the video bid request', function () { - sandbox.stub(config, 'getConfig').callsFake(key => { - const cfg = { - ortb2: { - site: { - keywords: 'test keyword' - }, - user: { - data: 'some user data' - } - } - }; - return deepAccess(cfg, key); - }); - const bidRequest = bidRequests[0]; - bidRequest.mediaTypes = { video: {} }; - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/page.html' - } - }; - const requests = spec.buildRequests([ bidRequest ], bidderRequest); - const data = requests[0].data; - expect(data.user.data).to.equal('some user data'); - expect(data.site.keywords).to.equal('test keyword'); - expect(data.site.page).to.equal('http://example.com/page.html'); - expect(data.site.domain).to.equal('example.com'); - }); - - it('must add first-party data to the banner bid request', function () { - sandbox.stub(config, 'getConfig').callsFake(key => { - const cfg = { - ortb2: { - site: { - keywords: 'test keyword' - }, - user: { - data: 'some user data' - } - } - }; - return deepAccess(cfg, key); - }); - const bidRequest = bidRequests[0]; - bidRequest.mediaTypes = { banner: {} }; - const requests = spec.buildRequests([ bidRequest ]); - const data = requests[0].data; - expect(data.ortb2.user.data).to.equal('some user data'); - expect(data.ortb2.site.keywords).to.equal('test keyword'); - }); - }); - describe('for multi-format bids', function () { it('should create a POST request for each bid format', function () { const width = 300; diff --git a/test/spec/modules/beopBidAdapter_spec.js b/test/spec/modules/beopBidAdapter_spec.js index 832ad2707d3..58296243a4a 100644 --- a/test/spec/modules/beopBidAdapter_spec.js +++ b/test/spec/modules/beopBidAdapter_spec.js @@ -1,7 +1,6 @@ import { expect } from 'chai'; import { spec } from 'modules/beopBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; -import { config } from 'src/config.js'; const utils = require('src/utils'); const ENDPOINT = 'https://hb.beop.io/bid'; @@ -17,12 +16,6 @@ let validBid = { 'sizes': [[1, 1]] } }, - 'getFloor': () => { - return { - currency: 'USD', - floor: 10, - } - }, 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', @@ -31,10 +24,6 @@ let validBid = { }; describe('BeOp Bid Adapter tests', () => { - afterEach(function () { - config.setConfig({}); - }); - const adapter = newBidder(spec); describe('inherited functions', () => { @@ -92,7 +81,6 @@ describe('BeOp Bid Adapter tests', () => { bidRequests.push(validBid); it('should build the request', function () { - config.setConfig({'currency': {'adServerCurrency': 'USD'}}); const request = spec.buildRequests(bidRequests, {}); const payload = JSON.parse(request.data); const url = request.url; @@ -101,7 +89,6 @@ describe('BeOp Bid Adapter tests', () => { expect(payload.pid).to.equal('5a8af500c9e77c00017e4cad'); expect(payload.slts[0].name).to.exist; expect(payload.slts[0].name).to.equal('bellow-article'); - expect(payload.slts[0].flr).to.equal(10); }); it('should call the endpoint with GDPR consent and pageURL info if found', function () { @@ -124,7 +111,7 @@ describe('BeOp Bid Adapter tests', () => { expect(payload.tc_string).to.exist; expect(payload.tc_string).to.equal('BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='); expect(payload.url).to.exist; - expect(payload.url).to.equal('http://localhost:9876/context.html'); + expect(payload.url).to.equal('http://test.te'); }); }); diff --git a/test/spec/modules/betweenBidAdapter_spec.js b/test/spec/modules/betweenBidAdapter_spec.js index 3baa92e35d5..44d0752d4b2 100644 --- a/test/spec/modules/betweenBidAdapter_spec.js +++ b/test/spec/modules/betweenBidAdapter_spec.js @@ -23,32 +23,6 @@ describe('betweenBidAdapterTests', function () { let req_data = JSON.parse(request.data)[0].data; expect(req_data.bidid).to.equal('bid1234'); }); - - it('validate_video_params', function () { - let bidRequestData = [{ - bidId: 'bid1234', - bidder: 'between', - params: {w: 240, h: 400, s: 1112}, - mediaTypes: { - video: { - context: 'outstream', - playerSize: [970, 250], - maxd: 123, - mind: 234, - codeType: 'unknown code type' - } - }, - }]; - let request = spec.buildRequests(bidRequestData); - let req_data = JSON.parse(request.data)[0].data; - - expect(req_data.mediaType).to.equal(2); - expect(req_data.maxd).to.equal(123); - expect(req_data.mind).to.equal(234); - expect(req_data.pos).to.equal('atf'); - expect(req_data.codeType).to.equal('inpage'); - }); - it('validate itu param', function() { let bidRequestData = [{ bidId: 'bid1234', @@ -103,54 +77,6 @@ describe('betweenBidAdapterTests', function () { expect(req_data.subid).to.equal(1138); }); - - it('validate eids parameter', function() { - const USER_ID_DATA = [ - { - source: 'admixer.net', - uids: [ - { id: '5706411dc1c54268ac2ed668b27f92a3', atype: 3 } - ] - } - ]; - - let bidRequestData = [{ - bidId: 'bid1234', - bidder: 'between', - params: { - w: 240, - h: 400, - s: 1112, - }, - sizes: [[240, 400]], - userIdAsEids: USER_ID_DATA, - }]; - - let request = spec.buildRequests(bidRequestData); - let req_data = JSON.parse(request.data)[0].data; - - expect(req_data.eids).to.have.deep.members(USER_ID_DATA); - }); - - it('validate eids parameter, if userIdAsEids = undefined', function() { - let bidRequestData = [{ - bidId: 'bid1234', - bidder: 'between', - params: { - w: 240, - h: 400, - s: 1112, - }, - sizes: [[240, 400]], - userIdAsEids: undefined - }]; - - let request = spec.buildRequests(bidRequestData); - let req_data = JSON.parse(request.data)[0].data; - - expect(req_data.eids).to.have.deep.members([]); - }); - it('validate click3rd param', function() { let bidRequestData = [{ bidId: 'bid1234', @@ -256,21 +182,6 @@ describe('betweenBidAdapterTests', function () { expect(bid.requestId).to.equal('bid1234'); expect(bid.ad).to.equal('Ad html'); }); - - it('validate_response_video_params', function () { - let serverResponse = { - body: [{ - mediaType: 2, - vastXml: 'vastXml', - }] - }; - let bids = spec.interpretResponse(serverResponse); - expect(bids).to.have.lengthOf(1); - let bid = bids[0]; - expect(bid.mediaType).to.equal(2); - expect(bid.vastXml).to.equal('vastXml'); - }); - it('validate response params without currency', function () { let serverResponse = { body: [{ @@ -283,13 +194,12 @@ describe('betweenBidAdapterTests', function () { let bids = spec.interpretResponse(serverResponse); expect(bids).to.have.lengthOf(1); let bid = bids[0]; - expect(bid.currency).to.equal('USD'); + expect(bid.currency).to.equal('RUB'); }); it('check getUserSyncs', function() { const syncs = spec.getUserSyncs({}, {}); - expect(syncs).to.be.an('array').that.to.have.lengthOf(2); + expect(syncs).to.be.an('array').that.to.have.lengthOf(1); expect(syncs[0]).to.deep.equal({type: 'iframe', url: 'https://ads.betweendigital.com/sspmatch-iframe'}); - expect(syncs[1]).to.deep.equal({type: 'image', url: 'https://ads.betweendigital.com/sspmatch'}); }); it('check sizes', function() { @@ -312,6 +222,53 @@ describe('betweenBidAdapterTests', function () { expect(req_data.sizes).to.deep.equal(['970x250', '240x400', '728x90']) }); + it('check sharedId with id and third', function() { + const bidRequestData = [{ + bidId: 'bid123', + bidder: 'between', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + params: { + s: 1112, + }, + userId: { + sharedid: { + id: '01EXQE7JKNDRDDVATB0S2GX1NT', + third: '01EXQE7JKNDRDDVATB0S2GX1NT' + } + } + }]; + const shid = JSON.parse(spec.buildRequests(bidRequestData).data)[0].data.shid; + const shid3 = JSON.parse(spec.buildRequests(bidRequestData).data)[0].data.shid3; + expect(shid).to.equal('01EXQE7JKNDRDDVATB0S2GX1NT') && expect(shid3).to.equal('01EXQE7JKNDRDDVATB0S2GX1NT'); + }); + + it('check sharedId with only id', function() { + const bidRequestData = [{ + bidId: 'bid123', + bidder: 'between', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + params: { + s: 1112, + }, + userId: { + sharedid: { + id: '01EXQE7JKNDRDDVATB0S2GX1NT', + } + } + }]; + const shid = JSON.parse(spec.buildRequests(bidRequestData).data)[0].data.shid; + const shid3 = JSON.parse(spec.buildRequests(bidRequestData).data)[0].data.shid3; + expect(shid).to.equal('01EXQE7JKNDRDDVATB0S2GX1NT') && expect(shid3).to.equal(''); + }); + it('check adomain', function() { const serverResponse = { body: [{ diff --git a/test/spec/modules/bidViewabilityIO_spec.js b/test/spec/modules/bidViewabilityIO_spec.js index 5b4944082bc..b59dbc867c1 100644 --- a/test/spec/modules/bidViewabilityIO_spec.js +++ b/test/spec/modules/bidViewabilityIO_spec.js @@ -3,7 +3,7 @@ import * as events from 'src/events.js'; import * as utils from 'src/utils.js'; import * as sinon from 'sinon'; import { expect } from 'chai'; -import CONSTANTS from 'src/constants.json'; +import { EVENTS } from 'src/constants.json'; describe('#bidViewabilityIO', function() { const makeElement = (id) => { @@ -97,7 +97,7 @@ describe('#bidViewabilityIO', function() { expect(mockObserver.unobserve.calledOnce).to.be.true; expect(emitSpy.calledOnce).to.be.true; // expect(emitSpy.firstCall.args).to.be.false; - expect(emitSpy.firstCall.args[0]).to.eq(CONSTANTS.EVENTS.BID_VIEWABLE); + expect(emitSpy.firstCall.args[0]).to.eq(EVENTS.BID_VIEWABLE); }); }) diff --git a/test/spec/modules/bidViewability_spec.js b/test/spec/modules/bidViewability_spec.js index a822d86f852..211dec090a5 100644 --- a/test/spec/modules/bidViewability_spec.js +++ b/test/spec/modules/bidViewability_spec.js @@ -5,7 +5,7 @@ import * as utils from 'src/utils.js'; import * as sinon from 'sinon'; import {expect, spy} from 'chai'; import * as prebidGlobal from 'src/prebidGlobal.js'; -import CONSTANTS from 'src/constants.json'; +import { EVENTS } from 'src/constants.json'; import adapterManager, { gdprDataHandler, uspDataHandler } from 'src/adapterManager.js'; import parse from 'url-parse'; @@ -279,9 +279,9 @@ describe('#bidViewability', function() { let call = callBidViewableBidderSpy.getCall(0); expect(call.args[0]).to.equal(PBJS_WINNING_BID.bidder); expect(call.args[1]).to.deep.equal(PBJS_WINNING_BID); - // CONSTANTS.EVENTS.BID_VIEWABLE is triggered + // EVENTS.BID_VIEWABLE is triggered call = eventsEmitSpy.getCall(0); - expect(call.args[0]).to.equal(CONSTANTS.EVENTS.BID_VIEWABLE); + expect(call.args[0]).to.equal(EVENTS.BID_VIEWABLE); expect(call.args[1]).to.deep.equal(PBJS_WINNING_BID); }); @@ -290,7 +290,7 @@ describe('#bidViewability', function() { expect(triggerPixelSpy.callCount).to.equal(0); // adapterManager.callBidViewableBidder is NOT called expect(callBidViewableBidderSpy.callCount).to.equal(0); - // CONSTANTS.EVENTS.BID_VIEWABLE is NOT triggered + // EVENTS.BID_VIEWABLE is NOT triggered expect(eventsEmitSpy.callCount).to.equal(0); }); }); diff --git a/test/spec/modules/biddoBidAdapter_spec.js b/test/spec/modules/biddoBidAdapter_spec.js deleted file mode 100644 index 25986b3407f..00000000000 --- a/test/spec/modules/biddoBidAdapter_spec.js +++ /dev/null @@ -1,172 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/biddoBidAdapter.js'; - -describe('biddo bid adapter tests', function () { - describe('bid requests', function () { - it('should accept valid bid', function () { - const validBid = { - bidder: 'biddo', - params: {zoneId: 123}, - }; - - expect(spec.isBidRequestValid(validBid)).to.equal(true); - }); - - it('should reject invalid bid', function () { - const invalidBid = { - bidder: 'biddo', - params: {}, - }; - - expect(spec.isBidRequestValid(invalidBid)).to.equal(false); - }); - - it('should correctly build payload string', function () { - const bidRequests = [{ - bidder: 'biddo', - params: {zoneId: 123}, - mediaTypes: { - banner: { - sizes: [[300, 250]], - }, - }, - bidId: '23acc48ad47af5', - auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', - bidderRequestId: '1c56ad30b9b8ca8', - transactionId: '92489f71-1bf2-49a0-adf9-000cea934729', - }]; - const payload = spec.buildRequests(bidRequests)[0].data; - - expect(payload).to.contain('ctype=div'); - expect(payload).to.contain('pzoneid=123'); - expect(payload).to.contain('width=300'); - expect(payload).to.contain('height=250'); - }); - - it('should support multiple bids', function () { - const bidRequests = [{ - bidder: 'biddo', - params: {zoneId: 123}, - mediaTypes: { - banner: { - sizes: [[300, 250]], - }, - }, - bidId: '23acc48ad47af5', - auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', - bidderRequestId: '1c56ad30b9b8ca8', - transactionId: '92489f71-1bf2-49a0-adf9-000cea934729', - }, { - bidder: 'biddo', - params: {zoneId: 321}, - mediaTypes: { - banner: { - sizes: [[728, 90]], - }, - }, - bidId: '23acc48ad47af52', - auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba992', - bidderRequestId: '1c56ad30b9b8ca82', - transactionId: '92489f71-1bf2-49a0-adf9-000cea9347292', - }]; - const payload = spec.buildRequests(bidRequests); - - expect(payload).to.be.lengthOf(2); - }); - - it('should support multiple sizes', function () { - const bidRequests = [{ - bidder: 'biddo', - params: {zoneId: 123}, - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]], - }, - }, - bidId: '23acc48ad47af5', - auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', - bidderRequestId: '1c56ad30b9b8ca8', - transactionId: '92489f71-1bf2-49a0-adf9-000cea934729', - }]; - const payload = spec.buildRequests(bidRequests); - - expect(payload).to.be.lengthOf(2); - }); - }); - - describe('bid responses', function () { - it('should return complete bid response', function () { - const serverResponse = { - body: { - banner: { - hash: '1c56ad30b9b8ca8', - }, - hb: { - cpm: 0.5, - netRevenue: false, - adomains: ['securepubads.g.doubleclick.net'], - }, - template: { - html: '', - }, - }, - }; - const bidderRequest = { - bidId: '23acc48ad47af5', - params: { - requestedSizes: [300, 250], - }, - }; - - const bids = spec.interpretResponse(serverResponse, {bidderRequest}); - - expect(bids).to.be.lengthOf(1); - expect(bids[0].requestId).to.equal('23acc48ad47af5'); - expect(bids[0].creativeId).to.equal('1c56ad30b9b8ca8'); - expect(bids[0].width).to.equal(300); - expect(bids[0].height).to.equal(250); - expect(bids[0].ttl).to.equal(600); - expect(bids[0].cpm).to.equal(0.5); - expect(bids[0].netRevenue).to.equal(false); - expect(bids[0].currency).to.equal('USD'); - expect(bids[0].meta.advertiserDomains).to.be.lengthOf(1); - expect(bids[0].meta.advertiserDomains[0]).to.equal('securepubads.g.doubleclick.net'); - }); - - it('should return empty bid response', function () { - const serverResponse = { - body: {}, - }; - const bidderRequest = { - bidId: '23acc48ad47af5', - params: { - requestedSizes: [300, 250], - }, - }; - - const bids = spec.interpretResponse(serverResponse, {bidderRequest}); - - expect(bids).to.be.lengthOf(0); - }); - - it('should return empty bid response 2', function () { - const serverResponse = { - body: { - template: { - html: '', - } - }, - }; - const bidderRequest = { - bidId: '23acc48ad47af5', - params: { - requestedSizes: [300, 250], - }, - }; - - const bids = spec.interpretResponse(serverResponse, {bidderRequest}); - - expect(bids).to.be.lengthOf(0); - }); - }); -}); diff --git a/test/spec/modules/bidwatchAnalyticsAdapter_spec.js b/test/spec/modules/bidwatchAnalyticsAdapter_spec.js deleted file mode 100644 index 1a322d131a9..00000000000 --- a/test/spec/modules/bidwatchAnalyticsAdapter_spec.js +++ /dev/null @@ -1,288 +0,0 @@ -import bidwatchAnalytics from 'modules/bidwatchAnalyticsAdapter.js'; -import { expect } from 'chai'; -import { server } from 'test/mocks/xhr.js'; -let adapterManager = require('src/adapterManager').default; -let events = require('src/events'); -let constants = require('src/constants.json'); - -describe('BidWatch Analytics', function () { - let timestamp = new Date() - 256; - let auctionId = '5018eb39-f900-4370-b71e-3bb5b48d324f'; - let timeout = 1500; - - let bidTimeout = [ - { - 'bidId': '5fe418f2d70364', - 'bidder': 'appnexusAst', - 'adUnitCode': 'tag_200124_banner', - 'auctionId': '1e8b993d-8f0a-4232-83eb-3639ddf3a44b' - } - ]; - - const auctionEnd = { - 'auctionId': '1e8b993d-8f0a-4232-83eb-3639ddf3a44b', - 'timestamp': 1647424261187, - 'auctionEnd': 1647424261714, - 'auctionStatus': 'completed', - 'adUnits': [ - { - 'code': 'tag_200124_banner', - 'mediaTypes': { - 'banner': { - 'sizes': [ - [ - 300, - 600 - ] - ] - } - }, - 'bids': [ - { - 'bidder': 'appnexus', - 'params': { - 'placementId': 123456 - } - }, - { - 'bidder': 'appnexusAst', - 'params': { - 'placementId': 234567 - } - } - ], - 'sizes': [ - [ - 300, - 600 - ] - ], - 'transactionId': 'de664ccb-e18b-4436-aeb0-362382eb1b40' - } - ], - 'adUnitCodes': [ - 'tag_200124_banner' - ], - 'bidderRequests': [ - { - 'bidderCode': 'appnexus', - 'auctionId': '1e8b993d-8f0a-4232-83eb-3639ddf3a44b', - 'bidderRequestId': '11dc6ff6378de7', - 'bids': [ - { - 'bidder': 'appnexus', - 'params': { - 'placementId': 123456 - }, - 'mediaTypes': { - 'banner': { - 'sizes': [ - [ - 300, - 600 - ] - ] - } - }, - 'adUnitCode': 'tag_200124_banner', - 'transactionId': 'de664ccb-e18b-4436-aeb0-362382eb1b40', - 'sizes': [ - [ - 300, - 600 - ] - ], - 'bidId': '34a63e5d5378a3', - 'bidderRequestId': '11dc6ff6378de7', - 'auctionId': '1e8b993d-8f0a-4232-83eb-3639ddf3a44b', - 'src': 'client', - 'bidRequestsCount': 1, - 'bidderRequestsCount': 1, - 'bidderWinsCount': 0 - } - ], - 'auctionStart': 1647424261187, - 'timeout': 1000, - 'gdprConsent': { - 'consentString': 'CONSENT', - 'gdprApplies': true, - 'apiVersion': 2 - }, - 'start': 1647424261189 - }, - ], - 'noBids': [ - { - 'bidder': 'appnexusAst', - 'params': { - 'placementId': 10471298 - }, - 'mediaTypes': { - 'banner': { - 'sizes': [ - [ - 300, - 600 - ] - ] - } - }, - 'adUnitCode': 'tag_200124_banner', - 'transactionId': 'de664ccb-e18b-4436-aeb0-362382eb1b40', - 'sizes': [ - [ - 300, - 600 - ] - ], - 'bidId': '5fe418f2d70364', - 'bidderRequestId': '4229a45ab8ea87', - 'auctionId': '1e8b993d-8f0a-4232-83eb-3639ddf3a44b', - 'src': 'client', - 'bidRequestsCount': 1, - 'bidderRequestsCount': 1, - 'bidderWinsCount': 0 - } - ], - 'bidsReceived': [ - { - 'bidderCode': 'appnexus', - 'width': 300, - 'height': 600, - 'statusMessage': 'Bid available', - 'adId': '7a4ced80f33d33', - 'requestId': '34a63e5d5378a3', - 'transactionId': 'de664ccb-e18b-4436-aeb0-362382eb1b40', - 'auctionId': '1e8b993d-8f0a-4232-83eb-3639ddf3a44b', - 'mediaType': 'banner', - 'source': 'client', - 'cpm': 27.4276, - 'creativeId': '158534630', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 2000, - 'ad': 'some html', - 'meta': { - 'advertiserDomains': [ - 'example.com' - ] - }, - 'originalCpm': 25.02521, - 'originalCurrency': 'EUR', - 'responseTimestamp': 1647424261559, - 'requestTimestamp': 1647424261189, - 'bidder': 'appnexus', - 'adUnitCode': 'tag_200124_banner', - 'timeToRespond': 370, - 'pbLg': '5.00', - 'pbMg': '20.00', - 'pbHg': '20.00', - 'pbAg': '20.00', - 'pbDg': '20.00', - 'pbCg': '20.000000', - 'size': '300x600', - 'adserverTargeting': { - 'hb_bidder': 'appnexus', - 'hb_adid': '7a4ced80f33d33', - 'hb_pb': '20.000000', - 'hb_size': '300x600', - 'hb_source': 'client', - 'hb_format': 'banner', - 'hb_adomain': 'example.com' - } - } - ], - 'winningBids': [ - - ], - 'timeout': 1000 - }; - - let bidWon = { - 'bidderCode': 'appnexus', - 'width': 970, - 'height': 250, - 'statusMessage': 'Bid available', - 'adId': '65d16ef039a97a', - 'requestId': '2bd3e8ff8a113f', - 'transactionId': '8b2a8629-d1ea-4bb1-aff0-e335b96dd002', - 'auctionId': '1e8b993d-8f0a-4232-83eb-3639ddf3a44b', - 'mediaType': 'banner', - 'source': 'client', - 'cpm': 27.4276, - 'creativeId': '158533702', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 2000, - 'ad': 'some html', - 'meta': { - 'advertiserDomains': [ - 'example.com' - ] - }, - 'originalCpm': 25.02521, - 'originalCurrency': 'EUR', - 'responseTimestamp': 1647424261558, - 'requestTimestamp': 1647424261189, - 'bidder': 'appnexus', - 'adUnitCode': 'tag_200123_banner', - 'timeToRespond': 369, - 'originalBidder': 'appnexus', - 'pbLg': '5.00', - 'pbMg': '20.00', - 'pbHg': '20.00', - 'pbAg': '20.00', - 'pbDg': '20.00', - 'pbCg': '20.000000', - 'size': '970x250', - 'adserverTargeting': { - 'hb_bidder': 'appnexus', - 'hb_adid': '65d16ef039a97a', - 'hb_pb': '20.000000', - 'hb_size': '970x250', - 'hb_source': 'client', - 'hb_format': 'banner', - 'hb_adomain': 'example.com' - }, - 'status': 'rendered', - 'params': [ - { - 'placementId': 123456 - } - ] - }; - - after(function () { - bidwatchAnalytics.disableAnalytics(); - }); - - describe('main test flow', function () { - beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); - }); - - afterEach(function () { - events.getEvents.restore(); - }); - - it('should catch events of interest', function () { - sinon.spy(bidwatchAnalytics, 'track'); - - adapterManager.registerAnalyticsAdapter({ - code: 'bidwatch', - adapter: bidwatchAnalytics - }); - - adapterManager.enableAnalytics({ - provider: 'bidwatch', - options: { - domain: 'test' - } - }); - events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeout); - events.emit(constants.EVENTS.AUCTION_END, auctionEnd); - events.emit(constants.EVENTS.BID_WON, bidWon); - sinon.assert.callCount(bidwatchAnalytics.track, 3); - }); - }); -}); diff --git a/test/spec/modules/big-richmediaBidAdapter_spec.js b/test/spec/modules/big-richmediaBidAdapter_spec.js deleted file mode 100644 index 1e97e1ac1d7..00000000000 --- a/test/spec/modules/big-richmediaBidAdapter_spec.js +++ /dev/null @@ -1,310 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/big-richmediaBidAdapter.js'; -import { auctionManager } from 'src/auctionManager.js'; -import * as bidderFactory from 'src/adapters/bidderFactory.js'; -import { config } from 'src/config.js'; -import { deepClone } from 'src/utils.js'; - -describe('bigRichMediaAdapterTests', function () { - before(function () { - config.setConfig({ - bigRichmedia: { - publisherId: '123ABC' - } - }); - }); - - after(function () { - config.resetConfig(); - }); - - describe('bidRequestValidity', function () { - const bid = { - 'bidder': 'bigRichmedia', - 'params': { - 'placementId': '10433394' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }; - - it('bidRequest with zoneId and deliveryUrl params', function () { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('bidRequest with no params is not valid', function () { - const localBid = Object.assign({}, bid); - localBid.params = {}; - expect(spec.isBidRequestValid(localBid)).to.equal(false); - }); - }); - - describe('bidRequest', function () { - let getAdUnitsStub; - const bidRequests = [ - { - 'bidder': 'bigRichmedia', - 'params': { - 'placementId': '10433394' - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250], [300, 600], [1800, 1000]] - } - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600], [1800, 1000]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'transactionId': '04f2659e-c005-4eb1-a57c-fa93145e3843' - } - ]; - - beforeEach(function() { - getAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits').callsFake(function() { - return []; - }); - }); - - afterEach(function() { - getAdUnitsStub.restore(); - }); - - it('should have skin size', function () { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - format: 'skin' - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].sizes).to.exist; - expect(payload.tags[0].sizes).to.have.lengthOf(3); - }); - - it('should build video bid request', function() { - const bidRequest = deepClone(bidRequests[0]); - bidRequest.params = { - placementId: '1234235', - video: { - skippable: true, - playback_method: ['auto_play_sound_off', 'auto_play_sound_unknown'], - context: 'outstream', - format: 'sticky-top' - } - }; - bidRequest.mediaTypes = { - video: { - playerSize: [640, 480], - context: 'outstream', - mimes: ['video/mp4'], - skip: 0, - minduration: 5, - api: [1, 5, 6], - playbackmethod: [2, 4] - } - }; - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].video).to.deep.equal({ - minduration: 5, - playback_method: 2, - skippable: true, - context: 4 - }); - expect(payload.tags[0].video_frameworks).to.deep.equal([1, 4]) - }); - }); - - describe('interpretResponse', function () { - let bfStub; - - before(function() { - bfStub = sinon.stub(bidderFactory, 'getIabSubCategory'); - }); - - after(function() { - bfStub.restore(); - }); - - const response = { - 'version': '3.0.0', - 'tags': [ - { - 'uuid': '3db3773286ee59', - 'tag_id': 10433394, - 'auction_id': '4534722592064951574', - 'nobid': false, - 'no_ad_url': 'https://lax1-ib.adnxs.com/no-ad', - 'timeout_ms': 10000, - 'ad_profile_id': 27079, - 'ads': [ - { - 'content_source': 'rtb', - 'ad_type': 'banner', - 'buyer_member_id': 958, - 'creative_id': 29681110, - 'media_type_id': 1, - 'media_subtype_id': 1, - 'cpm': 0.5, - 'cpm_publisher_currency': 0.5, - 'publisher_currency_code': '$', - 'client_initiated_ad_counting': true, - 'viewability': { - 'config': '' - }, - 'rtb': { - 'banner': { - 'content': '', - 'width': 300, - 'height': 250 - }, - 'trackers': [ - { - 'impression_urls': [ - 'https://lax1-ib.adnxs.com/impression', - 'https://www.test.com/tracker' - ], - 'video_events': {} - } - ] - } - } - ] - } - ] - }; - - it('should get correct bid response', function () { - const expectedResponse = [ - { - 'requestId': '3db3773286ee59', - 'cpm': 0.5, - 'creativeId': 29681110, - 'dealId': undefined, - 'width': 300, - 'height': 250, - 'ad': '', - 'mediaType': 'banner', - 'currency': 'USD', - 'ttl': 300, - 'netRevenue': true, - 'adUnitCode': 'code', - 'appnexus': { - 'buyerMemberId': 958 - }, - 'meta': { - 'dchain': { - 'ver': '1.0', - 'complete': 0, - 'nodes': [{ - 'bsid': '958' - }] - } - } - } - ]; - const bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code' - }] - }; - const result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); - }); - - it('handles outstream video responses', function () { - const response = { - 'tags': [{ - 'uuid': '84ab500420319d', - 'ads': [{ - 'ad_type': 'video', - 'cpm': 0.500000, - 'notify_url': 'imptracker.com', - 'rtb': { - 'video': { - 'content': '' - } - }, - 'javascriptTrackers': '' - }] - }] - }; - const bidderRequest = { - bids: [{ - bidId: '84ab500420319d', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'outstream' - } - } - }] - } - - const result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(result[0]).not.to.have.property('vastXml'); - expect(result[0]).not.to.have.property('vastUrl'); - expect(result[0]).to.have.property('width', 1); - expect(result[0]).to.have.property('height', 1); - expect(result[0]).to.have.property('mediaType', 'banner'); - }); - }); - - describe('getUserSyncs', function() { - const syncOptions = { - syncEnabled: false - }; - - it('should not return sync', function() { - const serverResponse = [{ body: '' }]; - const result = spec.getUserSyncs(syncOptions, serverResponse); - expect(result).to.be.undefined; - }); - }); - - describe('transformBidParams', function() { - it('cast placementId to number', function() { - const adUnit = { - code: 'adunit-code', - params: { - placementId: '456' - } - }; - const bid = { - params: { - placementId: '456' - }, - sizes: [[300, 250]], - mediaTypes: { - banner: { sizes: [[300, 250]] } - } - }; - - const params = spec.transformBidParams({ placementId: '456' }, true, adUnit, [{ bidderCode: 'bigRichmedia', auctionId: bid.auctionId, bids: [bid] }]); - - expect(params.placement_id).to.exist; - expect(params.placement_id).to.be.a('number'); - }); - }); - - describe('onBidWon', function() { - it('Should not have any error', function() { - const result = spec.onBidWon({}); - expect(true).to.be.true; - }); - }); -}); diff --git a/test/spec/modules/bizzclickBidAdapter_spec.js b/test/spec/modules/bizzclickBidAdapter_spec.js index f80051b0a50..500f45e0573 100644 --- a/test/spec/modules/bizzclickBidAdapter_spec.js +++ b/test/spec/modules/bizzclickBidAdapter_spec.js @@ -48,17 +48,6 @@ const BANNER_BID_REQUEST = { sizes: [[300, 250], [300, 600]] } }, - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '164', - hp: 1 - } - ] - }, bidder: 'bizzclick', params: { placementId: 'hash', @@ -263,11 +252,6 @@ describe('BizzclickAdapter', function() { expect(request.data[0].regs.ext.us_privacy).to.equal(BANNER_BID_REQUEST.uspConsent); }) - it('check schain is set properly', function() { - expect(request.data[0].source.ext.schain.complete).to.equal(1); - expect(request.data[0].source.ext.schain.ver).to.equal('1.0'); - }) - it('Returns valid URL', function () { expect(request.url).to.equal('https://us-e-node1.bizzclick.com/bid?rtb_seat_id=prebidjs&secret_key=accountId'); }); diff --git a/test/spec/modules/bliinkBidAdapter_spec.js b/test/spec/modules/bliinkBidAdapter_spec.js deleted file mode 100644 index 729605f7db8..00000000000 --- a/test/spec/modules/bliinkBidAdapter_spec.js +++ /dev/null @@ -1,612 +0,0 @@ -import { expect } from 'chai' -import { spec, buildBid, BLIINK_ENDPOINT_ENGINE, parseXML, getMetaList } from 'modules/bliinkBidAdapter.js' - -/** - * @description Mockup bidRequest - * @return {{ - * bidderWinsCount: number, - * adUnitCode: string, - * bidder: string, - * src: string, - * bidRequestsCount: number, - * params: {tagId: string, placement: string}, - * bidId: string, - * transactionId: string, - * auctionId: string, - * bidderRequestId: string, - * bidderRequestsCount: number, - * mediaTypes: {banner: {sizes: number[][]}}, - * sizes: number[][], - * crumbs: {pubcid: string}, - * ortb2Imp: {ext: {data: {pbadslot: string}}}}} - */ -const getConfigBid = (placement) => { - return { - adUnitCode: '/19968336/test', - auctionId: '6752b51c-dcd4-4001-85dc-885ab5c504cf', - bidId: '2def0c5b2a7f6e', - bidRequestsCount: 1, - bidder: 'bliink', - bidderRequestId: '1592eb20088b18', - bidderRequestsCount: 1, - bidderWinsCount: 0, - crumbs: { - pubcid: '55ffadc5-051f-428d-8ecc-dc585e0bde0d' - }, - mediaTypes: { - banner: { - sizes: [ - [300, 250] - ] - } - }, - ortb2Imp: { - ext: { - data: { - pbadslot: '/19968336/test' - } - } - }, - params: { - placement: placement, - tagId: '14f30eca-85d2-11e8-9eed-0242ac120007' - }, - sizes: [ - [300, 250] - ], - src: 'client', - transactionId: 'cc6678c4-9746-4082-b9e2-d8065d078ebf' - } -} - -/** - * @description Mockup response from engine.bliink.io/xxxx - * @return { - * { - * viewability_percent_in_view: number, - * viewability_duration: number, - * ad_id: number, - * id: number, - * category: number, - * type: number, - * content: { - * creative: { - * adm: string - * } - * } - * } - * } -* } - */ -const getConfigCreative = () => { - return { - ad_id: 5648, - price: 1, - currency: 'EUR', - media_type: 'banner', - category: 1, - id: 2825, - creativeId: 2825, - type: 1, - viewability_duration: 1, - viewability_percent_in_view: 30, - content: { - creative: { - adm: '', - } - } - } -} - -const getConfigCreativeVideo = () => { - return { - ad_id: 5648, - price: 1, - currency: 'EUR', - media_type: 'video', - category: 1, - creativeId: 2825, - content: '' - } -} - -/** - * @description Mockup BuildRequest function - * @return {{bidderRequestId: string, bidderCode: string, bids: {bidderWinsCount: number, adUnitCode: string, bidder: string, src: string, bidRequestsCount: number, params: {tagId: string, placement: string}, bidId: string, transactionId: string, auctionId: string, bidderRequestId: string, bidderRequestsCount: number, mediaTypes: {banner: {sizes: number[][]}}, sizes: number[][], crumbs: {pubcid: string}, ortb2Imp: {ext: {data: {pbadslot: string}}}}[], refererInfo: {referer: string, canonicalUrl: null, isAmp: boolean, reachedTop: boolean, numIframes: number}}} - */ -const getConfigBuildRequest = (placement) => { - let buildRequest = { - bidderRequestId: '164ddfd207e94d', - bidderCode: 'bliink', - bids: [getConfigBid(placement)], - refererInfo: { - canonicalUrl: null, - isAmp: false, - numIframes: 0, - reachedTop: true, - referer: 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html?pbjs_debug=true', - }, - } - - if (!placement) { - return buildRequest - } - - return Object.assign(buildRequest, { - params: { - bids: [getConfigBid(placement)], - placement: placement - }, - }) -} - -/** - * @description Mockup response from API - * @param noAd - * @return {{mode: string, message: string}|{headers: {}, body: {mode: string, creative: {viewability_percent_in_view: number, viewability_duration: number, ad_id: number, adm: string, id: number, category: number, type: number}, token: string}}} - */ -const getConfigInterpretResponse = (noAd = false) => { - if (noAd) { - return { - message: 'invalid tag', - mode: 'no-ad' - } - } - - return { - body: { - creative: getConfigCreative(), - mode: 'ad', - token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MjgxNzA4MzEsImlhdCI6MTYyNzU2NjAzMSwiaXNzIjoiYmxpaW5rIiwiZGF0YSI6eyJ0eXBlIjoiYWQtc2VydmVyIiwidHJhbnNhY3Rpb25JZCI6IjM1YmU1NDNjLTNkZTQtNGQ1Yy04N2NjLWIzYzEyOGZiYzU0MCIsIm5ldHdvcmtJZCI6MjEsInNpdGVJZCI6NTksInRhZ0lkIjo1OSwiY29va2llSWQiOiJjNGU4MWVhOS1jMjhmLTQwZDItODY1ZC1hNjQzZjE1OTcyZjUiLCJldmVudElkIjozLCJ0YXJnZXRpbmciOnsicGxhdGZvcm0iOiJXZWJzaXRlIiwiaXAiOiI3OC4xMjIuNzUuNzIiLCJ0aW1lIjoxNjI3NTY2MDMxLCJsb2NhdGlvbiI6eyJsYXRpdHVkZSI6NDguOTczOSwibG9uZ2l0dWRlIjozLjMxMTMsInJlZ2lvbiI6IkhERiIsImNvdW50cnkiOiJGUiIsImNpdHkiOiJTYXVsY2hlcnkiLCJ6aXBDb2RlIjoiMDIzMTAiLCJkZXBhcnRtZW50IjoiMDIifSwiY2l0eSI6IlNhdWxjaGVyeSIsImNvdW50cnkiOiJGUiIsImRldmljZU9zIjoibWFjT1MiLCJkZXZpY2VQbGF0Zm9ybSI6IldlYnNpdGUiLCJyYXdVc2VyQWdlbnQiOiJNb3ppbGxhLzUuMCAoTWFjaW50b3NoOyBJbnRlbCBNYWMgT1MgWCAxMF8xNV83KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvOTEuMC40NDcyLjEyNCBTYWZhcmkvNTM3LjM2In0sImdkcHIiOnsiaGFzQ29uc2VudCI6dHJ1ZX0sIndpbiI6ZmFsc2UsImFkSWQiOjU2NDgsImFkdmVydGlzZXJJZCI6MSwiY2FtcGFpZ25JZCI6MSwiY3JlYXRpdmVJZCI6MjgyNSwiZXJyb3IiOmZhbHNlfX0.-UefQH4G0k-RJGemBYffs-KL7EEwma2Wuwgk2xnpij8' - }, - headers: {}, - } -} - -/** - * @description Mockup response from API for RTB creative - * @param noAd - * @return {{body: string} | {mode: string, message: string}} - */ -const getConfigInterpretResponseRTB = (noAd = false) => { - if (noAd) { - return { - message: 'invalid tag', - mode: 'no-ad' - } - } - - return { - body: ` - - - - BLIINK - https://vast.bliink.io/p/508379d0-9f65-4198-8ba5-f61f2b51224f.xml - https://e.api.bliink.io/e?name=vast-error&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzQwMzA1MjcsImlhdCI6MTYzMzQyNTcyNywiaXNzIjoiYmxpaW5rIiwiZGF0YSI6eyJ0eXBlIjoiYWQtc2VydmVyIiwidHJhbnNhY3Rpb25JZCI6ImE2NjJjZGJmLTkzNDYtNDI0MS1iMTU0LTJhOTc2OTg0NjNmOSIsIm5ldHdvcmtJZCI6MjUsInNpdGVJZCI6MTQzLCJ0YWdJZCI6MTI3MSwiY29va2llSWQiOiIwNWFhN2UwMi05MzgzLTQ1NGYtOTJmZC1jOTE2YWNlMmUyZjYiLCJldmVudElkIjozLCJ0YXJnZXRpbmciOnsicGxhdGZvcm0iOiJXZWJzaXRlIiwicmVmZXJyZXIiOiJodHRwOi8vbG9jYWxob3N0OjgxODEvaW50ZWdyYXRpb25FeGFtcGxlcy9ncHQvYmxpaW5rLWluc3RyZWFtLmh0bWwiLCJwYWdlVXJsIjoiaHR0cDovL2xvY2FsaG9zdDo4MTgxL2ludGVncmF0aW9uRXhhbXBsZXMvZ3B0L2JsaWluay1pbnN0cmVhbS5odG1sIiwiaXAiOiIzMS4zOS4xNDEuMTQwIiwidGltZSI6MTYzMzQyNTcyNywibG9jYXRpb24iOnsibGF0aXR1ZGUiOjQ4Ljk0MjIsImxvbmdpdHVkZSI6Mi41MDM5LCJyZWdpb24iOiJJREYiLCJjb3VudHJ5IjoiRlIiLCJjaXR5IjoiQXVsbmF5LXNvdXMtQm9pcyIsInppcENvZGUiOiI5MzYwMCIsImRlcGFydG1lbnQiOiI5MyJ9LCJjaXR5IjoiQXVsbmF5LXNvdXMtQm9pcyIsImNvdW50cnkiOiJGUiIsImRldmljZU9zIjoibWFjT1MiLCJkZXZpY2VQbGF0Zm9ybSI6IldlYnNpdGUiLCJyYXdVc2VyQWdlbnQiOiJNb3ppbGxhLzUuMCAoTWFjaW50b3NoOyBJbnRlbCBNYWMgT1MgWCAxMF8xNV83KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvOTMuMC40NTc3LjYzIFNhZmFyaS81MzcuMzYiLCJjb250ZW50Q2xhc3NpZmljYXRpb24iOnsiYnJhbmRzYWZlIjpmYWxzZX19LCJnZHByIjp7Imhhc0NvbnNlbnQiOnRydWV9LCJ3aW4iOmZhbHNlLCJhZElkIjo1NzkzLCJhZHZlcnRpc2VySWQiOjEsImNhbXBhaWduSWQiOjEsImNyZWF0aXZlSWQiOjExOTQsImVycm9yIjpmYWxzZX19.nJSJPKovg0_jSHtLdrMPDqesAIlFKCuXPXYxpsyWBDw - https://e.api.bliink.io/e?name=impression&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzQwMzA1MjcsImlhdCI6MTYzMzQyNTcyNywiaXNzIjoiYmxpaW5rIiwiZGF0YSI6eyJ0eXBlIjoiYWQtc2VydmVyIiwidHJhbnNhY3Rpb25JZCI6ImE2NjJjZGJmLTkzNDYtNDI0MS1iMTU0LTJhOTc2OTg0NjNmOSIsIm5ldHdvcmtJZCI6MjUsInNpdGVJZCI6MTQzLCJ0YWdJZCI6MTI3MSwiY29va2llSWQiOiIwNWFhN2UwMi05MzgzLTQ1NGYtOTJmZC1jOTE2YWNlMmUyZjYiLCJldmVudElkIjozLCJ0YXJnZXRpbmciOnsicGxhdGZvcm0iOiJXZWJzaXRlIiwicmVmZXJyZXIiOiJodHRwOi8vbG9jYWxob3N0OjgxODEvaW50ZWdyYXRpb25FeGFtcGxlcy9ncHQvYmxpaW5rLWluc3RyZWFtLmh0bWwiLCJwYWdlVXJsIjoiaHR0cDovL2xvY2FsaG9zdDo4MTgxL2ludGVncmF0aW9uRXhhbXBsZXMvZ3B0L2JsaWluay1pbnN0cmVhbS5odG1sIiwiaXAiOiIzMS4zOS4xNDEuMTQwIiwidGltZSI6MTYzMzQyNTcyNywibG9jYXRpb24iOnsibGF0aXR1ZGUiOjQ4Ljk0MjIsImxvbmdpdHVkZSI6Mi41MDM5LCJyZWdpb24iOiJJREYiLCJjb3VudHJ5IjoiRlIiLCJjaXR5IjoiQXVsbmF5LXNvdXMtQm9pcyIsInppcENvZGUiOiI5MzYwMCIsImRlcGFydG1lbnQiOiI5MyJ9LCJjaXR5IjoiQXVsbmF5LXNvdXMtQm9pcyIsImNvdW50cnkiOiJGUiIsImRldmljZU9zIjoibWFjT1MiLCJkZXZpY2VQbGF0Zm9ybSI6IldlYnNpdGUiLCJyYXdVc2VyQWdlbnQiOiJNb3ppbGxhLzUuMCAoTWFjaW50b3NoOyBJbnRlbCBNYWMgT1MgWCAxMF8xNV83KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvOTMuMC40NTc3LjYzIFNhZmFyaS81MzcuMzYiLCJjb250ZW50Q2xhc3NpZmljYXRpb24iOnsiYnJhbmRzYWZlIjpmYWxzZX19LCJnZHByIjp7Imhhc0NvbnNlbnQiOnRydWV9LCJ3aW4iOmZhbHNlLCJhZElkIjo1NzkzLCJhZHZlcnRpc2VySWQiOjEsImNhbXBhaWduSWQiOjEsImNyZWF0aXZlSWQiOjExOTQsImVycm9yIjpmYWxzZX19.nJSJPKovg0_jSHtLdrMPDqesAIlFKCuXPXYxpsyWBDw - 1EUR - - - - ` - } -} - -/** - * - * - * - * @description Below start tests for utils fonctions - * - * - * - */ - -const testsGetMetaList = [ - { - title: 'Should return empty array if there are no parameters', - args: { - fn: getMetaList() - }, - want: [] - }, - { - title: 'Should return list of metas with name associated', - args: { - fn: getMetaList('test'), - }, - want: [ - { - key: 'name', - value: 'test', - }, - { - key: 'name*', - value: 'test', - }, - { - key: 'itemprop*', - value: 'test', - }, - { - key: 'property', - value: `'og:${'test'}'`, - }, - { - key: 'property', - value: `'twitter:${'test'}'`, - }, - { - key: 'property', - value: `'article:${'test'}'`, - }, - ] - } -] - -describe('BLIINK Adapter getMetaList', function() { - for (const test of testsGetMetaList) { - it(test.title, () => { - const res = test.args.fn - expect(res).to.eql(test.want) - }) - } -}) - -/** - * @description Array of tests used in describe function below - * @type {[{args: {fn: (string|Document)}, want: string, title: string}, {args: {fn: (string|Document)}, want: string, title: string}]} - */ -const testsParseXML = [ - { - title: 'Should return null, if content length equal to 0', - args: { - fn: parseXML('') - }, - want: null, - }, - { - title: 'Should return null, if content isnt string', - args: { - fn: parseXML({}) - }, - want: null, - }, -] - -describe('BLIINK Adapter parseXML', function() { - for (const test of testsParseXML) { - it(test.title, () => { - const res = test.args.fn - expect(res).to.eql(test.want) - }) - } -}) - -/** - * - * - * - * @description End tests for utils fonctions - * - * - * - */ - -/** - * @description Array of tests used in describe function below - * @type {[{args: {fn}, want: boolean, title: string}, {args: {fn}, want: boolean, title: string}, {args: {fn}, want: boolean, title: string}]} - */ -const testsIsBidRequestValid = [ - { - title: 'isBidRequestValid format not valid', - args: { - fn: spec.isBidRequestValid({}) - }, - want: false, - }, - { - title: 'isBidRequestValid does not receive any bid', - args: { - fn: spec.isBidRequestValid() - }, - want: false, - }, - { - title: 'isBidRequestValid Receive a valid bid', - args: { - fn: spec.isBidRequestValid(getConfigBid('banner')) - }, - want: true, - } -] - -describe('BLIINK Adapter isBidRequestValid', function() { - for (const test of testsIsBidRequestValid) { - it(test.title, () => { - const res = test.args.fn - expect(res).to.eql(test.want) - }) - } -}) - -const testsInterpretResponse = [ - { - title: 'Should construct bid for video instream', - args: { - fn: spec.interpretResponse(getConfigInterpretResponseRTB(false), getConfigBuildRequest('video')) - }, - want: { - cpm: 0, - currency: 'EUR', - height: 250, - width: 300, - creativeId: 0, - mediaType: 'video', - netRevenue: false, - requestId: '2def0c5b2a7f6e', - ttl: 3600, - vastXml: getConfigInterpretResponseRTB().body, - } - }, - { - title: 'ServerResponse with message: invalid tag, return empty array', - args: { - fn: spec.interpretResponse(getConfigInterpretResponse(true), getConfigBuildRequest('banner')) - }, - want: [] - }, -] - -describe('BLIINK Adapter interpretResponse', function() { - for (const test of testsInterpretResponse) { - it(test.title, () => { - const res = test.args.fn - - if (res) { - expect(res).to.eql(test.want) - } - }) - } -}) - -/** - * @description Array of tests used in describe function below - * @type {[ - * {args: - * {fn: { - * cpm: number, - * netRevenue: boolean, - * ad, requestId, - * meta: {mediaType}, - * width: number, - * currency: string, - * ttl: number, - * creativeId: number, - * height: number - * } - * }, want, title: string}]} - */ -const testsBuildBid = [ - { - title: 'Should return null if no bid passed in parameters', - args: { - fn: buildBid() - }, - want: null - }, - { - title: 'Input data must respect the output model', - args: { - fn: buildBid({ id: 1, test: '123' }, { id: 2, test: '345' }, false, false) - }, - want: null - }, - { - title: 'input data respect the output model for video', - args: { - fn: buildBid(getConfigBid('video'), getConfigCreativeVideo()) - }, - want: { - requestId: getConfigBid('video').bidId, - cpm: 1, - currency: 'EUR', - mediaType: 'video', - width: 300, - height: 250, - creativeId: getConfigCreativeVideo().creativeId, - netRevenue: false, - vastXml: getConfigCreativeVideo().content, - ttl: 3600, - } - }, - { - title: 'input data respect the output model for banner', - args: { - fn: buildBid(getConfigBid('banner'), getConfigCreative()) - }, - want: { - requestId: getConfigBid('banner').bidId, - cpm: 1, - currency: 'EUR', - mediaType: 'banner', - width: 300, - height: 250, - creativeId: getConfigCreative().id, - ad: getConfigCreative().content.creative.adm, - ttl: 3600, - netRevenue: false, - } - } -] - -describe('BLIINK Adapter buildBid', function() { - for (const test of testsBuildBid) { - it(test.title, () => { - const res = test.args.fn - expect(res).to.eql(test.want) - }) - } -}) - -/** - * @description Array of tests used in describe function below - * @type {[{args: {fn}, want, title: string}]} - */ -const testsBuildRequests = [ - { - title: 'Should not build request, no bidder request exist', - args: { - fn: spec.buildRequests() - }, - want: null - }, - { - title: 'Should build request if bidderRequest exist', - args: { - fn: spec.buildRequests([], getConfigBuildRequest('banner')) - }, - want: { - method: 'GET', - url: `${BLIINK_ENDPOINT_ENGINE}/${getConfigBuildRequest('banner').bids[0].params.tagId}`, - params: { - bidderRequestId: getConfigBuildRequest('banner').bidderRequestId, - bidderCode: getConfigBuildRequest('banner').bidderCode, - bids: getConfigBuildRequest('banner').bids, - refererInfo: getConfigBuildRequest('banner').refererInfo - }, - data: { - gdpr: false, - gdpr_consent: '', - height: 250, - width: 300, - keywords: '', - pageDescription: '', - pageTitle: '', - pageUrl: 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html?pbjs_debug=true', - } - } - }, - { - title: 'Should build request width GDPR configuration', - args: { - fn: spec.buildRequests([], Object.assign(getConfigBuildRequest('banner'), { - gdprConsent: { - gdprApplies: true, - consentString: 'XXXX' - }, - })) - }, - want: { - method: 'GET', - url: `${BLIINK_ENDPOINT_ENGINE}/${getConfigBuildRequest('banner').bids[0].params.tagId}`, - params: { - bidderRequestId: getConfigBuildRequest('banner').bidderRequestId, - bidderCode: getConfigBuildRequest('banner').bidderCode, - bids: getConfigBuildRequest('banner').bids, - refererInfo: getConfigBuildRequest('banner').refererInfo - }, - data: { - gdpr: true, - gdpr_consent: 'XXXX', - pageDescription: '', - pageTitle: '', - keywords: '', - pageUrl: 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html?pbjs_debug=true', - height: 250, - width: 300, - } - } - } -] - -describe('BLIINK Adapter buildRequests', function() { - for (const test of testsBuildRequests) { - it(test.title, () => { - const res = test.args.fn - expect(res).to.eql(test.want) - }) - } -}) - -const getSyncOptions = (pixelEnabled = true, iframeEnabled = 'false') => { - return { - pixelEnabled, - iframeEnabled - } -} - -const getServerResponses = () => { - return [ - { - body: '', - } - ] -} - -const getGdprConsent = () => { - return { - gdprApplies: 1, - consentString: 'XXX' - } -} - -const testsGetUserSyncs = [ - { - title: 'Should not have gdprConsent exist', - args: { - fn: spec.getUserSyncs(getSyncOptions(), getServerResponses(), getGdprConsent()) - }, - want: [ - { - type: 'script', - url: 'https://prg.smartadserver.com/ac?out=js&nwid=3392&siteid=305791&pgname=rg&fmtid=81127&tgt=[sas_target]&visit=m&tmstp=[timestamp]&clcturl=[countgo]' - }, - { - type: 'image', - url: 'https://sync.smartadserver.com/getuid?nwid=3392&consentString=XXX&url=https%3A%2F%2Fcookiesync.api.bliink.io%2Fcookiesync%3Fpartner%3Dsmart%26uid%3D%5Bsas_uid%5D' - }, - { - type: 'image', - url: 'https://ad.360yield.com/server_match?partner_id=1531&consentString=XXX&r=https%3A%2F%2Fcookiesync.api.bliink.io%2Fcookiesync%3Fpartner%3Dazerion%26uid%3D%7BPUB_USER_ID%7D', - }, - { - type: 'image', - url: 'https://ads.stickyadstv.com/auto-user-sync?consentString=XXX', - }, - { - type: 'image', - url: 'https://cookiesync.api.bliink.io/getuid?url=https%3A%2F%2Fvisitor.omnitagjs.com%2Fvisitor%2Fsync%3Fuid%3D1625272249969090bb9d544bd6d8d645%26name%3DBLIINK%26visitor%3D%24UID%26external%3Dtrue&consentString=XXX', - }, - { - type: 'image', - url: 'https://cookiesync.api.bliink.io/getuid?url=https://pixel.advertising.com/ups/58444/sync?&gdpr=1&gdpr_consent=XXX&redir=true&uid=$UID', - }, - { - type: 'image', - url: 'https://ups.analytics.yahoo.com/ups/58499/occ?gdpr=1&gdpr_consent=XXX', - }, - { - type: 'image', - url: 'https://secure.adnxs.com/getuid?https%3A%2F%2Fcookiesync.api.bliink.io%2Fcookiesync%3Fpartner%3Dazerion%26uid%3D%24UID', - }, - ] - }, - { - title: 'Should not have gdpr consent', - args: { - fn: spec.getUserSyncs(getSyncOptions(), getServerResponses()) - }, - want: [] - } -] - -describe('BLIINK Adapter getUserSyncs', function() { - for (const test of testsGetUserSyncs) { - it(test.title, () => { - const res = test.args.fn - expect(res).to.eql(test.want) - }) - } -}) diff --git a/test/spec/modules/brandmetricsRtdProvider_spec.js b/test/spec/modules/brandmetricsRtdProvider_spec.js deleted file mode 100644 index 3cac5a3d559..00000000000 --- a/test/spec/modules/brandmetricsRtdProvider_spec.js +++ /dev/null @@ -1,191 +0,0 @@ -import * as brandmetricsRTD from '../../../modules/brandmetricsRtdProvider.js'; -import {config} from 'src/config.js'; - -const VALID_CONFIG = { - name: 'brandmetrics', - waitForIt: true, - params: { - scriptId: '00000000-0000-0000-0000-000000000000', - bidders: ['ozone'] - } -}; - -const NO_BIDDERS_CONFIG = { - name: 'brandmetrics', - waitForIt: true, - params: { - scriptId: '00000000-0000-0000-0000-000000000000' - } -}; - -const NO_SCRIPTID_CONFIG = { - name: 'brandmetrics', - waitForIt: true -}; - -const USER_CONSENT = { - gdpr: { - vendorData: { - vendor: { - consents: { - 422: true - } - }, - purpose: { - consents: { - 1: true, - 7: true - } - } - }, - gdprApplies: true - } -}; - -const NO_TCF_CONSENT = { - gdpr: { - vendorData: { - vendor: { - consents: { - 422: false - } - }, - purpose: { - consents: { - 1: false, - 7: false - } - } - }, - gdprApplies: true - } -}; - -const NO_USP_CONSENT = { - usp: '1NYY' -}; - -function mockSurveyLoaded(surveyConf) { - const commands = window._brandmetrics || []; - commands.forEach(command => { - if (command.cmd === '_addeventlistener') { - const conf = command.val; - if (conf.event === 'surveyloaded') { - conf.handler(surveyConf); - } - } - }); -} - -function scriptTagExists(url) { - const tags = document.getElementsByTagName('script'); - for (let i = 0; i < tags.length; i++) { - if (tags[i].src === url) { - return true; - } - } - return false; -} - -describe('BrandmetricsRTD module', () => { - beforeEach(function () { - const scriptTags = document.getElementsByTagName('script'); - for (let i = 0; i < scriptTags.length; i++) { - if (scriptTags[i].src.indexOf('brandmetrics') !== -1) { - scriptTags[i].remove(); - } - } - }); - - it('should init and return true', () => { - expect(brandmetricsRTD.brandmetricsSubmodule.init(VALID_CONFIG, USER_CONSENT)).to.equal(true); - }); - - it('should init and return true even if bidders is not included', () => { - expect(brandmetricsRTD.brandmetricsSubmodule.init(NO_BIDDERS_CONFIG, USER_CONSENT)).to.equal(true); - }); - - it('should init even if script- id is not configured', () => { - expect(brandmetricsRTD.brandmetricsSubmodule.init(NO_SCRIPTID_CONFIG, USER_CONSENT)).to.equal(true); - }); - - it('should not init when there is no TCF- consent', () => { - expect(brandmetricsRTD.brandmetricsSubmodule.init(VALID_CONFIG, NO_TCF_CONSENT)).to.equal(false); - }); - - it('should not init when there is no usp- consent', () => { - expect(brandmetricsRTD.brandmetricsSubmodule.init(VALID_CONFIG, NO_USP_CONSENT)).to.equal(false); - }); -}); - -describe('getBidRequestData', () => { - beforeEach(function () { - config.resetConfig() - }) - - it('should set targeting keys for specified bidders', () => { - brandmetricsRTD.brandmetricsSubmodule.getBidRequestData({}, () => { - const bidderConfig = config.getBidderConfig() - const expected = VALID_CONFIG.params.bidders - - expected.forEach(exp => { - expect(bidderConfig[exp].ortb2.user.ext.data.mockTargetKey).to.equal('mockMeasurementId') - }) - }, VALID_CONFIG); - - mockSurveyLoaded({ - available: true, - conf: { - displayOption: { - type: 'pbjs', - targetKey: 'mockTargetKey' - } - }, - survey: { - measurementId: 'mockMeasurementId' - } - }); - }); - - it('should only set targeting keys when the brandmetrics survey- type is "pbjs"', () => { - mockSurveyLoaded({ - available: true, - conf: { - displayOption: { - type: 'dfp', - targetKey: 'mockTargetKey' - } - }, - survey: { - measurementId: 'mockMeasurementId' - } - }); - - brandmetricsRTD.brandmetricsSubmodule.getBidRequestData({}, () => {}, VALID_CONFIG); - const bidderConfig = config.getBidderConfig() - expect(Object.keys(bidderConfig).length).to.equal(0) - }); - - it('should use a default targeting key name if the brandmetrics- configuration does not include one', () => { - mockSurveyLoaded({ - available: true, - conf: { - displayOption: { - type: 'pbjs', - } - }, - survey: { - measurementId: 'mockMeasurementId' - } - }); - - brandmetricsRTD.brandmetricsSubmodule.getBidRequestData({}, () => {}, VALID_CONFIG); - - const bidderConfig = config.getBidderConfig() - const expected = VALID_CONFIG.params.bidders - - expected.forEach(exp => { - expect(bidderConfig[exp].ortb2.user.ext.data.brandmetrics_survey).to.equal('mockMeasurementId') - }) - }); -}); diff --git a/test/spec/modules/browsiRtdProvider_spec.js b/test/spec/modules/browsiRtdProvider_spec.js index c36b48c5105..ee37d16905b 100644 --- a/test/spec/modules/browsiRtdProvider_spec.js +++ b/test/spec/modules/browsiRtdProvider_spec.js @@ -1,8 +1,5 @@ import * as browsiRTD from '../../../modules/browsiRtdProvider.js'; import {makeSlot} from '../integration/faker/googletag.js'; -import * as utils from '../../../src/utils' -import * as events from '../../../src/events'; -import * as sinon from 'sinon'; describe('browsi Real time data sub module', function () { const conf = { @@ -17,28 +14,6 @@ describe('browsi Real time data sub module', function () { } }] }; - const auction = {adUnits: [ - { - code: 'adMock', - transactionId: 1 - }, - { - code: 'hasPrediction', - transactionId: 1 - } - ]}; - - let sandbox; - let eventsEmitSpy; - - before(() => { - sandbox = sinon.sandbox.create(); - eventsEmitSpy = sandbox.spy(events, ['emit']); - }); - - after(() => { - sandbox.restore(); - }); it('should init and return true', function () { browsiRTD.collectData(); @@ -54,11 +29,11 @@ describe('browsi Real time data sub module', function () { }); it('should match placement with ad unit', function () { - const slot = makeSlot({code: '/123/abc', divId: 'browsiAd_1'}); + const slot = makeSlot({code: '/57778053/Browsi_Demo_300x250', divId: 'browsiAd_1'}); - const test1 = browsiRTD.isIdMatchingAdUnit(slot, ['/123/abc']); // true - const test2 = browsiRTD.isIdMatchingAdUnit(slot, ['/123/abc', '/456/def']); // true - const test3 = browsiRTD.isIdMatchingAdUnit(slot, ['/123/def']); // false + const test1 = browsiRTD.isIdMatchingAdUnit(slot, ['/57778053/Browsi_Demo_300x250']); // true + const test2 = browsiRTD.isIdMatchingAdUnit(slot, ['/57778053/Browsi_Demo_300x250', '/57778053/Browsi']); // true + const test3 = browsiRTD.isIdMatchingAdUnit(slot, ['/57778053/Browsi_Demo_Low']); // false const test4 = browsiRTD.isIdMatchingAdUnit(slot, []); // true expect(test1).to.equal(true); @@ -68,12 +43,12 @@ describe('browsi Real time data sub module', function () { }); it('should return correct macro values', function () { - const slot = makeSlot({code: '/123/abc', divId: 'browsiAd_1'}); + const slot = makeSlot({code: '/57778053/Browsi_Demo_300x250', divId: 'browsiAd_1'}); slot.setTargeting('test', ['test', 'value']); // slot getTargeting doesn't act like GPT so we can't expect real value const macroResult = browsiRTD.getMacroId({p: '/'}, slot); - expect(macroResult).to.equal('/123/abc/NA'); + expect(macroResult).to.equal('/57778053/Browsi_Demo_300x250/NA'); const macroResultB = browsiRTD.getMacroId({}, slot); expect(macroResultB).to.equal('browsiAd_1'); @@ -85,151 +60,24 @@ describe('browsi Real time data sub module', function () { describe('should return data to RTD module', function () { it('should return empty if no ad units defined', function () { browsiRTD.setData({}); - expect(browsiRTD.browsiSubmodule.getTargetingData([], null, null, auction)).to.eql({}); + expect(browsiRTD.browsiSubmodule.getTargetingData([])).to.eql({}); }); it('should return NA if no prediction for ad unit', function () { makeSlot({code: 'adMock', divId: 'browsiAd_2'}); browsiRTD.setData({}); - expect(browsiRTD.browsiSubmodule.getTargetingData(['adMock'], null, null, auction)).to.eql({adMock: {bv: 'NA'}}); + expect(browsiRTD.browsiSubmodule.getTargetingData(['adMock'])).to.eql({adMock: {bv: 'NA'}}); }); it('should return prediction from server', function () { makeSlot({code: 'hasPrediction', divId: 'hasPrediction'}); const data = { - p: {'hasPrediction': {ps: {0: 0.234}}}, + p: {'hasPrediction': {p: 0.234}}, kn: 'bv', pmd: undefined }; browsiRTD.setData(data); - expect(browsiRTD.browsiSubmodule.getTargetingData(['hasPrediction'], null, null, auction)).to.eql({hasPrediction: {bv: '0.20'}}); - }) - }) - - describe('should return matching prediction', function () { - const predictions = { - 0: 0.123, - 1: 0.254, - 3: 0, - 4: 0.8 - } - const singlePrediction = { - 0: 0.123 - } - it('should return raw value if valid', function () { - expect(browsiRTD.getCurrentData(predictions, 0)).to.equal(0.123); - expect(browsiRTD.getCurrentData(predictions, 1)).to.equal(0.254); - }) - it('should return 0 for prediction = 0', function () { - expect(browsiRTD.getCurrentData(predictions, 3)).to.equal(0); - }) - it('should return -1 for invalid params', function () { - expect(browsiRTD.getCurrentData(null, 3)).to.equal(-1); - expect(browsiRTD.getCurrentData(predictions, null)).to.equal(-1); - }) - it('should return prediction according to object keys length ', function () { - expect(browsiRTD.getCurrentData(singlePrediction, 0)).to.equal(0.123); - expect(browsiRTD.getCurrentData(singlePrediction, 1)).to.equal(-1); - expect(browsiRTD.getCurrentData(singlePrediction, 2)).to.equal(-1); - expect(browsiRTD.getCurrentData(predictions, 4)).to.equal(0.8); - expect(browsiRTD.getCurrentData(predictions, 5)).to.equal(0.8); - expect(browsiRTD.getCurrentData(predictions, 8)).to.equal(0.8); - }) - }) - describe('should set bid request data', function () { - const data = { - p: { - 'adUnit1': {ps: {0: 0.234}}, - 'adUnit2': {ps: {0: 0.134}}}, - kn: 'bv', - pmd: undefined - }; - browsiRTD.setData(data); - const fakeAdUnits = [ - { - code: 'adUnit1' - }, - { - code: 'adUnit2' - } - ] - browsiRTD.browsiSubmodule.getBidRequestData({adUnits: fakeAdUnits}, () => {}, {}, null); - it('should set ad unit params with prediction values', function () { - expect(utils.deepAccess(fakeAdUnits[0], 'ortb2Imp.ext.data.browsi')).to.eql({bv: '0.20'}); - expect(utils.deepAccess(fakeAdUnits[1], 'ortb2Imp.ext.data.browsi')).to.eql({bv: '0.10'}); - }) - }) - - describe('should emit billable event', function () { - beforeEach(() => { - eventsEmitSpy.resetHistory(); - }) - it('should send one event per ad unit code', function () { - const auction = {adUnits: [ - { - code: 'a', - transactionId: 1 - }, - { - code: 'b', - transactionId: 2 - }, - { - code: 'a', - transactionId: 3 - }, - ]}; - - browsiRTD.browsiSubmodule.getTargetingData(['a', 'b'], null, null, auction); - expect(eventsEmitSpy.callCount).to.equal(2); - }) - it('should send events only for received ad unit codes', function () { - const auction = {adUnits: [ - { - code: 'a', - transactionId: 1 - }, - { - code: 'b', - transactionId: 2 - }, - { - code: 'c', - transactionId: 3 - }, - ]}; - - browsiRTD.browsiSubmodule.getTargetingData(['a'], null, null, auction); - expect(eventsEmitSpy.callCount).to.equal(1); - browsiRTD.browsiSubmodule.getTargetingData(['b'], null, null, auction); - expect(eventsEmitSpy.callCount).to.equal(2); - }) - it('should use 1st transaction ID in case of twin ad unit codes', function () { - const auction = { - auctionId: '123', - adUnits: [ - { - code: 'a', - transactionId: 1 - }, - { - code: 'a', - transactionId: 3 - }, - ]}; - - const expectedCall = { - vendor: 'browsi', - type: 'adRequest', - transactionId: 1, - auctionId: '123' - } - - browsiRTD.browsiSubmodule.getTargetingData(['a'], null, null, auction); - const callArguments = eventsEmitSpy.getCalls()[0].args[1]; - // billing id is random, we can't check its value - delete callArguments['billingId']; - expect(callArguments).to.eql(expectedCall); + expect(browsiRTD.browsiSubmodule.getTargetingData(['hasPrediction'])).to.eql({hasPrediction: {bv: '0.20'}}); }) }) }); diff --git a/test/spec/modules/byDataAnalyticsAdapter_spec.js b/test/spec/modules/byDataAnalyticsAdapter_spec.js deleted file mode 100644 index 90b4e1d53a6..00000000000 --- a/test/spec/modules/byDataAnalyticsAdapter_spec.js +++ /dev/null @@ -1,139 +0,0 @@ -import ascAdapter from 'modules/byDataAnalyticsAdapter'; -import { expect } from 'chai'; -let adapterManager = require('src/adapterManager').default; -let events = require('src/events'); -let constants = require('src/constants.json'); -let auctionId = 'b70ef967-5c5b-4602-831e-f2cf16e59af2'; -const initOptions = { - clientId: 'asc00000', - logFrequency: 1, -}; -let userData = { - userId: '5da77-ec87-277b-8e7a5', - client_id: 'asc00000', - plateform_name: 'Macintosh', - os_version: 10.157, - browser_name: 'Chrome', - browser_version: 92.04515107, - screen_size: { - width: 1440, - height: 900 - }, - device_type: 'Desktop', - time_zone: 'Asia/Calcutta' -}; -let bidTimeoutArgs = [{ - auctionId, - bidId: '12e90cb5ddc5dea', - bidder: 'appnexus', - adUnitCode: 'div-gpt-ad-mrec1' -}]; -let noBidArgs = { - adUnitCode: 'div-gpt-ad-mrec1', - auctionId, - bidId: '14480e9832f2d2b', - bidder: 'appnexus', - bidderRequestId: '13b87b6c20d3636', - mediaTypes: {banner: {sizes: [[300, 250], [250, 250]]}}, - sizes: [[300, 250], [250, 250]], - src: 'client', - transactionId: 'c8ee3914-1ee0-4ce6-9126-748d5692188c' -} -let auctionEndArgs = { - adUnitCodes: ['div-gpt-ad-mrec1'], - adUnits: [{ - code: 'div-gpt-ad-mrec1', - mediaTypes: {banner: {sizes: [[300, 250], [250, 250]]}}, - sizes: [[300, 250], [250, 250]], - bids: [{bidder: 'appnexus', params: {placementId: '19305195'}}], - transactionId: 'c8ee3914-1ee0-4ce6-9126-748d5692188c' - }], - auctionEnd: 1627973487504, - auctionId, - auctionStatus: 'completed', - timestamp: 1627973484504, - bidsReceived: [], - bidderRequests: [{ - auctionId, - auctionStart: 1627973484504, - bidderCode: 'appnexus', - bidderRequestId: '13b87b6c20d3636', - bids: [ - { - adUnitCode: 'div-gpt-ad-mrec1', - auctionId, - bidId: '14480e9832f2d2b', - bidder: 'appnexus', - bidderRequestId: '13b87b6c20d3636', - src: 'client', - mediaTypes: {banner: {sizes: [[300, 250], [250, 250]]}}, - sizes: [[300, 250], [250, 250]], - transactionId: 'c8ee3914-1ee0-4ce6-9126-748d5692188c' - } - ] - }] -} -let expectedDataArgs = { - visitor_data: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1ZGE3Ny1lYzg3LTI3N2ItOGU3YTUiLCJjbGllbnRfaWQiOiJhc2MwMDAwMCIsInBsYXRlZm9ybV9uYW1lIjoiTWFjaW50b3NoIiwib3NfdmVyc2lvbiI6MTAuMTU3LCJicm93c2VyX25hbWUiOiJDaHJvbWUiLCJicm93c2VyX3ZlcnNpb24iOjkyLjA0NTE1MTA3LCJzY3JlZW5fc2l6ZSI6eyJ3aWR0aCI6MTQ0MCwiaGVpZ2h0Ijo5MDB9LCJkZXZpY2VfdHlwZSI6IkRlc2t0b3AiLCJ0aW1lX3pvbmUiOiJBc2lhL0NhbGN1dHRhIn0.jNKjsb3Q-ZjkVMcbss_dQFOmu_GdkGqd7t9MbRmqlG4YEMorcJHhUVmUuPi-9pKvC9_t4XlgjED90UieCvdxCQ', - auction_id: auctionId, - auction_start: 1627973484504, - auctionData: [ { - 'adUnit': 'div-gpt-ad-mrec1', - 'size': '300x250', - 'media_type': 'display', - 'bids_bidder': 'appnexus', - 'bids_bid_id': '14480e9832f2d2b' - }, { - 'adUnit': 'div-gpt-ad-mrec1', - 'size': '250x250', - 'media_type': 'display', - 'bids_bidder': 'appnexus', - 'bids_bid_id': '14480e9832f2d2b' - }] -} - -describe('byData Analytics Adapter ', () => { - beforeEach(() => { - sinon.stub(events, 'getEvents').returns([]); - }); - afterEach(() => { - events.getEvents.restore(); - }); - - describe('enableAnalytics ', function () { - beforeEach(() => { - sinon.spy(ascAdapter, 'track'); - }); - afterEach(() => { - ascAdapter.disableAnalytics(); - ascAdapter.track.restore(); - }); - it('should init with correct options', function () { - ascAdapter.enableAnalytics(initOptions) - // Step 1: Initialize adapter - adapterManager.enableAnalytics({ - provider: 'bydata', - options: initOptions - }); - expect(ascAdapter.initOptions).to.have.property('clientId', 'asc00000'); - expect(ascAdapter.initOptions).to.have.property('logFrequency', 1); - }); - }); - - describe('track-events', function () { - ascAdapter.enableAnalytics(initOptions) - // Step 1: Initialize adapter - adapterManager.enableAnalytics({ - provider: 'bydata', - options: initOptions - }); - it('sends and formatted auction data ', function () { - events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeoutArgs); - events.emit(constants.EVENTS.NO_BID, noBidArgs); - var userToken = ascAdapter.getVisitorData(userData); - var newAuData = ascAdapter.dataProcess(auctionEndArgs); - newAuData['visitor_data'] = userToken; - expect(newAuData).to.deep.equal(expectedDataArgs); - }); - }); -}); diff --git a/test/spec/modules/cleanioRtdProvider_spec.js b/test/spec/modules/cleanioRtdProvider_spec.js deleted file mode 100644 index 47c4b1b4961..00000000000 --- a/test/spec/modules/cleanioRtdProvider_spec.js +++ /dev/null @@ -1,188 +0,0 @@ -import * as utils from '../../../src/utils.js'; -import * as hook from '../../../src/hook.js' - -import { __TEST__ } from '../../../modules/cleanioRtdProvider.js'; - -const { - readConfig, - ConfigError, - pageInitStepPreloadScript, - pageInitStepProtectPage, - bidWrapStepAugmentHtml, - bidWrapStepProtectByWrapping, - beforeInit, -} = __TEST__; - -sinon.assert.expose(chai.assert, { prefix: 'sinon' }); - -const fakeScriptURL = 'https://example.com/script.js'; - -function makeFakeBidResponse() { - return { - ad: 'hello ad', - bidderCode: 'BIDDER', - creativeId: 'CREATIVE', - cpm: 1.23, - }; -} - -describe('clean.io RTD module', function () { - describe('readConfig()', function() { - it('should throw ConfigError on invalid configurations', function() { - expect(() => readConfig({})).to.throw(ConfigError); - expect(() => readConfig({ params: {} })).to.throw(ConfigError); - expect(() => readConfig({ params: { protectionMode: 'bids' } })).to.throw(ConfigError); - expect(() => readConfig({ params: { cdnUrl: 'abc' } })).to.throw(ConfigError); - expect(() => readConfig({ params: { cdnUrl: 'abc', protectionMode: 'bids' } })).to.throw(ConfigError); - expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: '123' } })).to.throw(ConfigError); - }); - - it('should accept valid configurations', function() { - expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'full' } })).to.not.throw(); - expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids' } })).to.not.throw(); - expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids-nowait' } })).to.not.throw(); - }); - }); - - describe('Module initialization step', function() { - let insertElementStub; - beforeEach(function() { - insertElementStub = sinon.stub(utils, 'insertElement'); - }); - afterEach(function() { - utils.insertElement.restore(); - }); - - it('pageInitStepPreloadScript() should insert link/preload element', function() { - pageInitStepPreloadScript(fakeScriptURL); - - sinon.assert.calledOnce(insertElementStub); - sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'LINK')); - sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.rel === 'preload')); - sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.as === 'script')); - sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.href === fakeScriptURL)); - }); - - it('pageInitStepProtectPage() should insert script element', function() { - pageInitStepProtectPage(fakeScriptURL); - - sinon.assert.calledOnce(insertElementStub); - sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'SCRIPT')); - sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.type === 'text/javascript')); - sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.src === fakeScriptURL)); - }); - }); - - function ensurePrependToBidResponse(fakeBidResponse) { - expect(fakeBidResponse).to.have.own.property('ad').which.is.a('string'); - expect(fakeBidResponse.ad).to.contain(''); - } - - function ensureWrapBidResponse(fakeBidResponse, scriptUrl) { - expect(fakeBidResponse).to.have.own.property('ad').which.is.a('string'); - expect(fakeBidResponse.ad).to.contain(`src="${scriptUrl}"`); - expect(fakeBidResponse.ad).to.contain('agent.put(ad)'); - } - - describe('Bid processing step', function() { - it('bidWrapStepAugmentHtml() should prepend bid-specific information in a comment', function() { - const fakeBidResponse = makeFakeBidResponse(); - bidWrapStepAugmentHtml(fakeBidResponse); - ensurePrependToBidResponse(fakeBidResponse); - }); - - it('bidWrapStepProtectByWrapping() should wrap payload into a script tag', function() { - const fakeBidResponse = makeFakeBidResponse(); - bidWrapStepProtectByWrapping(fakeScriptURL, 0, fakeBidResponse); - ensureWrapBidResponse(fakeBidResponse, fakeScriptURL); - }); - }); - - describe('Sumbodule execution', function() { - let submoduleStub; - let insertElementStub; - beforeEach(function () { - submoduleStub = sinon.stub(hook, 'submodule'); - insertElementStub = sinon.stub(utils, 'insertElement'); - }); - afterEach(function () { - utils.insertElement.restore(); - submoduleStub.restore(); - }); - - function getModule() { - beforeInit(); - - expect(submoduleStub.calledOnceWith('realTimeData')).to.equal(true); - - const registeredSubmoduleDefinition = submoduleStub.getCall(0).args[1]; - expect(registeredSubmoduleDefinition).to.be.an('object'); - expect(registeredSubmoduleDefinition).to.have.own.property('name', 'clean.io'); - expect(registeredSubmoduleDefinition).to.have.own.property('init').that.is.a('function'); - expect(registeredSubmoduleDefinition).to.have.own.property('onBidResponseEvent').that.is.a('function'); - - return registeredSubmoduleDefinition; - } - - it('should register clean.io RTD submodule provider', function () { - getModule(); - }); - - it('should refuse initialization with incorrect parameters', function () { - const { init } = getModule(); - expect(init({ params: { cdnUrl: 'abc', protectionMode: 'full' } }, {})).to.equal(false); // too short distribution name - sinon.assert.notCalled(insertElementStub); - }); - - it('should iniitalize in full (page) protection mode', function () { - const { init, onBidResponseEvent } = getModule(); - expect(init({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'full' } }, {})).to.equal(true); - sinon.assert.calledOnce(insertElementStub); - sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'SCRIPT')); - - const fakeBidResponse = makeFakeBidResponse(); - onBidResponseEvent(fakeBidResponse, {}, {}); - ensurePrependToBidResponse(fakeBidResponse); - }); - - it('should iniitalize in bids (frame) protection mode', function () { - const { init, onBidResponseEvent } = getModule(); - expect(init({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids' } }, {})).to.equal(true); - sinon.assert.calledOnce(insertElementStub); - sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'LINK')); - - const fakeBidResponse = makeFakeBidResponse(); - onBidResponseEvent(fakeBidResponse, {}, {}); - ensureWrapBidResponse(fakeBidResponse, 'https://abc1234567890.cloudfront.net/script.js'); - }); - - it('should respect preload status in bids-nowait protection mode', function () { - const { init, onBidResponseEvent } = getModule(); - expect(init({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids-nowait' } }, {})).to.equal(true); - sinon.assert.calledOnce(insertElementStub); - sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'LINK')); - const preloadLink = insertElementStub.getCall(0).args[0]; - expect(preloadLink).to.have.property('onload').which.is.a('function'); - expect(preloadLink).to.have.property('onerror').which.is.a('function'); - - const fakeBidResponse1 = makeFakeBidResponse(); - onBidResponseEvent(fakeBidResponse1, {}, {}); - ensurePrependToBidResponse(fakeBidResponse1); - - // Simulate successful preloading - preloadLink.onload(); - - const fakeBidResponse2 = makeFakeBidResponse(); - onBidResponseEvent(fakeBidResponse2, {}, {}); - ensureWrapBidResponse(fakeBidResponse2, 'https://abc1234567890.cloudfront.net/script.js'); - - // Simulate error - preloadLink.onerror(); - - // Now we should fallback to just prepending - const fakeBidResponse3 = makeFakeBidResponse(); - onBidResponseEvent(fakeBidResponse3, {}, {}); - ensurePrependToBidResponse(fakeBidResponse3); - }); - }); -}); diff --git a/test/spec/modules/codefuelBidAdapter_spec.js b/test/spec/modules/codefuelBidAdapter_spec.js deleted file mode 100644 index a2549012d84..00000000000 --- a/test/spec/modules/codefuelBidAdapter_spec.js +++ /dev/null @@ -1,316 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/codefuelBidAdapter.js'; -import {config} from 'src/config.js'; -import {server} from 'test/mocks/xhr'; - -const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/92.0.4515.159 Safari/537.36'; -const DEFAULT_USER_AGENT = window.navigator.userAgent; -const setUADefault = () => { window.navigator.__defineGetter__('userAgent', function () { return DEFAULT_USER_AGENT }) }; -const setUAMock = () => { window.navigator.__defineGetter__('userAgent', function () { return USER_AGENT }) }; - -describe('Codefuel Adapter', function () { - describe('Bid request and response', function () { - const commonBidRequest = { - bidder: 'codefuel', - params: { - publisher: { - id: 'publisher-id' - }, - }, - bidId: '2d6815a92ba1ba', - auctionId: '12043683-3254-4f74-8934-f941b085579e', - } - const nativeBidRequestParams = { - nativeParams: { - image: { - required: true, - sizes: [ - 120, - 100 - ], - sendId: true - }, - title: { - required: true, - sendId: true - }, - sponsoredBy: { - required: false - } - }, - } - - const displayBidRequestParams = { - sizes: [ - [ - 300, - 250 - ] - ] - } - - describe('isBidRequestValid', function () { - before(() => { - config.setConfig({ - codefuel: { - bidderUrl: 'https://bidder-url.com', - } - } - ) - }) - after(() => { - config.resetConfig() - }) - - it('should fail when bid is invalid', function () { - const bid = { - bidder: 'codefuel', - params: { - publisher: { - id: 'publisher-id', - } - }, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - it('should not succeed when bid contains native params', function () { - const bid = { - bidder: 'codefuel', - params: { - publisher: { - id: 'publisher-id', - } - }, - ...nativeBidRequestParams, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - it('should not succeed when bid contains only sizes', function () { - const bid = { - bidder: 'codefuel', - params: { - publisher: { - id: 'publisher-id', - } - }, - ...displayBidRequestParams, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - it('should fail if publisher id is not set', function () { - const bid = { - bidder: 'codefuel', - ...nativeBidRequestParams, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - - it('should fail if bidder url is not set', function () { - const bid = { - bidder: 'codefuel', - params: { - publisher: { - id: 'publisher-id', - } - }, - ...nativeBidRequestParams, - } - config.resetConfig() - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - }) - - describe('buildRequests', function () { - before(() => { - setUAMock() - config.setConfig({ - codefuel: { - bidderUrl: 'https://bidder-url.com', - } - } - ) - }) - after(() => { - config.resetConfig() - setUADefault() - }) - - const commonBidderRequest = { - timeout: 500, - auctionId: '12043683-3254-4f74-8934-f941b085579e', - refererInfo: { - referer: 'https://example.com/', - } - } - - it('should build display request', function () { - const bidRequest = { - ...commonBidRequest, - ...displayBidRequestParams, - } - const expectedData = { - cur: [ - 'USD' - ], - device: { - devicetype: 2, - ua: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/92.0.4515.159 Safari/537.36' - }, - id: '12043683-3254-4f74-8934-f941b085579e', - imp: [ - { - banner: { - format: [ - { - h: 250, - w: 300 - } - ] - }, - id: '1' - } - ], - site: { - domain: 'example.com', - page: 'https://example.com/', - publisher: { - id: 'publisher-id' - } - }, - source: { - fd: 1 - }, - tmax: 500 - } - const res = spec.buildRequests([bidRequest], commonBidderRequest) - expect(res.url).to.equal('https://ai-p-codefuel-ds-rtb-us-east-1-k8s.seccint.com/prebid') - expect(res.data).to.deep.equal(expectedData) - }) - - it('should pass bidder timeout', function () { - const bidRequest = { - ...commonBidRequest, - } - const bidderRequest = { - ...commonBidderRequest, - timeout: 500 - } - const res = spec.buildRequests([bidRequest], bidderRequest) - const resData = res.data - expect(resData.tmax).to.equal(500) - }); - }) - - describe('interpretResponse', function () { - it('should return empty array if no valid bids', function () { - const res = spec.interpretResponse({}, []) - expect(res).to.be.an('array').that.is.empty - }); - - it('should interpret display response', function () { - const serverResponse = { - body: { - id: '6b2eedc8-8ff5-46ef-adcf-e701b508943e', - seatbid: [ - { - bid: [ - { - id: 'd90fe7fa-28d7-11eb-8ce4-462a842a7cf9', - impid: '1', - price: 1.1, - nurl: 'http://example.com/win/${AUCTION_PRICE}', - adm: '
ad
', - adomain: [ - 'example.com' - ], - cid: '3865084', - crid: '29998660', - cat: [ - 'IAB10-2' - ], - w: 300, - h: 250 - } - ], - seat: 'acc-6536' - } - ], - bidid: 'd90fe7fa-28d7-11eb-8ce4-13d94bfa26f9', - cur: 'USD' - } - } - const request = { - bids: [ - { - ...commonBidRequest, - ...displayBidRequestParams - } - ] - } - const expectedRes = [ - { - requestId: request.bids[0].bidId, - cpm: 1.1, - creativeId: '29998660', - ttl: 360, - netRevenue: true, - currency: 'USD', - mediaType: 'banner', - ad: '
ad
', - width: 300, - height: 250, - meta: {'advertiserDomains': []} - } - ] - - const res = spec.interpretResponse(serverResponse, request) - expect(res).to.deep.equal(expectedRes) - }); - }) - }) - - describe('getUserSyncs', function () { - const usersyncUrl = 'https://usersync-url.com'; - beforeEach(() => { - config.setConfig({ - codefuel: { - usersyncUrl: usersyncUrl, - } - } - ) - }) - after(() => { - config.resetConfig() - }) - - it('should not return user sync if pixel enabled with codefuel config', function () { - const ret = spec.getUserSyncs({pixelEnabled: true}) - expect(ret).to.be.an('array').that.is.empty - }) - - it('should not return user sync if pixel disabled', function () { - const ret = spec.getUserSyncs({pixelEnabled: false}) - expect(ret).to.be.an('array').that.is.empty - }) - - it('should not return user sync if url is not set', function () { - config.resetConfig() - const ret = spec.getUserSyncs({pixelEnabled: true}) - expect(ret).to.be.an('array').that.is.empty - }) - - it('should not pass GDPR consent', function() { - expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'foo'}, undefined)).to.to.be.an('array').that.is.empty - expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: false, consentString: 'foo'}, undefined)).to.be.an('array').that.is.empty - expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: undefined}, undefined)).to.be.an('array').that.is.empty - }); - - it('should not pass US consent', function() { - expect(spec.getUserSyncs({ pixelEnabled: true }, {}, undefined, '1NYN')).to.be.an('array').that.is.empty - }); - - it('should pass GDPR and US consent', function() { - expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'foo'}, '1NYN')).to.be.an('array').that.is.empty - }); - }) -}) diff --git a/test/spec/modules/cointrafficBidAdapter_spec.js b/test/spec/modules/cointrafficBidAdapter_spec.js index 24570de5083..3755ddc4c4a 100644 --- a/test/spec/modules/cointrafficBidAdapter_spec.js +++ b/test/spec/modules/cointrafficBidAdapter_spec.js @@ -3,7 +3,7 @@ import { spec } from 'modules/cointrafficBidAdapter.js'; import { config } from 'src/config.js' import * as utils from 'src/utils.js' -const ENDPOINT_URL = 'https://apps-pbd.ctengine.io/pb/tmp'; +const ENDPOINT_URL = 'https://appspb.cointraffic.io/pb/tmp'; describe('cointrafficBidAdapter', function () { describe('isBidRequestValid', function () { diff --git a/test/spec/modules/colossussspBidAdapter_spec.js b/test/spec/modules/colossussspBidAdapter_spec.js index da050b3af90..150bcb72121 100644 --- a/test/spec/modules/colossussspBidAdapter_spec.js +++ b/test/spec/modules/colossussspBidAdapter_spec.js @@ -1,5 +1,5 @@ -import { expect } from 'chai'; -import { spec } from '../../../modules/colossussspBidAdapter.js'; +import {expect} from 'chai'; +import {spec} from '../../../modules/colossussspBidAdapter.js'; describe('ColossussspAdapter', function () { let bid = { @@ -7,8 +7,7 @@ describe('ColossussspAdapter', function () { bidder: 'colossusssp', bidderRequestId: '145e1d6a7837c9', params: { - placement_id: 0, - group_id: 0 + placement_id: 0 }, placementCode: 'placementid_0', auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', @@ -17,13 +16,6 @@ describe('ColossussspAdapter', function () { sizes: [[300, 250]] } }, - ortb2Imp: { - ext: { - data: { - pbadslot: '/19968336/prebid_cache_video_adunit' - } - } - }, transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62', schain: { ver: '1.0', @@ -48,10 +40,6 @@ describe('ColossussspAdapter', function () { auctionStart: 1472239426000, timeout: 5000, uspConsent: '1YN-', - gdprConsent: { - consentString: 'xxx', - gdprApplies: 1 - }, refererInfo: { referer: 'http://www.example.com', reachedTop: true, @@ -65,7 +53,6 @@ describe('ColossussspAdapter', function () { }); it('Should return false when placement_id is not a number', function () { bid.params.placement_id = 'aaa'; - delete bid.params.group_id; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); @@ -84,14 +71,14 @@ describe('ColossussspAdapter', function () { it('Returns valid URL', function () { expect(serverRequest.url).to.equal('https://colossusssp.com/?c=o&m=multi'); }); - it('Should contain ccpa', function () { + it('Should contain ccpa', function() { expect(serverRequest.data.ccpa).to.be.an('string') }) it('Returns valid data if array of bids is valid', function () { let data = serverRequest.data; expect(data).to.be.an('object'); - expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'ccpa', 'gdpr_consent', 'gdpr_require'); + expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'ccpa'); expect(data.deviceWidth).to.be.a('number'); expect(data.deviceHeight).to.be.a('number'); expect(data.language).to.be.a('string'); @@ -101,66 +88,17 @@ describe('ColossussspAdapter', function () { let placements = data['placements']; for (let i = 0; i < placements.length; i++) { let placement = placements[i]; - expect(placement).to.have.all.keys('placementId', 'groupId', 'eids', 'bidId', 'traffic', 'sizes', 'schain', 'floor', 'gpid'); + expect(placement).to.have.all.keys('placementId', 'eids', 'bidId', 'traffic', 'sizes', 'schain', 'floor'); expect(placement.schain).to.be.an('object') expect(placement.placementId).to.be.a('number'); - expect(placement.groupId).to.be.a('number'); expect(placement.bidId).to.be.a('string'); expect(placement.traffic).to.be.a('string'); expect(placement.sizes).to.be.an('array'); expect(placement.floor).to.be.an('object'); - expect(placement.gpid).to.be.an('string'); - } - }); - - it('Returns valid video data if array of bids is valid', function () { - const videoBid = { - ...bid, - params: { - placement_id: 0, - traffic: 'video', - }, - mediaTypes: { - video: { - playerSize: [[300, 300]], - minduration: 5, - maxduration: 60 - } - } - } - let serverRequest = spec.buildRequests([videoBid], bidderRequest); - - let data = serverRequest.data; - expect(data).to.be.an('object'); - expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'ccpa', 'gdpr_consent', 'gdpr_require'); - expect(data.deviceWidth).to.be.a('number'); - expect(data.deviceHeight).to.be.a('number'); - expect(data.language).to.be.a('string'); - expect(data.secure).to.be.within(0, 1); - expect(data.host).to.be.a('string'); - expect(data.page).to.be.a('string'); - let placements = data['placements']; - for (let i = 0; i < placements.length; i++) { - let placement = placements[i]; - expect(placement).to.have.all.keys('placementId', 'groupId', 'eids', 'bidId', 'traffic', 'schain', 'floor', 'gpid', 'sizes', - 'playerSize', 'minduration', 'maxduration', 'mimes', 'protocols', 'startdelay', 'placement', 'skip', 'skipafter', - 'minbitrate', 'maxbitrate', 'delivery', 'playbackmethod', 'api', 'linearity' - ); - expect(placement.schain).to.be.an('object') - expect(placement.placementId).to.be.a('number'); - expect(placement.bidId).to.be.a('string'); - expect(placement.traffic).to.be.a('string'); - expect(placement.floor).to.be.an('object'); - expect(placement.gpid).to.be.an('string'); - expect(placement.sizes).to.be.an('array'); - expect(placement.playerSize).to.be.an('array'); - expect(placement.minduration).to.be.an('number'); - expect(placement.maxduration).to.be.an('number'); } }); - it('Returns empty data if no valid requests are passed', function () { - serverRequest = spec.buildRequests([], bidderRequest); + serverRequest = spec.buildRequests([]); let data = serverRequest.data; expect(data.placements).to.be.an('array').that.is.empty; }); @@ -172,7 +110,6 @@ describe('ColossussspAdapter', function () { bid.userId.idl_env = 'idl_env123'; bid.userId.tdid = 'tdid123'; bid.userId.id5id = { uid: 'id5id123' }; - bid.userId.uid2 = { id: 'uid2id123' }; let serverRequest = spec.buildRequests([bid], bidderRequest); it('Returns valid data if array of bids is valid', function () { let data = serverRequest.data; @@ -182,11 +119,11 @@ describe('ColossussspAdapter', function () { let placement = placements[i]; expect(placement).to.have.property('eids') expect(placement.eids).to.be.an('array') - expect(placement.eids.length).to.be.equal(5) + expect(placement.eids.length).to.be.equal(4) for (let index in placement.eids) { let v = placement.eids[index]; expect(v).to.have.all.keys('source', 'uids') - expect(v.source).to.be.oneOf(['britepool.com', 'identityLink', 'adserver.org', 'id5-sync.com', 'uidapi.com']) + expect(v.source).to.be.oneOf(['britepool.com', 'identityLink', 'adserver.org', 'id5-sync.com']) expect(v.uids).to.be.an('array'); expect(v.uids.length).to.be.equal(1) expect(v.uids[0]).to.have.property('id') @@ -197,7 +134,7 @@ describe('ColossussspAdapter', function () { describe('interpretResponse', function () { let resObject = { - body: [{ + body: [ { requestId: '123', mediaType: 'banner', cpm: 0.3, @@ -212,7 +149,7 @@ describe('ColossussspAdapter', function () { advertiserDomains: ['google.com'], advertiserId: 1234 } - }] + } ] }; let serverResponses = spec.interpretResponse(resObject); it('Returns an array of valid server responses if response object is valid', function () { @@ -238,68 +175,16 @@ describe('ColossussspAdapter', function () { expect(serverResponses).to.be.an('array').that.is.empty; }); }); - - let videoResObject = { - body: [{ - requestId: '123', - mediaType: 'video', - cpm: 0.3, - width: 320, - height: 50, - vastUrl: '', - ttl: 1000, - creativeId: '123asd', - netRevenue: true, - currency: 'USD', - meta: { - advertiserDomains: ['google.com'], - advertiserId: 1234 - } - }] - }; - let videoServerResponses = spec.interpretResponse(videoResObject); - it('Returns an array of valid server video responses if response object is valid', function () { - expect(videoServerResponses).to.be.an('array').that.is.not.empty; - for (let i = 0; i < videoServerResponses.length; i++) { - let dataItem = videoServerResponses[i]; - expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'vastUrl', 'ttl', 'creativeId', - 'netRevenue', 'currency', 'mediaType', 'meta'); - expect(dataItem.requestId).to.be.a('string'); - expect(dataItem.cpm).to.be.a('number'); - expect(dataItem.width).to.be.a('number'); - expect(dataItem.height).to.be.a('number'); - expect(dataItem.vastUrl).to.be.a('string'); - expect(dataItem.ttl).to.be.a('number'); - expect(dataItem.creativeId).to.be.a('string'); - expect(dataItem.netRevenue).to.be.a('boolean'); - expect(dataItem.currency).to.be.a('string'); - expect(dataItem.mediaType).to.be.a('string'); - expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains'); - } - it('Returns an empty array if invalid response is passed', function () { - videoServerResponses = spec.interpretResponse('invalid_response'); - expect(videoServerResponses).to.be.an('array').that.is.empty; - }); - }); }); - describe('onBidWon', function () { - it('should make an ajax call', function () { - const bid = { - nurl: 'http://example.com/win', - }; - expect(spec.onBidWon(bid)).to.equals(undefined); - }); - }) - describe('getUserSyncs', function () { - let userSync = spec.getUserSyncs({}, {}, { consentString: 'xxx', gdprApplies: 1 }, { consentString: '1YN-' }); + let userSync = spec.getUserSyncs(); it('Returns valid URL and type', function () { expect(userSync).to.be.an('array').with.lengthOf(1); expect(userSync[0].type).to.exist; expect(userSync[0].url).to.exist; - expect(userSync[0].type).to.be.equal('hms.gif'); - expect(userSync[0].url).to.be.equal('https://sync.colossusssp.com/hms.gif?pbjs=1&gdpr=0&gdpr_consent=xxx&ccpa_consent=1YN-&coppa=0'); + expect(userSync[0].type).to.be.equal('image'); + expect(userSync[0].url).to.be.equal('https://colossusssp.com/?c=o&m=cookie'); }); }); }); diff --git a/test/spec/modules/compassBidAdapter_spec.js b/test/spec/modules/compassBidAdapter_spec.js deleted file mode 100644 index 28021c4f7c0..00000000000 --- a/test/spec/modules/compassBidAdapter_spec.js +++ /dev/null @@ -1,398 +0,0 @@ -import { expect } from 'chai'; -import { spec } from '../../../modules/compassBidAdapter.js'; -import { BANNER, VIDEO, NATIVE } from '../../../src/mediaTypes.js'; -import { getUniqueIdentifierStr } from '../../../src/utils.js'; - -const bidder = 'compass' - -describe('CompassBidAdapter', function () { - const bids = [ - { - bidId: getUniqueIdentifierStr(), - bidder: bidder, - mediaTypes: { - [BANNER]: { - sizes: [[300, 250]] - } - }, - params: { - placementId: 'testBanner', - } - }, - { - bidId: getUniqueIdentifierStr(), - bidder: bidder, - mediaTypes: { - [VIDEO]: { - playerSize: [[300, 300]], - minduration: 5, - maxduration: 60 - } - }, - params: { - placementId: 'testVideo', - } - }, - { - bidId: getUniqueIdentifierStr(), - bidder: bidder, - mediaTypes: { - [NATIVE]: { - native: { - title: { - required: true - }, - body: { - required: true - }, - icon: { - required: true, - size: [64, 64] - } - } - } - }, - params: { - placementId: 'testNative', - } - } - ]; - - const invalidBid = { - bidId: getUniqueIdentifierStr(), - bidder: bidder, - mediaTypes: { - [BANNER]: { - sizes: [[300, 250]] - } - }, - params: { - - } - } - - const bidderRequest = { - uspConsent: '1---', - gdprConsent: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw', - refererInfo: { - referer: 'https://test.com' - } - }; - - describe('isBidRequestValid', function () { - it('Should return true if there are bidId, params and key parameters present', function () { - expect(spec.isBidRequestValid(bids[0])).to.be.true; - }); - it('Should return false if at least one of parameters is not present', function () { - expect(spec.isBidRequestValid(invalidBid)).to.be.false; - }); - }); - - describe('buildRequests', function () { - let serverRequest = spec.buildRequests(bids, bidderRequest); - - it('Creates a ServerRequest object with method, URL and data', function () { - expect(serverRequest).to.exist; - expect(serverRequest.method).to.exist; - expect(serverRequest.url).to.exist; - expect(serverRequest.data).to.exist; - }); - - it('Returns POST method', function () { - expect(serverRequest.method).to.equal('POST'); - }); - - it('Returns valid URL', function () { - expect(serverRequest.url).to.equal('https://sa-lb.deliverimp.com/pbjs'); - }); - - it('Returns general data valid', function () { - let data = serverRequest.data; - expect(data).to.be.an('object'); - expect(data).to.have.all.keys('deviceWidth', - 'deviceHeight', - 'language', - 'secure', - 'host', - 'page', - 'placements', - 'coppa', - 'ccpa', - 'gdpr', - 'tmax' - ); - expect(data.deviceWidth).to.be.a('number'); - expect(data.deviceHeight).to.be.a('number'); - expect(data.language).to.be.a('string'); - expect(data.secure).to.be.within(0, 1); - expect(data.host).to.be.a('string'); - expect(data.page).to.be.a('string'); - expect(data.coppa).to.be.a('number'); - expect(data.gdpr).to.be.a('string'); - expect(data.ccpa).to.be.a('string'); - expect(data.tmax).to.be.a('number'); - expect(data.placements).to.have.lengthOf(3); - }); - - it('Returns valid placements', function () { - const { placements } = serverRequest.data; - for (let i = 0, len = placements.length; i < len; i++) { - const placement = placements[i]; - expect(placement.placementId).to.be.oneOf(['testBanner', 'testVideo', 'testNative']); - expect(placement.adFormat).to.be.oneOf([BANNER, VIDEO, NATIVE]); - expect(placement.bidId).to.be.a('string'); - expect(placement.schain).to.be.an('object'); - expect(placement.bidfloor).to.exist.and.to.equal(0); - expect(placement.type).to.exist.and.to.equal('publisher'); - - if (placement.adFormat === BANNER) { - expect(placement.sizes).to.be.an('array'); - } - switch (placement.adFormat) { - case BANNER: - expect(placement.sizes).to.be.an('array'); - break; - case VIDEO: - expect(placement.playerSize).to.be.an('array'); - expect(placement.minduration).to.be.an('number'); - expect(placement.maxduration).to.be.an('number'); - break; - case NATIVE: - expect(placement.native).to.be.an('object'); - break; - } - } - }); - - it('Returns data with gdprConsent and without uspConsent', function () { - delete bidderRequest.uspConsent; - serverRequest = spec.buildRequests(bids, bidderRequest); - let data = serverRequest.data; - expect(data.gdpr).to.exist; - expect(data.gdpr).to.be.a('string'); - expect(data.gdpr).to.equal(bidderRequest.gdprConsent); - expect(data.ccpa).to.not.exist; - delete bidderRequest.gdprConsent; - }); - - it('Returns data with uspConsent and without gdprConsent', function () { - bidderRequest.uspConsent = '1---'; - delete bidderRequest.gdprConsent; - serverRequest = spec.buildRequests(bids, bidderRequest); - let data = serverRequest.data; - expect(data.ccpa).to.exist; - expect(data.ccpa).to.be.a('string'); - expect(data.ccpa).to.equal(bidderRequest.uspConsent); - expect(data.gdpr).to.not.exist; - }); - - it('Returns empty data if no valid requests are passed', function () { - serverRequest = spec.buildRequests([], bidderRequest); - let data = serverRequest.data; - expect(data.placements).to.be.an('array').that.is.empty; - }); - }); - - describe('interpretResponse', function () { - it('Should interpret banner response', function () { - const banner = { - body: [{ - mediaType: 'banner', - width: 300, - height: 250, - cpm: 0.4, - ad: 'Test', - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1', - meta: { - advertiserDomains: ['google.com'], - advertiserId: 1234 - } - }] - }; - let bannerResponses = spec.interpretResponse(banner); - expect(bannerResponses).to.be.an('array').that.is.not.empty; - let dataItem = bannerResponses[0]; - expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', - 'netRevenue', 'currency', 'dealId', 'mediaType', 'meta'); - expect(dataItem.requestId).to.equal(banner.body[0].requestId); - expect(dataItem.cpm).to.equal(banner.body[0].cpm); - expect(dataItem.width).to.equal(banner.body[0].width); - expect(dataItem.height).to.equal(banner.body[0].height); - expect(dataItem.ad).to.equal(banner.body[0].ad); - expect(dataItem.ttl).to.equal(banner.body[0].ttl); - expect(dataItem.creativeId).to.equal(banner.body[0].creativeId); - expect(dataItem.netRevenue).to.be.true; - expect(dataItem.currency).to.equal(banner.body[0].currency); - expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains'); - }); - it('Should interpret video response', function () { - const video = { - body: [{ - vastUrl: 'test.com', - mediaType: 'video', - cpm: 0.5, - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1', - meta: { - advertiserDomains: ['google.com'], - advertiserId: 1234 - } - }] - }; - let videoResponses = spec.interpretResponse(video); - expect(videoResponses).to.be.an('array').that.is.not.empty; - - let dataItem = videoResponses[0]; - expect(dataItem).to.have.all.keys('requestId', 'cpm', 'vastUrl', 'ttl', 'creativeId', - 'netRevenue', 'currency', 'dealId', 'mediaType', 'meta'); - expect(dataItem.requestId).to.equal('23fhj33i987f'); - expect(dataItem.cpm).to.equal(0.5); - expect(dataItem.vastUrl).to.equal('test.com'); - expect(dataItem.ttl).to.equal(120); - expect(dataItem.creativeId).to.equal('2'); - expect(dataItem.netRevenue).to.be.true; - expect(dataItem.currency).to.equal('USD'); - expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains'); - }); - it('Should interpret native response', function () { - const native = { - body: [{ - mediaType: 'native', - native: { - clickUrl: 'test.com', - title: 'Test', - image: 'test.com', - impressionTrackers: ['test.com'], - }, - ttl: 120, - cpm: 0.4, - requestId: '23fhj33i987f', - creativeId: '2', - netRevenue: true, - currency: 'USD', - meta: { - advertiserDomains: ['google.com'], - advertiserId: 1234 - } - }] - }; - let nativeResponses = spec.interpretResponse(native); - expect(nativeResponses).to.be.an('array').that.is.not.empty; - - let dataItem = nativeResponses[0]; - expect(dataItem).to.have.keys('requestId', 'cpm', 'ttl', 'creativeId', 'netRevenue', 'currency', 'mediaType', 'native', 'meta'); - expect(dataItem.native).to.have.keys('clickUrl', 'impressionTrackers', 'title', 'image') - expect(dataItem.requestId).to.equal('23fhj33i987f'); - expect(dataItem.cpm).to.equal(0.4); - expect(dataItem.native.clickUrl).to.equal('test.com'); - expect(dataItem.native.title).to.equal('Test'); - expect(dataItem.native.image).to.equal('test.com'); - expect(dataItem.native.impressionTrackers).to.be.an('array').that.is.not.empty; - expect(dataItem.native.impressionTrackers[0]).to.equal('test.com'); - expect(dataItem.ttl).to.equal(120); - expect(dataItem.creativeId).to.equal('2'); - expect(dataItem.netRevenue).to.be.true; - expect(dataItem.currency).to.equal('USD'); - expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains'); - }); - it('Should return an empty array if invalid banner response is passed', function () { - const invBanner = { - body: [{ - width: 300, - cpm: 0.4, - ad: 'Test', - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - - let serverResponses = spec.interpretResponse(invBanner); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - it('Should return an empty array if invalid video response is passed', function () { - const invVideo = { - body: [{ - mediaType: 'video', - cpm: 0.5, - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - let serverResponses = spec.interpretResponse(invVideo); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - it('Should return an empty array if invalid native response is passed', function () { - const invNative = { - body: [{ - mediaType: 'native', - clickUrl: 'test.com', - title: 'Test', - impressionTrackers: ['test.com'], - ttl: 120, - requestId: '23fhj33i987f', - creativeId: '2', - netRevenue: true, - currency: 'USD', - }] - }; - let serverResponses = spec.interpretResponse(invNative); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - it('Should return an empty array if invalid response is passed', function () { - const invalid = { - body: [{ - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - let serverResponses = spec.interpretResponse(invalid); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - }); - - describe('getUserSyncs', function() { - it('Should return array of objects with proper sync config , include GDPR', function() { - const syncData = spec.getUserSyncs({}, {}, { - consentString: 'ALL', - gdprApplies: true, - }, {}); - expect(syncData).to.be.an('array').which.is.not.empty; - expect(syncData[0]).to.be.an('object') - expect(syncData[0].type).to.be.a('string') - expect(syncData[0].type).to.equal('image') - expect(syncData[0].url).to.be.a('string') - expect(syncData[0].url).to.equal('https://sa-cs.deliverimp.com/image?pbjs=1&gdpr=1&gdpr_consent=ALL&coppa=0') - }); - it('Should return array of objects with proper sync config , include CCPA', function() { - const syncData = spec.getUserSyncs({}, {}, {}, { - consentString: '1---' - }); - expect(syncData).to.be.an('array').which.is.not.empty; - expect(syncData[0]).to.be.an('object') - expect(syncData[0].type).to.be.a('string') - expect(syncData[0].type).to.equal('image') - expect(syncData[0].url).to.be.a('string') - expect(syncData[0].url).to.equal('https://sa-cs.deliverimp.com/image?pbjs=1&ccpa_consent=1---&coppa=0') - }); - }); -}); diff --git a/test/spec/modules/connectIdSystem_spec.js b/test/spec/modules/connectIdSystem_spec.js deleted file mode 100644 index 41135a74515..00000000000 --- a/test/spec/modules/connectIdSystem_spec.js +++ /dev/null @@ -1,189 +0,0 @@ -import {expect} from 'chai'; -import {parseQS} from 'src/utils.js'; -import {connectIdSubmodule} from 'modules/connectIdSystem.js'; - -describe('Yahoo ConnectID Submodule', () => { - const HASHED_EMAIL = '6bda6f2fa268bf0438b5423a9861a2cedaa5dec163c03f743cfe05c08a8397b2'; - const PIXEL_ID = '1234'; - const PROD_ENDPOINT = `https://ups.analytics.yahoo.com/ups/${PIXEL_ID}/fed`; - const OVERRIDE_ENDPOINT = 'https://foo/bar'; - - it('should have the correct module name declared', () => { - expect(connectIdSubmodule.name).to.equal('connectId'); - }); - - it('should have the correct TCFv2 Vendor ID declared', () => { - expect(connectIdSubmodule.gvlid).to.equal(25); - }); - - describe('getId()', () => { - let ajaxStub; - let getAjaxFnStub; - let consentData; - beforeEach(() => { - ajaxStub = sinon.stub(); - getAjaxFnStub = sinon.stub(connectIdSubmodule, 'getAjaxFn'); - getAjaxFnStub.returns(ajaxStub); - - consentData = { - gdpr: { - gdprApplies: 1, - consentString: 'GDPR_CONSENT_STRING' - }, - uspConsent: 'USP_CONSENT_STRING' - }; - }); - - afterEach(() => { - getAjaxFnStub.restore(); - }); - - function invokeGetIdAPI(configParams, consentData) { - let result = connectIdSubmodule.getId({ - params: configParams - }, consentData); - if (typeof result === 'object') { - result.callback(sinon.stub()); - } - return result; - } - - it('returns undefined if he and pixelId params are not passed', () => { - expect(invokeGetIdAPI({}, consentData)).to.be.undefined; - expect(ajaxStub.callCount).to.equal(0); - }); - - it('returns undefined if the pixelId param is not passed', () => { - expect(invokeGetIdAPI({ - he: HASHED_EMAIL - }, consentData)).to.be.undefined; - expect(ajaxStub.callCount).to.equal(0); - }); - - it('returns undefined if the he param is not passed', () => { - expect(invokeGetIdAPI({ - pixelId: PIXEL_ID - }, consentData)).to.be.undefined; - expect(ajaxStub.callCount).to.equal(0); - }); - - it('returns an object with the callback function if the correct params are passed', () => { - let result = invokeGetIdAPI({ - he: HASHED_EMAIL, - pixelId: PIXEL_ID - }, consentData); - expect(result).to.be.an('object').that.has.all.keys('callback'); - expect(result.callback).to.be.a('function'); - }); - - it('Makes an ajax GET request to the production API endpoint with query params', () => { - invokeGetIdAPI({ - he: HASHED_EMAIL, - pixelId: PIXEL_ID - }, consentData); - - const expectedParams = { - he: HASHED_EMAIL, - pixelId: PIXEL_ID, - '1p': '0', - gdpr: '1', - gdpr_consent: consentData.gdpr.consentString, - us_privacy: consentData.uspConsent - }; - const requestQueryParams = parseQS(ajaxStub.firstCall.args[0].split('?')[1]); - - expect(ajaxStub.firstCall.args[0].indexOf(`${PROD_ENDPOINT}?`)).to.equal(0); - expect(requestQueryParams).to.deep.equal(expectedParams); - expect(ajaxStub.firstCall.args[3]).to.deep.equal({method: 'GET', withCredentials: true}); - }); - - it('Makes an ajax GET request to the specified override API endpoint with query params', () => { - invokeGetIdAPI({ - he: HASHED_EMAIL, - endpoint: OVERRIDE_ENDPOINT - }, consentData); - - const expectedParams = { - he: HASHED_EMAIL, - '1p': '0', - gdpr: '1', - gdpr_consent: consentData.gdpr.consentString, - us_privacy: consentData.uspConsent - }; - const requestQueryParams = parseQS(ajaxStub.firstCall.args[0].split('?')[1]); - - expect(ajaxStub.firstCall.args[0].indexOf(`${OVERRIDE_ENDPOINT}?`)).to.equal(0); - expect(requestQueryParams).to.deep.equal(expectedParams); - expect(ajaxStub.firstCall.args[3]).to.deep.equal({method: 'GET', withCredentials: true}); - }); - - it('sets the callbacks param of the ajax function call correctly', () => { - invokeGetIdAPI({ - he: HASHED_EMAIL, - pixelId: PIXEL_ID, - }, consentData); - - expect(ajaxStub.firstCall.args[1]).to.be.an('object').that.has.all.keys(['success', 'error']); - }); - - it('sets GDPR consent data flag correctly when call is under GDPR jurisdiction.', () => { - invokeGetIdAPI({ - he: HASHED_EMAIL, - pixelId: PIXEL_ID, - }, consentData); - - const requestQueryParams = parseQS(ajaxStub.firstCall.args[0].split('?')[1]); - expect(requestQueryParams.gdpr).to.equal('1'); - expect(requestQueryParams.gdpr_consent).to.equal(consentData.gdpr.consentString); - }); - - it('sets GDPR consent data flag correctly when call is NOT under GDPR jurisdiction.', () => { - consentData.gdpr.gdprApplies = false; - - invokeGetIdAPI({ - he: HASHED_EMAIL, - pixelId: PIXEL_ID, - }, consentData); - - const requestQueryParams = parseQS(ajaxStub.firstCall.args[0].split('?')[1]); - expect(requestQueryParams.gdpr).to.equal('0'); - expect(requestQueryParams.gdpr_consent).to.equal(''); - }); - - [1, '1', true].forEach(firstPartyParamValue => { - it(`sets 1p payload property to '1' for a config value of ${firstPartyParamValue}`, () => { - invokeGetIdAPI({ - '1p': firstPartyParamValue, - he: HASHED_EMAIL, - pixelId: PIXEL_ID, - }, consentData); - - const requestQueryParams = parseQS(ajaxStub.firstCall.args[0].split('?')[1]); - expect(requestQueryParams['1p']).to.equal('1'); - }); - }); - }); - - describe('decode()', () => { - const VALID_API_RESPONSES = [{ - key: 'connectid', - expected: '4567', - payload: { - connectid: '4567' - } - }]; - VALID_API_RESPONSES.forEach(responseData => { - it('should return a newly constructed object with the connect ID for a payload with ${responseData.key} key(s)', () => { - expect(connectIdSubmodule.decode(responseData.payload)).to.deep.equal( - {connectId: responseData.expected} - ); - }); - }); - - [{}, '', {foo: 'bar'}].forEach((response) => { - it(`should return undefined for an invalid response "${JSON.stringify(response)}"`, () => { - expect(connectIdSubmodule.decode(response)).to.be.undefined; - }); - }); - }); -}); diff --git a/test/spec/modules/consentManagementUsp_spec.js b/test/spec/modules/consentManagementUsp_spec.js index a2b1e22ed35..7d3cd48a8e4 100644 --- a/test/spec/modules/consentManagementUsp_spec.js +++ b/test/spec/modules/consentManagementUsp_spec.js @@ -8,9 +8,9 @@ import { } from 'modules/consentManagementUsp.js'; import * as utils from 'src/utils.js'; import { config } from 'src/config.js'; -import {uspDataHandler} from 'src/adapterManager.js'; -import 'src/prebid.js'; +import { uspDataHandler } from 'src/adapterManager.js'; +let assert = require('chai').assert; let expect = require('chai').expect; function createIFrameMarker() { @@ -58,12 +58,6 @@ describe('consentManagement', function () { sinon.assert.notCalled(utils.logInfo); }); - it('should not produce any USP metadata', function() { - setConsentConfig({}); - let consentMeta = uspDataHandler.getConsentMeta(); - expect(consentMeta).to.be.undefined; - }); - it('should exit the consent manager if only config.gdpr is an object', function() { setConsentConfig({ gdpr: { cmpApi: 'iab' } }); expect(consentAPI).to.be.undefined; @@ -77,11 +71,6 @@ describe('consentManagement', function () { sinon.assert.calledOnce(utils.logWarn); sinon.assert.notCalled(utils.logInfo); }); - - it('should immediately start looking up consent data', () => { - setConsentConfig({usp: {cmpApi: 'invalid'}}); - expect(uspDataHandler.ready).to.be.true; - }); }); describe('valid setConsentConfig value', function () { @@ -102,21 +91,6 @@ describe('consentManagement', function () { expect(consentAPI).to.be.equal('daa'); expect(consentTimeout).to.be.equal(7500); }); - - it('should enable uspDataHandler', () => { - setConsentConfig({usp: {cmpApi: 'daa', timeout: 7500}}); - expect(uspDataHandler.enabled).to.be.true; - }); - - it('should call setConsentData(null) on invalid CMP api', () => { - setConsentConfig({usp: {cmpApi: 'invalid'}}); - let hookRan = false; - requestBidsHook(() => { - hookRan = true; - }, {}); - expect(hookRan).to.be.true; - expect(uspDataHandler.ready).to.be.true; - }); }); describe('static consent string setConsentConfig value', () => { @@ -140,7 +114,6 @@ describe('consentManagement', function () { setConsentConfig(staticConfig); expect(consentAPI).to.be.equal('static'); expect(consentTimeout).to.be.equal(0); // should always return without a timeout when config is used - expect(uspDataHandler.getConsentData()).to.eql(staticConfig.usp.consentData.getUSPData.uspString) expect(staticConsentData.usPrivacy).to.be.equal(staticConfig.usp.consentData.getUSPData.uspString); }); }); @@ -247,32 +220,6 @@ describe('consentManagement', function () { expect(consent).to.equal(testConsentData.uspString); sinon.assert.called(uspStub); }); - - it('should call uspDataHandler.setConsentData(null) on error', () => { - let hookRan = false; - uspStub = sinon.stub(window, '__uspapi').callsFake((...args) => { - args[2](null, false); - }); - requestBidsHook(() => { - hookRan = true; - }, {}); - expect(hookRan).to.be.true; - expect(uspDataHandler.ready).to.be.true; - expect(uspDataHandler.getConsentData()).to.equal(null); - }); - - it('should call uspDataHandler.setConsentData(null) on timeout', (done) => { - setConsentConfig({usp: {timeout: 10}}); - let hookRan = false; - uspStub = sinon.stub(window, '__uspapi').callsFake(() => {}); - requestBidsHook(() => { hookRan = true; }, {}); - setTimeout(() => { - expect(hookRan).to.be.true; - expect(uspDataHandler.ready).to.be.true; - expect(uspDataHandler.getConsentData()).to.equal(null); - done(); - }, 20) - }); }); describe('USPAPI workflow for iframed page', function () { @@ -419,27 +366,6 @@ describe('consentManagement', function () { expect(didHookReturn).to.be.true; expect(consent).to.equal(testConsentData.uspString); }); - - it('returns USP consent metadata', function () { - let testConsentData = { - uspString: '1NY' - }; - - uspapiStub = sinon.stub(window, '__uspapi').callsFake((...args) => { - args[2](testConsentData, true); - }); - - setConsentConfig(goodConfig); - requestBidsHook(() => { didHookReturn = true; }, {}); - - let consentMeta = uspDataHandler.getConsentMeta(); - - sinon.assert.notCalled(utils.logWarn); - sinon.assert.notCalled(utils.logError); - - expect(consentMeta.usp).to.equal(testConsentData.uspString); - expect(consentMeta.generatedAt).to.be.above(1644367751709); - }); }); }); }); diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index b0cd0197f8b..5e9b0f07f46 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -2,7 +2,6 @@ import { setConsentConfig, requestBidsHook, resetConsentData, userCMP, consentTi import { gdprDataHandler } from 'src/adapterManager.js'; import * as utils from 'src/utils.js'; import { config } from 'src/config.js'; -import 'src/prebid.js'; let expect = require('chai').expect; @@ -46,18 +45,6 @@ describe('consentManagement', function () { expect(userCMP).to.be.undefined; sinon.assert.calledOnce(utils.logWarn); }); - - it('should not produce any consent metadata', function() { - setConsentConfig(undefined) - let consentMetadata = gdprDataHandler.getConsentMeta(); - expect(consentMetadata).to.be.undefined; - sinon.assert.calledOnce(utils.logWarn); - }) - - it('should immediately look up consent data', () => { - setConsentConfig({gdpr: {cmpApi: 'invalid'}}); - expect(gdprDataHandler.ready).to.be.true; - }) }); describe('valid setConsentConfig value', function () { @@ -137,11 +124,6 @@ describe('consentManagement', function () { }); expect(gdprScope).to.be.equal(false); }); - - it('should enable gdprDataHandler', () => { - setConsentConfig({gdpr: {}}); - expect(gdprDataHandler.enabled).to.be.true; - }); }); describe('static consent string setConsentConfig value', () => { @@ -281,9 +263,6 @@ describe('consentManagement', function () { definedInConfig: true }); expect(gdprScope).to.be.equal(false); - const consent = gdprDataHandler.getConsentData(); - expect(consent.consentString).to.eql(staticConfig.consentData.getTCData.tcString); - expect(consent.vendorData).to.eql(staticConfig.consentData.getTCData); expect(staticConsentData).to.be.equal(staticConfig.consentData); }); }); @@ -302,14 +281,6 @@ describe('consentManagement', function () { allowAuctionWithoutConsent: true }; - const staticConfig = { - cmpApi: 'static', - timeout: 7500, - consentData: { - getTCData: {} - } - } - let didHookReturn; afterEach(function () { @@ -347,14 +318,6 @@ describe('consentManagement', function () { expect(consent).to.be.null; }); - it('should call gpdrDataHandler.setConsentData() when unknown CMP api is used', () => { - setConsentConfig({gdpr: {cmpApi: 'invalid'}}); - let hookRan = false; - requestBidsHook(() => { hookRan = true; }, {}); - expect(hookRan).to.be.true; - expect(gdprDataHandler.ready).to.be.true; - }) - it('should throw proper errors when CMP is not found', function () { setConsentConfig(goodConfigWithCancelAuction); @@ -366,19 +329,7 @@ describe('consentManagement', function () { sinon.assert.calledTwice(utils.logError); expect(didHookReturn).to.be.false; expect(consent).to.be.null; - expect(gdprDataHandler.ready).to.be.true; }); - - it('should not trip when adUnits have no size', () => { - setConsentConfig(staticConfig); - let ran = false; - requestBidsHook(() => { - ran = true; - }, {adUnits: [{code: 'test', mediaTypes: {video: {}}}]}); - return gdprDataHandler.promise.then(() => { - expect(ran).to.be.true; - }); - }) }); describe('already known consentData:', function () { @@ -716,33 +667,6 @@ describe('consentManagement', function () { expect(consent.apiVersion).to.equal(2); }); - it('produces gdpr metadata', function () { - let testConsentData = { - tcString: 'abc12345234', - gdprApplies: true, - purposeOneTreatment: false, - eventStatus: 'tcloaded', - vendorData: { - tcString: 'abc12345234' - } - }; - cmpStub = sinon.stub(window, '__tcfapi').callsFake((...args) => { - args[2](testConsentData, true); - }); - - setConsentConfig(goodConfigWithAllowAuction); - - requestBidsHook(() => { - didHookReturn = true; - }, {}); - let consentMeta = gdprDataHandler.getConsentMeta(); - sinon.assert.notCalled(utils.logError); - expect(consentMeta.consentStringSize).to.be.above(0) - expect(consentMeta.gdprApplies).to.be.true; - expect(consentMeta.apiVersion).to.equal(2); - expect(consentMeta.generatedAt).to.be.above(1644367751709); - }); - it('performs lookup check and stores consentData for a valid existing user with additional consent', function () { let testConsentData = { tcString: 'abc12345234', @@ -779,11 +703,6 @@ describe('consentManagement', function () { setConsentConfig(goodConfigWithAllowAuction); - sinon.assert.calledOnce(utils.logWarn); - sinon.assert.notCalled(utils.logError); - - [utils.logWarn, utils.logError].forEach((stub) => stub.reset()); - requestBidsHook(() => { didHookReturn = true; }, { bidsBackHandler: () => bidsBackHandlerReturn = true }); @@ -794,28 +713,6 @@ describe('consentManagement', function () { expect(didHookReturn).to.be.false; expect(bidsBackHandlerReturn).to.be.true; expect(consent).to.be.null; - expect(gdprDataHandler.ready).to.be.true; - }); - - it('allows the auction when CMP is unresponsive', (done) => { - setConsentConfig({ - cmpApi: 'iab', - timeout: 10, - defaultGdprScope: true - }); - - requestBidsHook(() => { - didHookReturn = true; - }, {}); - - setTimeout(() => { - expect(didHookReturn).to.be.true; - const consent = gdprDataHandler.getConsentData(); - expect(consent.gdprApplies).to.be.true; - expect(consent.consentString).to.be.undefined; - expect(gdprDataHandler.ready).to.be.true; - done(); - }, 20); }); it('It still considers it a valid cmp response if gdprApplies is not a boolean', function () { diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js index b70cd6fe631..f0b02913f96 100644 --- a/test/spec/modules/consumableBidAdapter_spec.js +++ b/test/spec/modules/consumableBidAdapter_spec.js @@ -177,69 +177,6 @@ const AD_SERVER_RESPONSE = { } }; -const AD_SERVER_RESPONSE_2 = { - 'headers': null, - 'body': { - 'user': { 'key': 'ue1-2d33e91b71e74929b4aeecc23f4376f1' }, - 'pixels': [{ 'type': 'image', 'url': '//sync.serverbid.com/ss/' }], - 'bdr': 'notcx', - 'decisions': { - '2b0f82502298c9': { - 'adId': 2364764, - 'creativeId': 1950991, - 'flightId': 2788300, - 'campaignId': 542982, - 'clickUrl': 'https://e.serverbid.com/r', - 'impressionUrl': 'https://e.serverbid.com/i.gif', - 'contents': [{ - 'type': 'html', - 'body': '', - 'data': { - 'height': 90, - 'width': 728, - 'imageUrl': 'https://static.adzerk.net/Advertisers/b0ab77db8a7848c8b78931aed022a5ef.gif', - 'fileName': 'b0ab77db8a7848c8b78931aed022a5ef.gif' - }, - 'template': 'image' - }], - 'height': 90, - 'width': 728, - 'events': [], - 'pricing': {'price': 0.5, 'clearPrice': 0.5, 'revenue': 0.0005, 'rateType': 2, 'eCPM': 0.5}, - 'mediaType': 'banner', - 'cats': ['IAB1', 'IAB2', 'IAB3'], - 'networkId': 1234567, - }, - '123': { - 'adId': 2364764, - 'creativeId': 1950991, - 'flightId': 2788300, - 'campaignId': 542982, - 'clickUrl': 'https://e.serverbid.com/r', - 'impressionUrl': 'https://e.serverbid.com/i.gif', - 'contents': [{ - 'type': 'html', - 'body': '', - 'data': { - 'height': 90, - 'width': 728, - 'imageUrl': 'https://static.adzerk.net/Advertisers/b0ab77db8a7848c8b78931aed022a5ef.gif', - 'fileName': 'b0ab77db8a7848c8b78931aed022a5ef.gif' - }, - 'template': 'image' - }], - 'height': 90, - 'width': 728, - 'events': [], - 'pricing': {'price': 0.5, 'clearPrice': 0.5, 'revenue': 0.0005, 'rateType': 2, 'eCPM': 0.5}, - 'mediaType': 'banner', - 'cats': ['IAB1', 'IAB2'], - 'networkId': 2345678, - } - } - } -}; - const BUILD_REQUESTS_OUTPUT = { method: 'POST', url: 'https://e.serverbid.com/api/v2', @@ -348,7 +285,7 @@ describe('Consumable BidAdapter', function () { }); it('registers bids', function () { - let bids = spec.interpretResponse(AD_SERVER_RESPONSE_2, BUILD_REQUESTS_OUTPUT); + let bids = spec.interpretResponse(AD_SERVER_RESPONSE, BUILD_REQUESTS_OUTPUT); bids.forEach(b => { expect(b).to.have.property('cpm'); expect(b.cpm).to.be.above(0); @@ -362,13 +299,9 @@ describe('Consumable BidAdapter', function () { expect(b).to.have.property('currency', 'USD'); expect(b).to.have.property('creativeId'); expect(b).to.have.property('ttl', 30); + expect(b.meta).to.have.property('advertiserDomains'); expect(b).to.have.property('netRevenue', true); expect(b).to.have.property('referrer'); - expect(b.meta).to.have.property('advertiserDomains'); - expect(b.meta).to.have.property('primaryCatId'); - expect(b.meta).to.have.property('secondaryCatIds'); - expect(b.meta).to.have.property('networkId'); - expect(b.meta).to.have.property('mediaType'); }); }); @@ -400,24 +333,6 @@ describe('Consumable BidAdapter', function () { expect(opts.length).to.equal(1); }); - it('should return a sync url if iframe syncs are enabled and server response is empty', function () { - let opts = spec.getUserSyncs(syncOptions, []); - - expect(opts.length).to.equal(1); - }); - - it('should return a sync url if iframe syncs are enabled and server response does not contain a bdr attribute', function () { - let opts = spec.getUserSyncs(syncOptions, [AD_SERVER_RESPONSE]); - - expect(opts.length).to.equal(1); - }); - - it('should return a sync url if iframe syncs are enabled and server response contains a bdr attribute that is not cx', function () { - let opts = spec.getUserSyncs(syncOptions, [AD_SERVER_RESPONSE_2]); - - expect(opts.length).to.equal(1); - }); - it('should return a sync url if pixel syncs are enabled and some are returned from the server', function () { let syncOptions = {'pixelEnabled': true}; let opts = spec.getUserSyncs(syncOptions, [AD_SERVER_RESPONSE]); diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index 53169326d3b..e871ab3f9c6 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -2,8 +2,6 @@ import {expect} from 'chai'; import {spec, storage} from 'modules/conversantBidAdapter.js'; import * as utils from 'src/utils.js'; import {createEidsArray} from 'modules/userId/eids.js'; -import { config } from '../../../src/config.js'; -import {deepAccess} from 'src/utils'; describe('Conversant adapter tests', function() { const siteId = '108060'; @@ -121,34 +119,7 @@ describe('Conversant adapter tests', function() { bidId: 'bid005', bidderRequestId: '117d765b87bed38', auctionId: 'req000' - }, - // video with first party data - { - bidder: 'conversant', - params: { - site_id: siteId - }, - mediaTypes: { - video: { - context: 'instream', - mimes: ['video/mp4', 'video/x-flv'] - } - }, - ortb2Imp: { - instl: 1, - ext: { - data: { - pbadslot: 'homepage-top-rect' - } - } - }, - placementCode: 'pcode006', - transactionId: 'tx006', - bidId: 'bid006', - bidderRequestId: '117d765b87bed38', - auctionId: 'req000' - } - ]; + }]; const bidResponses = { body: { @@ -245,7 +216,7 @@ describe('Conversant adapter tests', function() { expect(payload).to.have.property('id', 'req000'); expect(payload).to.have.property('at', 1); expect(payload).to.have.property('imp'); - expect(payload.imp).to.be.an('array').with.lengthOf(7); + expect(payload.imp).to.be.an('array').with.lengthOf(6); expect(payload.imp[0]).to.have.property('id', 'bid000'); expect(payload.imp[0]).to.have.property('secure', 1); @@ -335,16 +306,6 @@ describe('Conversant adapter tests', function() { expect(payload.imp[5].video).to.not.have.property('maxduration'); expect(payload.imp[5]).to.not.have.property('banner'); - expect(payload.imp[6]).to.have.property('id', 'bid006'); - expect(payload.imp[6]).to.have.property('video'); - expect(payload.imp[6].video).to.have.property('mimes'); - expect(payload.imp[6].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); - expect(payload.imp[6]).to.not.have.property('banner'); - expect(payload.imp[6]).to.have.property('instl'); - expect(payload.imp[6]).to.have.property('ext'); - expect(payload.imp[6].ext).to.have.property('data'); - expect(payload.imp[6].ext.data).to.have.property('pbadslot'); - expect(payload).to.have.property('site'); expect(payload.site).to.have.property('id', siteId); expect(payload.site).to.have.property('mobile').that.is.oneOf([0, 1]); @@ -360,34 +321,6 @@ describe('Conversant adapter tests', function() { expect(payload).to.not.have.property('user'); // there should be no user by default }); - it('Verify first party data', () => { - const bidderRequest = {refererInfo: {referer: 'http://test.com?a=b&c=123'}}; - const cfg = {ortb2: {site: {content: {series: 'MySeries', season: 'MySeason', episode: 3, title: 'MyTitle'}}}}; - config.setConfig(cfg); - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = request.data; - expect(payload.site).to.have.property('content'); - expect(payload.site.content).to.have.property('series'); - expect(payload.site.content).to.have.property('season'); - expect(payload.site.content).to.have.property('episode'); - expect(payload.site.content).to.have.property('title'); - config.resetConfig(); - }); - - it('Verify supply chain data', () => { - const bidderRequest = {refererInfo: {referer: 'http://test.com?a=b&c=123'}}; - const schain = {complete: 1, ver: '1.0', nodes: [{asi: 'bidderA.com', sid: '00001', hp: 1}]}; - const bidsWithSchain = bidRequests.map((bid) => { - return Object.assign({ - schain: schain - }, bid); - }); - const request = spec.buildRequests(bidsWithSchain, bidderRequest); - const payload = request.data; - expect(deepAccess(payload, 'source.ext.schain.nodes')).to.exist; - expect(payload.source.ext.schain.nodes[0].asi).equals(schain.nodes[0].asi); - }); - it('Verify override url', function() { const testUrl = 'https://someurl?name=value'; const request = spec.buildRequests([{params: {white_label_url: testUrl}}]); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 57276759a35..7ec6972e1a5 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -23,7 +23,7 @@ describe('The Criteo bidding adapter', function () { sandbox = sinon.sandbox.create(); }); - afterEach(function () { + afterEach(function() { global.Criteo = undefined; utilsMock.restore(); sandbox.restore(); @@ -430,11 +430,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, + sizes: [[728, 90]], params: {} }, ]; @@ -449,15 +445,11 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, + sizes: [[728, 90]], params: { zoneId: 123, publisherSubId: '123', - nativeCallback: function () { }, + nativeCallback: function() {}, integrationMode: 'amp' }, }, @@ -481,11 +473,7 @@ describe('The Criteo bidding adapter', function () { it('should keep undefined sizes for non native banner', function () { const bidRequests = [ { - mediaTypes: { - banner: { - sizes: [[undefined, undefined]] - } - }, + sizes: [[undefined, undefined]], params: {}, }, ]; @@ -498,11 +486,7 @@ describe('The Criteo bidding adapter', function () { it('should keep undefined size for non native banner', function () { const bidRequests = [ { - mediaTypes: { - banner: { - sizes: [undefined, undefined] - } - }, + sizes: [undefined, undefined], params: {}, }, ]; @@ -515,13 +499,9 @@ describe('The Criteo bidding adapter', function () { it('should properly detect and get sizes of native sizeless banner', function () { const bidRequests = [ { - mediaTypes: { - banner: { - sizes: [[undefined, undefined]] - } - }, + sizes: [[undefined, undefined]], params: { - nativeCallback: function () { } + nativeCallback: function() {} }, }, ]; @@ -534,13 +514,9 @@ describe('The Criteo bidding adapter', function () { it('should properly detect and get size of native sizeless banner', function () { const bidRequests = [ { - mediaTypes: { - banner: { - sizes: [undefined, undefined] - } - }, + sizes: [undefined, undefined], params: { - nativeCallback: function () { } + nativeCallback: function() {} }, }, ]; @@ -609,11 +585,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, + sizes: [[728, 90]], params: { zoneId: 123, }, @@ -622,11 +594,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-234', transactionId: 'transaction-234', - mediaTypes: { - banner: { - sizes: [[300, 250], [728, 90]] - } - }, + sizes: [[300, 250], [728, 90]], params: { networkId: 456, }, @@ -657,11 +625,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, + sizes: [[728, 90]], params: { zoneId: 123, }, @@ -683,11 +647,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, + sizes: [[728, 90]], params: { zoneId: 123, }, @@ -703,42 +663,13 @@ describe('The Criteo bidding adapter', function () { expect(request.data.user.uspIab).to.equal('1YNY'); }); - it('should properly build a request with schain object', function () { - const expectedSchain = { - someProperty: 'someValue' - }; - const bidRequests = [ - { - bidder: 'criteo', - schain: expectedSchain, - adUnitCode: 'bid-123', - transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, - params: { - zoneId: 123, - }, - }, - ]; - - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.source.ext.schain).to.equal(expectedSchain); - }); - it('should properly build a request with if ccpa consent field is not provided', function () { const bidRequests = [ { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, + sizes: [[728, 90]], params: { zoneId: 123, }, @@ -759,7 +690,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - sizes: [[640, 480]], + sizes: [[728, 90]], mediaTypes: { video: { playerSize: [640, 480], @@ -786,7 +717,6 @@ describe('The Criteo bidding adapter', function () { expect(request.method).to.equal('POST'); const ortbRequest = request.data; expect(ortbRequest.slots[0].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); - expect(ortbRequest.slots[0].sizes).to.deep.equal([]); expect(ortbRequest.slots[0].video.playersizes).to.deep.equal(['640x480']); expect(ortbRequest.slots[0].video.maxduration).to.equal(30); expect(ortbRequest.slots[0].video.api).to.deep.equal([1, 2]); @@ -804,7 +734,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - sizes: [[640, 480], [800, 600]], + sizes: [[728, 90]], mediaTypes: { video: { playerSize: [[640, 480], [800, 600]], @@ -830,7 +760,6 @@ describe('The Criteo bidding adapter', function () { expect(request.url).to.match(/^https:\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; - expect(ortbRequest.slots[0].sizes).to.deep.equal([]); expect(ortbRequest.slots[0].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); expect(ortbRequest.slots[0].video.playersizes).to.deep.equal(['640x480', '800x600']); expect(ortbRequest.slots[0].video.maxduration).to.equal(30); @@ -843,56 +772,13 @@ describe('The Criteo bidding adapter', function () { expect(ortbRequest.slots[0].video.placement).to.equal(2); }); - it('should properly build a video request when mediaTypes.video.skip=0', function () { - const bidRequests = [ - { - bidder: 'criteo', - adUnitCode: 'bid-123', - transactionId: 'transaction-123', - sizes: [[300, 250]], - mediaTypes: { - video: { - playerSize: [[300, 250]], - mimes: ['video/mp4', 'video/MPV', 'video/H264', 'video/webm', 'video/ogg'], - minduration: 1, - maxduration: 30, - playbackmethod: [2, 3, 4, 5, 6], - api: [1, 2, 3, 4, 5, 6], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - skip: 0 - } - }, - params: { - networkId: 123 - } - } - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^https:\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); - expect(request.method).to.equal('POST'); - const ortbRequest = request.data; - expect(ortbRequest.slots[0].sizes).to.deep.equal([]); - expect(ortbRequest.slots[0].video.playersizes).to.deep.equal(['300x250']); - expect(ortbRequest.slots[0].video.mimes).to.deep.equal(['video/mp4', 'video/MPV', 'video/H264', 'video/webm', 'video/ogg']); - expect(ortbRequest.slots[0].video.minduration).to.equal(1); - expect(ortbRequest.slots[0].video.maxduration).to.equal(30); - expect(ortbRequest.slots[0].video.playbackmethod).to.deep.equal([2, 3, 4, 5, 6]); - expect(ortbRequest.slots[0].video.api).to.deep.equal([1, 2, 3, 4, 5, 6]); - expect(ortbRequest.slots[0].video.protocols).to.deep.equal([1, 2, 3, 4, 5, 6, 7, 8]); - expect(ortbRequest.slots[0].video.skip).to.equal(0); - }); - it('should properly build a request with ceh', function () { const bidRequests = [ { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, + sizes: [[728, 90]], params: { zoneId: 123, }, @@ -914,11 +800,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, + sizes: [[728, 90]], params: { zoneId: 123 } @@ -943,11 +825,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, + sizes: [[728, 90]], params: { zoneId: 123, ext: { @@ -970,7 +848,7 @@ describe('The Criteo bidding adapter', function () { }); it('should properly build a request with first party data', function () { - const siteData = { + const contextData = { keywords: ['power tools'], ext: { data: { @@ -991,11 +869,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, + sizes: [[728, 90]], params: { zoneId: 123, ext: { @@ -1015,7 +889,7 @@ describe('The Criteo bidding adapter', function () { sandbox.stub(config, 'getConfig').callsFake(key => { const config = { ortb2: { - site: siteData, + site: contextData, user: userData } }; @@ -1023,8 +897,8 @@ describe('The Criteo bidding adapter', function () { }); const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.publisher.ext).to.deep.equal({ data: { pageType: 'article' } }); - expect(request.data.user.ext).to.deep.equal({ data: { registered: true } }); + expect(request.data.publisher.ext).to.deep.equal({keywords: ['power tools'], data: {pageType: 'article'}}); + expect(request.data.user.ext).to.deep.equal({gender: 'M', data: {registered: true}}); expect(request.data.slots[0].ext).to.deep.equal({ bidfloor: 0.75, data: { @@ -1171,13 +1045,13 @@ describe('The Criteo bidding adapter', function () { 'advertiser': { 'description': 'sponsor', 'domain': 'criteo.com', - 'logo': { 'url': 'https://www.criteo.com/images/criteo-logo.svg', 'height': 300, 'width': 300 } + 'logo': {'url': 'https://www.criteo.com/images/criteo-logo.svg', 'height': 300, 'width': 300} }, 'privacy': { 'optout_click_url': 'https://info.criteo.com/privacy/informations', 'optout_image_url': 'https://static.criteo.net/flash/icon/nai_small.png', }, - 'impression_pixels': [{ 'url': 'https://my-impression-pixel/test/impression' }, { 'url': 'https://cas.com/lg.com' }] + 'impression_pixels': [{'url': 'https://my-impression-pixel/test/impression'}, {'url': 'https://cas.com/lg.com'}] } }], }, @@ -1201,7 +1075,7 @@ describe('The Criteo bidding adapter', function () { }); it('should warn only once if sendTargetingKeys set to true on required fields for native bidRequest', () => { - const bidderRequest = {}; + const bidderRequest = { }; const bidRequests = [ { bidder: 'criteo', @@ -1211,7 +1085,7 @@ describe('The Criteo bidding adapter', function () { params: { zoneId: 123, publisherSubId: '123', - nativeCallback: function () { } + nativeCallback: function() {} }, }, { @@ -1222,7 +1096,7 @@ describe('The Criteo bidding adapter', function () { params: { zoneId: 456, publisherSubId: '456', - nativeCallback: function () { } + nativeCallback: function() {} }, }, ]; @@ -1276,7 +1150,7 @@ describe('The Criteo bidding adapter', function () { .withArgs('Criteo: all native assets containing URL should be sent as placeholders with sendId(icon, image, clickUrl, displayUrl, privacyLink, privacyIcon)') .exactly(nativeParamsWithSendTargetingKeys.length * bidRequests.length); nativeParamsWithSendTargetingKeys.forEach(nativeParams => { - let transformedBidRequests = { ...bidRequests }; + let transformedBidRequests = {...bidRequests}; transformedBidRequests = [Object.assign(transformedBidRequests[0], nativeParams), Object.assign(transformedBidRequests[1], nativeParams)]; spec.buildRequests(transformedBidRequests, bidderRequest); }); @@ -1440,7 +1314,7 @@ describe('The Criteo bidding adapter', function () { describe('when pubtag prebid adapter is not available', function () { it('should not warn if sendId is provided on required fields for native bidRequest', () => { - const bidderRequest = {}; + const bidderRequest = { }; const bidRequestsWithSendId = [ { bidder: 'criteo', @@ -1450,7 +1324,7 @@ describe('The Criteo bidding adapter', function () { params: { zoneId: 123, publisherSubId: '123', - nativeCallback: function () { } + nativeCallback: function() {} }, nativeParams: { image: { @@ -1481,7 +1355,7 @@ describe('The Criteo bidding adapter', function () { }); it('should warn only once if sendId is not provided on required fields for native bidRequest', () => { - const bidderRequest = {}; + const bidderRequest = { }; const bidRequests = [ { bidder: 'criteo', @@ -1491,7 +1365,7 @@ describe('The Criteo bidding adapter', function () { params: { zoneId: 123, publisherSubId: '123', - nativeCallback: function () { } + nativeCallback: function() {} }, }, { @@ -1502,7 +1376,7 @@ describe('The Criteo bidding adapter', function () { params: { zoneId: 456, publisherSubId: '456', - nativeCallback: function () { } + nativeCallback: function() {} }, }, ]; @@ -1556,7 +1430,7 @@ describe('The Criteo bidding adapter', function () { .withArgs('Criteo: all native assets containing URL should be sent as placeholders with sendId(icon, image, clickUrl, displayUrl, privacyLink, privacyIcon)') .exactly(nativeParamsWithoutSendId.length * bidRequests.length); nativeParamsWithoutSendId.forEach(nativeParams => { - let transformedBidRequests = { ...bidRequests }; + let transformedBidRequests = {...bidRequests}; transformedBidRequests = [Object.assign(transformedBidRequests[0], nativeParams), Object.assign(transformedBidRequests[1], nativeParams)]; spec.buildRequests(transformedBidRequests, bidderRequest); }); @@ -1569,10 +1443,10 @@ describe('The Criteo bidding adapter', function () { const response = {}; const request = {}; - const adapter = { interpretResponse: function () { } }; + const adapter = { interpretResponse: function() {} }; const adapterMock = sinon.mock(adapter); adapterMock.expects('interpretResponse').withExactArgs(response, request).once().returns('ok'); - const prebidAdapter = { GetAdapter: function () { } }; + const prebidAdapter = { GetAdapter: function() {} }; const prebidAdapterMock = sinon.mock(prebidAdapter); prebidAdapterMock.expects('GetAdapter').withExactArgs(request).once().returns(adapter); @@ -1592,10 +1466,10 @@ describe('The Criteo bidding adapter', function () { it('should forward bid to pubtag when calling onBidWon', () => { const bid = { auctionId: 123 }; - const adapter = { handleBidWon: function () { } }; + const adapter = { handleBidWon: function() {} }; const adapterMock = sinon.mock(adapter); adapterMock.expects('handleBidWon').withExactArgs(bid).once(); - const prebidAdapter = { GetAdapter: function () { } }; + const prebidAdapter = { GetAdapter: function() {} }; const prebidAdapterMock = sinon.mock(prebidAdapter); prebidAdapterMock.expects('GetAdapter').withExactArgs(bid.auctionId).once().returns(adapter); @@ -1615,10 +1489,10 @@ describe('The Criteo bidding adapter', function () { it('should forward bid to pubtag when calling onSetTargeting', () => { const bid = { auctionId: 123 }; - const adapter = { handleSetTargeting: function () { } }; + const adapter = { handleSetTargeting: function() {} }; const adapterMock = sinon.mock(adapter); adapterMock.expects('handleSetTargeting').withExactArgs(bid).once(); - const prebidAdapter = { GetAdapter: function () { } }; + const prebidAdapter = { GetAdapter: function() {} }; const prebidAdapterMock = sinon.mock(prebidAdapter); prebidAdapterMock.expects('GetAdapter').withExactArgs(bid.auctionId).once().returns(adapter); @@ -1638,10 +1512,10 @@ describe('The Criteo bidding adapter', function () { it('should forward bid to pubtag when calling onTimeout', () => { const timeoutData = [{ auctionId: 123 }]; - const adapter = { handleBidTimeout: function () { } }; + const adapter = { handleBidTimeout: function() {} }; const adapterMock = sinon.mock(adapter); adapterMock.expects('handleBidTimeout').once(); - const prebidAdapter = { GetAdapter: function () { } }; + const prebidAdapter = { GetAdapter: function() {} }; const prebidAdapterMock = sinon.mock(prebidAdapter); prebidAdapterMock.expects('GetAdapter').withExactArgs(timeoutData[0].auctionId).once().returns(adapter); @@ -1659,15 +1533,15 @@ describe('The Criteo bidding adapter', function () { }); it('should return a POST method with url & data from pubtag', () => { - const bidRequests = {}; - const bidderRequest = {}; + const bidRequests = { }; + const bidderRequest = { }; - const prebidAdapter = { buildCdbUrl: function () { }, buildCdbRequest: function () { } }; + const prebidAdapter = { buildCdbUrl: function() {}, buildCdbRequest: function() {} }; const prebidAdapterMock = sinon.mock(prebidAdapter); prebidAdapterMock.expects('buildCdbUrl').once().returns('cdbUrl'); prebidAdapterMock.expects('buildCdbRequest').once().returns('cdbRequest'); - const adapters = { Prebid: function () { } }; + const adapters = { Prebid: function() {} }; const adaptersMock = sinon.mock(adapters); adaptersMock.expects('Prebid').withExactArgs(PROFILE_ID_PUBLISHERTAG, ADAPTER_VERSION, bidRequests, bidderRequest, '$prebid.version$').once().returns(prebidAdapter); diff --git a/test/spec/modules/criteoIdSystem_spec.js b/test/spec/modules/criteoIdSystem_spec.js index d50eadebb55..65e5aaf741d 100644 --- a/test/spec/modules/criteoIdSystem_spec.js +++ b/test/spec/modules/criteoIdSystem_spec.js @@ -1,9 +1,15 @@ import { criteoIdSubmodule, storage } from 'modules/criteoIdSystem.js'; import * as utils from 'src/utils.js'; -import {server} from '../../mocks/xhr'; +import * as ajaxLib from 'src/ajax.js'; const pastDateString = new Date(0).toString() +function mockResponse(responseText, fakeResponse = (url, callback) => callback(responseText)) { + return function() { + return fakeResponse; + } +} + describe('CriteoId module', function () { const cookiesMaxAge = 13 * 30 * 24 * 60 * 60 * 1000; @@ -16,6 +22,7 @@ describe('CriteoId module', function () { let removeFromLocalStorageStub; let timeStampStub; let parseUrlStub; + let ajaxBuilderStub; let triggerPixelStub; beforeEach(function (done) { @@ -25,6 +32,7 @@ describe('CriteoId module', function () { setLocalStorageStub = sinon.stub(storage, 'setDataInLocalStorage'); removeFromLocalStorageStub = sinon.stub(storage, 'removeDataFromLocalStorage'); timeStampStub = sinon.stub(utils, 'timestamp').returns(nowTimestamp); + ajaxBuilderStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockResponse('{}')); parseUrlStub = sinon.stub(utils, 'parseUrl').returns({protocol: 'https', hostname: 'testdev.com'}) triggerPixelStub = sinon.stub(utils, 'triggerPixel'); done(); @@ -37,6 +45,7 @@ describe('CriteoId module', function () { setLocalStorageStub.restore(); removeFromLocalStorageStub.restore(); timeStampStub.restore(); + ajaxBuilderStub.restore(); triggerPixelStub.restore(); parseUrlStub.restore(); }); @@ -52,9 +61,8 @@ describe('CriteoId module', function () { getCookieStub.withArgs('cto_bidid').returns(testCase.cookie); getLocalStorageStub.withArgs('cto_bidid').returns(testCase.localStorage); - const result = criteoIdSubmodule.getId(); - expect(result.id).to.be.deep.equal(testCase.expected ? { criteoId: testCase.expected } : undefined); - expect(result.callback).to.be.a('function'); + const id = criteoIdSubmodule.getId(); + expect(id).to.be.deep.equal({id: testCase.expected ? { criteoId: testCase.expected } : undefined}); })) it('decode() should return the bidId when it exists in local storages', function () { @@ -66,21 +74,16 @@ describe('CriteoId module', function () { getCookieStub.withArgs('cto_bundle').returns('bundle'); window.criteo_pubtag = {} - let callBackSpy = sinon.spy(); - let result = criteoIdSubmodule.getId(); - result.callback(callBackSpy); + const emptyObj = '{}'; + let ajaxStub = sinon.stub().callsFake((url, callback) => callback(emptyObj)); + ajaxBuilderStub.callsFake(mockResponse(undefined, ajaxStub)) + criteoIdSubmodule.getId(); const expectedUrl = `https://gum.criteo.com/sid/json?origin=prebid&topUrl=https%3A%2F%2Ftestdev.com%2F&domain=testdev.com&bundle=bundle&cw=1&pbt=1&lsw=1`; - let request = server.requests[0]; - expect(request.url).to.be.eq(expectedUrl); + expect(ajaxStub.calledWith(expectedUrl)).to.be.true; - request.respond( - 200, - {'Content-Type': 'application/json'}, - JSON.stringify({}) - ); - expect(callBackSpy.calledOnce).to.be.true; + window.criteo_pubtag = undefined; }); const responses = [ @@ -98,37 +101,31 @@ describe('CriteoId module', function () { responses.forEach(response => describe('test user sync response behavior', function () { const expirationTs = new Date(nowTimestamp + cookiesMaxAge).toString(); - it('should save bidId if it exists', function () { - const result = criteoIdSubmodule.getId(); - result.callback((id) => { - expect(id).to.be.deep.equal(response.bidId ? { criteoId: response.bidId } : undefined); - }); - - let request = server.requests[0]; - request.respond( - 200, - {'Content-Type': 'application/json'}, - JSON.stringify(response) - ); + beforeEach(function (done) { + const fakeResponse = (url, callback) => { + callback(JSON.stringify(response)); + setTimeout(done, 0); + } + ajaxBuilderStub.callsFake(mockResponse(undefined, fakeResponse)); + criteoIdSubmodule.getId(); + }) + it('should save bidId if it exists', function () { if (response.acwsUrl) { expect(triggerPixelStub.called).to.be.true; expect(setCookieStub.calledWith('cto_bundle')).to.be.false; expect(setLocalStorageStub.calledWith('cto_bundle')).to.be.false; } else if (response.bundle) { - expect(setCookieStub.calledWith('cto_bundle', response.bundle, expirationTs, null, '.com')).to.be.true; - expect(setCookieStub.calledWith('cto_bundle', response.bundle, expirationTs, null, '.testdev.com')).to.be.true; + expect(setCookieStub.calledWith('cto_bundle', response.bundle, expirationTs)).to.be.true; expect(setLocalStorageStub.calledWith('cto_bundle', response.bundle)).to.be.true; expect(triggerPixelStub.called).to.be.false; } if (response.bidId) { - expect(setCookieStub.calledWith('cto_bidid', response.bidId, expirationTs, null, '.com')).to.be.true; - expect(setCookieStub.calledWith('cto_bidid', response.bidId, expirationTs, null, '.testdev.com')).to.be.true; + expect(setCookieStub.calledWith('cto_bidid', response.bidId, expirationTs)).to.be.true; expect(setLocalStorageStub.calledWith('cto_bidid', response.bidId)).to.be.true; } else { - expect(setCookieStub.calledWith('cto_bidid', '', pastDateString, null, '.com')).to.be.true; - expect(setCookieStub.calledWith('cto_bidid', '', pastDateString, null, '.testdev.com')).to.be.true; + expect(setCookieStub.calledWith('cto_bidid', '', pastDateString)).to.be.true; expect(removeFromLocalStorageStub.calledWith('cto_bidid')).to.be.true; } }); @@ -143,23 +140,16 @@ describe('CriteoId module', function () { ]; gdprConsentTestCases.forEach(testCase => it('should call user sync url with the gdprConsent', function () { - let callBackSpy = sinon.spy(); - let result = criteoIdSubmodule.getId(undefined, testCase.consentData); - result.callback(callBackSpy); + const emptyObj = '{}'; + let ajaxStub = sinon.stub().callsFake((url, callback) => callback(emptyObj)); + ajaxBuilderStub.callsFake(mockResponse(undefined, ajaxStub)) + + criteoIdSubmodule.getId(undefined, testCase.consentData); - let request = server.requests[0]; if (testCase.expected) { - expect(request.url).to.have.string(`gdprString=${testCase.expected}`); + expect(ajaxStub.calledWithMatch(`gdprString=${testCase.expected}`)).to.be.true; } else { - expect(request.url).to.not.have.string('gdprString'); + expect(ajaxStub.calledWithMatch('gdprString')).not.to.be.true; } - - request.respond( - 200, - {'Content-Type': 'application/json'}, - JSON.stringify({}) - ); - - expect(callBackSpy.calledOnce).to.be.true; })); }); diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index 928c252943c..ccd205964a9 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -9,11 +9,8 @@ import { setConfig, addBidResponseHook, currencySupportEnabled, - currencyRates, - ready + currencyRates } from 'modules/currency.js'; -import {createBid} from '../../../src/bidfactory.js'; -import CONSTANTS from '../../../src/constants.json'; var assert = require('chai').assert; var expect = require('chai').expect; @@ -25,13 +22,8 @@ describe('currency', function () { let fn = sinon.spy(); - function makeBid(bidProps) { - return Object.assign(createBid(CONSTANTS.STATUS.GOOD), bidProps); - } - beforeEach(function () { fakeCurrencyFileServer = sinon.fakeServer.create(); - ready.reset(); }); afterEach(function () { @@ -294,7 +286,7 @@ describe('currency', function () { }); describe('currency.addBidResponseDecorator bidResponseQueue', function () { - it('not run until currency rates file is loaded', function (done) { + it('not run until currency rates file is loaded', function () { setConfig({}); fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); @@ -304,34 +296,21 @@ describe('currency', function () { setConfig({ 'adServerCurrency': 'JPY' }); var marker = false; - let promiseResolved = false; - addBidResponseHook(Object.assign(function() { + addBidResponseHook(function() { marker = true; - }, { - bail: function (promise) { - promise.then(() => promiseResolved = true); - } - }), 'elementId', bid); + }, 'elementId', bid); expect(marker).to.equal(false); - setTimeout(() => { - expect(promiseResolved).to.be.false; - fakeCurrencyFileServer.respond(); - - setTimeout(() => { - expect(marker).to.equal(true); - expect(promiseResolved).to.be.true; - done(); - }); - }); + fakeCurrencyFileServer.respond(); + expect(marker).to.equal(true); }); }); describe('currency.addBidResponseDecorator', function () { it('should leave bid at 1 when currency support is not enabled and fromCurrency is USD', function () { setConfig({}); - var bid = makeBid({ 'cpm': 1, 'currency': 'USD' }); + var bid = { 'cpm': 1, 'currency': 'USD' }; var innerBid; addBidResponseHook(function(adCodeId, bid) { innerBid = bid; @@ -342,7 +321,7 @@ describe('currency', function () { it('should result in NO_BID when currency support is not enabled and fromCurrency is not USD', function () { setConfig({}); - var bid = makeBid({ 'cpm': 1, 'currency': 'GBP' }); + var bid = { 'cpm': 1, 'currency': 'GBP' }; var innerBid; addBidResponseHook(function(adCodeId, bid) { innerBid = bid; @@ -354,7 +333,7 @@ describe('currency', function () { setConfig({ 'adServerCurrency': 'USD' }); - var bid = makeBid({ 'cpm': 1, 'currency': 'USD' }); + var bid = { 'cpm': 1, 'currency': 'USD' }; var innerBid; addBidResponseHook(function(adCodeId, bid) { innerBid = bid; @@ -369,7 +348,7 @@ describe('currency', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'JPY' }); fakeCurrencyFileServer.respond(); - var bid = makeBid({ 'cpm': 1, 'currency': 'ABC' }); + var bid = { 'cpm': 1, 'currency': 'ABC' }; var innerBid; addBidResponseHook(function(adCodeId, bid) { innerBid = bid; @@ -381,7 +360,7 @@ describe('currency', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'ABC' }); fakeCurrencyFileServer.respond(); - var bid = makeBid({ 'cpm': 1, 'currency': 'GBP' }); + var bid = { 'cpm': 1, 'currency': 'GBP' }; var innerBid; addBidResponseHook(function(adCodeId, bid) { innerBid = bid; @@ -393,7 +372,7 @@ describe('currency', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'JPY' }); fakeCurrencyFileServer.respond(); - var bid = makeBid({ 'cpm': 1, 'currency': 'JPY' }); + var bid = { 'cpm': 1, 'currency': 'JPY' }; var innerBid; addBidResponseHook(function(adCodeId, bid) { innerBid = bid; @@ -406,7 +385,7 @@ describe('currency', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'GBP' }); fakeCurrencyFileServer.respond(); - var bid = makeBid({ 'cpm': 1, 'currency': 'USD' }); + var bid = { 'cpm': 1, 'currency': 'USD' }; var innerBid; addBidResponseHook(function(adCodeId, bid) { innerBid = bid; @@ -419,7 +398,7 @@ describe('currency', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'GBP' }); fakeCurrencyFileServer.respond(); - var bid = makeBid({ 'cpm': 1, 'currency': 'CNY' }); + var bid = { 'cpm': 1, 'currency': 'CNY' }; var innerBid; addBidResponseHook(function(adCodeId, bid) { innerBid = bid; @@ -432,7 +411,7 @@ describe('currency', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'CNY' }); fakeCurrencyFileServer.respond(); - var bid = makeBid({ 'cpm': 1, 'currency': 'JPY' }); + var bid = { 'cpm': 1, 'currency': 'JPY' }; var innerBid; addBidResponseHook(function(adCodeId, bid) { innerBid = bid; diff --git a/test/spec/modules/cwireBidAdapter_spec.js b/test/spec/modules/cwireBidAdapter_spec.js deleted file mode 100644 index b21e73e1561..00000000000 --- a/test/spec/modules/cwireBidAdapter_spec.js +++ /dev/null @@ -1,369 +0,0 @@ -import { expect } from 'chai'; -import * as utils from '../../../src/utils.js'; -import { config } from '../../../src/config.js'; -import { - spec, - CW_PAGE_VIEW_ID, - ENDPOINT_URL, - RENDERER_URL, -} from '../../../modules/cwireBidAdapter.js'; -import * as prebidGlobal from 'src/prebidGlobal.js'; - -// ------------------------------------ -// Bid Request Builder -// ------------------------------------ - -const BID_DEFAULTS = { - request: { - bidder: 'cwire', - auctionId: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee', - transactionId: 'txaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee', - bidId: 'bid123445', - bidderRequestId: 'brid12345', - code: 'original-div', - }, - params: { - placementId: 123456, - pageId: 777, - }, - sizes: [[300, 250], [1, 1]], -}; - -const BidderRequestBuilder = function BidderRequestBuilder(options) { - const defaults = { - bidderCode: 'cwire', - auctionId: BID_DEFAULTS.request.auctionId, - bidderRequestId: BID_DEFAULTS.request.bidderRequestId, - transactionId: BID_DEFAULTS.request.transactionId, - timeout: 3000, - }; - - const request = { - ...defaults, - ...options - }; - - this.build = () => request; -}; - -const BidRequestBuilder = function BidRequestBuilder(options, deleteKeys) { - const defaults = JSON.parse(JSON.stringify(BID_DEFAULTS)); - - const request = { - ...defaults.request, - ...options - }; - - if (request && utils.isArray(deleteKeys)) { - deleteKeys.forEach((k) => { - delete request[k]; - }) - } - - this.withParams = (options, deleteKeys) => { - request.params = { - ...defaults.params, - ...options - }; - if (request && utils.isArray(deleteKeys)) { - deleteKeys.forEach((k) => { - delete request.params[k]; - }) - } - return this; - }; - - this.build = () => request; -}; - -describe('C-WIRE bid adapter', () => { - let sandbox; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - }); - - afterEach(() => { - sandbox.restore(); - config.resetConfig(); - }); - - // START TESTING - describe('C-WIRE - isBidRequestValid', function () { - it('should return true when required params found', function () { - const bid01 = new BidRequestBuilder().withParams().build(); - expect(spec.isBidRequestValid(bid01)).to.equal(true); - }); - - it('should fail if there is no placementId', function () { - const bid01 = new BidRequestBuilder().withParams().build(); - delete bid01.params.placementId - expect(spec.isBidRequestValid(bid01)).to.equal(false); - }); - - it('should fail if invalid placementId type', function () { - const bid01 = new BidRequestBuilder().withParams().build(); - delete bid01.params.placementId; - bid01.placementId = '322'; - expect(spec.isBidRequestValid(bid01)).to.equal(false); - }); - - it('should fail if there is no pageId', function () { - const bid01 = new BidRequestBuilder().withParams().build(); - delete bid01.params.pageId - expect(spec.isBidRequestValid(bid01)).to.equal(false); - }); - - it('should fail if invalid pageId type', function () { - const bid01 = new BidRequestBuilder().withParams().build(); - delete bid01.params.pageId; - bid01.params.pageId = '3320'; - expect(spec.isBidRequestValid(bid01)).to.equal(false); - }); - }); - - describe('C-WIRE - buildRequests()', function () { - it('creates a valid request', function () { - const bid01 = new BidRequestBuilder({ - mediaTypes: { - banner: { - sizes: [[1, 1]], - } - } - }).withParams({ - cwcreative: 54321, - cwapikey: 'xxx-xxx-yyy-zzz-uuid', - refgroups: 'group_1', - }).build(); - - const bidderRequest01 = new BidderRequestBuilder().build(); - - const requests = spec.buildRequests([bid01], bidderRequest01); - - expect(requests.data.slots.length).to.equal(1); - expect(requests.data.cwid).to.be.null; - expect(requests.data.cwid).to.be.null; - expect(requests.data.slots[0].sizes[0]).to.equal('1x1'); - expect(requests.data.cwcreative).to.equal(54321); - expect(requests.data.cwapikey).to.equal('xxx-xxx-yyy-zzz-uuid'); - expect(requests.data.refgroups[0]).to.equal('group_1'); - }); - - it('creates a valid request - read debug params from second bid', function () { - const bid01 = new BidRequestBuilder().withParams().build(); - - const bid02 = new BidRequestBuilder({ - mediaTypes: { - banner: { - sizes: [[1, 1]], - } - } - }).withParams({ - cwcreative: 1234, - cwapikey: 'api_key_5', - refgroups: 'group_5', - }).build(); - - const bidderRequest01 = new BidderRequestBuilder().build(); - - const requests = spec.buildRequests([bid01, bid02], bidderRequest01); - - expect(requests.data.slots.length).to.equal(2); - expect(requests.data.cwid).to.be.null; - expect(requests.data.cwid).to.be.null; - expect(requests.data.cwcreative).to.equal(1234); - expect(requests.data.cwapikey).to.equal('api_key_5'); - expect(requests.data.refgroups[0]).to.equal('group_5'); - }); - - it('creates a valid request - read debug params from first bid, ignore second', function () { - const bid01 = new BidRequestBuilder() - .withParams({ - cwcreative: 33, - cwapikey: 'api_key_33', - refgroups: 'group_33', - }).build(); - - const bid02 = new BidRequestBuilder() - .withParams({ - cwcreative: 1234, - cwapikey: 'api_key_5', - refgroups: 'group_5', - }).build(); - - const bidderRequest01 = new BidderRequestBuilder().build(); - - const requests = spec.buildRequests([bid01, bid02], bidderRequest01); - - expect(requests.data.slots.length).to.equal(2); - expect(requests.data.cwid).to.be.null; - expect(requests.data.cwid).to.be.null; - expect(requests.data.cwcreative).to.equal(33); - expect(requests.data.cwapikey).to.equal('api_key_33'); - expect(requests.data.refgroups[0]).to.equal('group_33'); - }); - - it('creates a valid request - read debug params from 3 different slots', function () { - const bid01 = new BidRequestBuilder() - .withParams({ - cwcreative: 33, - }).build(); - - const bid02 = new BidRequestBuilder() - .withParams({ - cwapikey: 'api_key_5', - }).build(); - - const bid03 = new BidRequestBuilder() - .withParams({ - refgroups: 'group_5', - }).build(); - const bidderRequest01 = new BidderRequestBuilder().build(); - - const requests = spec.buildRequests([bid01, bid02, bid03], bidderRequest01); - - expect(requests.data.slots.length).to.equal(3); - expect(requests.data.cwid).to.be.null; - expect(requests.data.cwid).to.be.null; - expect(requests.data.cwcreative).to.equal(33); - expect(requests.data.cwapikey).to.equal('api_key_5'); - expect(requests.data.refgroups[0]).to.equal('group_5'); - }); - - it('creates a valid request - config is overriden by URL params', function () { - // for whatever reason stub for getWindowLocation does not work - // so this was the closest way to test for get params - const params = sandbox.stub(utils, 'getParameterByName'); - params.withArgs('cwgroups').returns('group_2'); - params.withArgs('cwcreative').returns('654321'); - - const bid01 = new BidRequestBuilder({ - mediaTypes: { - banner: { - sizes: [[1, 1]], - } - } - }).withParams({ - cwcreative: 54321, - cwapikey: 'xxx-xxx-yyy-zzz', - refgroups: 'group_1', - }).build(); - - const bidderRequest01 = new BidderRequestBuilder().build(); - - const requests = spec.buildRequests([bid01], bidderRequest01); - - expect(requests.data.slots.length).to.equal(1); - expect(requests.data.cwid).to.be.null; - expect(requests.data.cwid).to.be.null; - expect(requests.data.slots[0].sizes[0]).to.equal('1x1'); - expect(requests.data.cwcreative).to.equal(654321); - expect(requests.data.cwapikey).to.equal('xxx-xxx-yyy-zzz'); - expect(requests.data.refgroups[0]).to.equal('group_2'); - }); - - it('creates a valid request - if params are not set, null or empty array are sent to the API', function () { - const bid01 = new BidRequestBuilder({ - mediaTypes: { - banner: { - sizes: [[1, 1]], - } - } - }).withParams().build(); - - const bidderRequest01 = new BidderRequestBuilder().build(); - - const requests = spec.buildRequests([bid01], bidderRequest01); - - expect(requests.data.slots.length).to.equal(1); - expect(requests.data.cwid).to.be.null; - expect(requests.data.cwid).to.be.null; - expect(requests.data.slots[0].sizes[0]).to.equal('1x1'); - expect(requests.data.cwcreative).to.equal(null); - expect(requests.data.cwapikey).to.equal(null); - expect(requests.data.refgroups.length).to.equal(0); - }); - }); - - describe('C-WIRE - interpretResponse()', function () { - const serverResponse = { - body: { - bids: [{ - html: '

AD CONTENT

', - currency: 'CHF', - cpm: 43.37, - dimensions: [1, 1], - netRevenue: true, - creativeId: '1337', - requestId: BID_DEFAULTS.request.bidId, - ttl: 3500, - }], - } - }; - - const expectedResponse = [{ - ad: JSON.parse(JSON.stringify(serverResponse.body.bids[0].html)), - bidderCode: BID_DEFAULTS.request.bidder, - cpm: JSON.parse(JSON.stringify(serverResponse.body.bids[0].cpm)), - creativeId: JSON.parse(JSON.stringify(serverResponse.body.bids[0].creativeId)), - currency: JSON.parse(JSON.stringify(serverResponse.body.bids[0].currency)), - height: JSON.parse(JSON.stringify(serverResponse.body.bids[0].dimensions[0])), - width: JSON.parse(JSON.stringify(serverResponse.body.bids[0].dimensions[1])), - netRevenue: JSON.parse(JSON.stringify(serverResponse.body.bids[0].netRevenue)), - requestId: JSON.parse(JSON.stringify(serverResponse.body.bids[0].requestId)), - ttl: JSON.parse(JSON.stringify(serverResponse.body.bids[0].ttl)), - meta: { - advertiserDomains: [], - }, - mediaType: 'banner', - }] - - it('correctly parses response', function () { - const bid01 = new BidRequestBuilder({ - mediaTypes: { - banner: { - sizes: [[1, 1]], - } - } - }).withParams().build(); - - const bidderRequest01 = new BidderRequestBuilder().build(); - const requests = spec.buildRequests([bid01], bidderRequest01); - - const response = spec.interpretResponse(serverResponse, requests); - expect(response).to.deep.equal(expectedResponse); - }); - - it('attaches renderer', function () { - const bid01 = new BidRequestBuilder({ - mediaTypes: { - video: { - playerSize: [[640, 480]], - context: 'outstream', - } - } - }).withParams().build(); - const bidderRequest01 = new BidderRequestBuilder().build(); - - const _serverResponse = utils.deepClone(serverResponse); - _serverResponse.body.bids[0].vastXml = ''; - - const _expectedResponse = utils.deepClone(expectedResponse); - _expectedResponse[0].mediaType = 'video'; - _expectedResponse[0].videoScript = JSON.parse(JSON.stringify(_serverResponse.body.bids[0].html)); - _expectedResponse[0].vastXml = JSON.parse(JSON.stringify(_serverResponse.body.bids[0].vastXml)); - delete _expectedResponse[0].ad; - - const requests = spec.buildRequests([bid01], bidderRequest01); - expect(requests.data.slots[0].sizes).to.deep.equal(['640x480']); - - const response = spec.interpretResponse(_serverResponse, requests); - expect(response[0].renderer).to.exist; - expect(response[0].renderer.url).to.equals(RENDERER_URL); - expect(response[0].renderer.loaded).to.equals(false); - - delete response[0].renderer; - expect(response).to.deep.equal(_expectedResponse); - }); - }); -}); diff --git a/test/spec/modules/dacIdSystem_spec.js b/test/spec/modules/dacIdSystem_spec.js deleted file mode 100644 index d78b4a69000..00000000000 --- a/test/spec/modules/dacIdSystem_spec.js +++ /dev/null @@ -1,51 +0,0 @@ -import { dacIdSystemSubmodule, storage, cookieKey } from 'modules/dacIdSystem.js'; - -const DACID_DUMMY_VALUE = 'dacIdTest'; -const DACID_DUMMY_OBJ = { - dacId: DACID_DUMMY_VALUE -}; - -describe('dacId module', function () { - let getCookieStub; - - beforeEach(function (done) { - getCookieStub = sinon.stub(storage, 'getCookie'); - done(); - }); - - afterEach(function () { - getCookieStub.restore(); - }); - - const cookieTestCasesForEmpty = [ - undefined, - null, - '' - ] - - describe('getId()', function () { - it('should return the uid when it exists in cookie', function () { - getCookieStub.withArgs(cookieKey).returns(DACID_DUMMY_VALUE); - const id = dacIdSystemSubmodule.getId(); - expect(id).to.be.deep.equal({id: {dacId: DACID_DUMMY_VALUE}}); - }); - - cookieTestCasesForEmpty.forEach(testCase => it('should return the uid when it not exists in cookie', function () { - getCookieStub.withArgs(cookieKey).returns(testCase); - const id = dacIdSystemSubmodule.getId(); - expect(id).to.be.deep.equal(undefined); - })); - }); - - describe('decode()', function () { - it('should return the uid when it exists in cookie', function () { - const decoded = dacIdSystemSubmodule.decode(DACID_DUMMY_OBJ); - expect(decoded).to.be.deep.equal({dacId: {id: DACID_DUMMY_VALUE}}); - }); - - it('should return the undefined when decode id is not "string"', function () { - const decoded = dacIdSystemSubmodule.decode(1); - expect(decoded).to.equal(undefined); - }); - }); -}); diff --git a/test/spec/modules/dailyhuntBidAdapter_spec.js b/test/spec/modules/dailyhuntBidAdapter_spec.js deleted file mode 100644 index f347d6cec5b..00000000000 --- a/test/spec/modules/dailyhuntBidAdapter_spec.js +++ /dev/null @@ -1,404 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/dailyhuntBidAdapter.js'; - -const PROD_PREBID_ENDPOINT_URL = 'https://pbs.dailyhunt.in/openrtb2/auction?partner=dailyhunt'; -const PROD_PREBID_TEST_ENDPOINT_URL = 'https://qa-pbs-van.dailyhunt.in/openrtb2/auction?partner=dailyhunt'; - -const _encodeURIComponent = function (a) { - if (!a) { return } - let b = window.encodeURIComponent(a); - b = b.replace(/'/g, '%27'); - return b; -} - -describe('DailyhuntAdapter', function () { - describe('isBidRequestValid', function () { - let bid = { - 'bidder': 'dailyhunt', - 'params': { - placement_id: 1, - publisher_id: 1, - partner_name: 'dailyhunt' - } - }; - - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when required params are not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {}; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - describe('buildRequests', function() { - let bidRequests = [ - { - bidder: 'dailyhunt', - params: { - placement_id: 1, - publisher_id: 1, - partner_name: 'dailyhunt', - bidfloor: 0.1, - device: { - ip: '47.9.247.217' - }, - site: { - cat: ['1', '2', '3'] - } - }, - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - adUnitCode: 'adunit-code', - sizes: [[300, 50]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - transactionId: '04f2659e-c005-4eb1-a57c-fa93145e3843' - } - ]; - let nativeBidRequests = [ - { - bidder: 'dailyhunt', - params: { - placement_id: 1, - publisher_id: 1, - partner_name: 'dailyhunt', - }, - nativeParams: { - title: { - required: true, - len: 80 - }, - image: { - required: true, - sizes: [150, 50] - }, - }, - mediaTypes: { - native: { - title: { - required: true - }, - } - }, - adUnitCode: 'adunit-code', - sizes: [[300, 250], [300, 50]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - transactionId: '04f2659e-c005-4eb1-a57c-fa93145e3843' - } - ]; - let videoBidRequests = [ - { - bidder: 'dailyhunt', - params: { - placement_id: 1, - publisher_id: 1, - partner_name: 'dailyhunt' - }, - nativeParams: { - video: { - context: 'instream' - } - }, - mediaTypes: { - video: { - context: 'instream' - } - }, - adUnitCode: 'adunit-code', - sizes: [[300, 250], [300, 50]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - transactionId: '04f2659e-c005-4eb1-a57c-fa93145e3843' - } - ]; - let bidderRequest = { - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'bidderCode': 'dailyhunt', - 'bids': [ - { - ...bidRequests[0] - } - ], - 'refererInfo': { - 'referer': 'http://m.dailyhunt.in/' - } - }; - let nativeBidderRequest = { - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'bidderCode': 'dailyhunt', - 'bids': [ - { - ...nativeBidRequests[0] - } - ], - 'refererInfo': { - 'referer': 'http://m.dailyhunt.in/' - } - }; - let videoBidderRequest = { - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'bidderCode': 'dailyhunt', - 'bids': [ - { - ...videoBidRequests[0] - } - ], - 'refererInfo': { - 'referer': 'http://m.dailyhunt.in/' - } - }; - - it('sends display bid request to ENDPOINT via POST', function () { - const request = spec.buildRequests(bidRequests, bidderRequest)[0]; - expect(request.url).to.equal(PROD_PREBID_ENDPOINT_URL); - expect(request.method).to.equal('POST'); - }); - - it('sends native bid request to ENDPOINT via POST', function () { - const request = spec.buildRequests(nativeBidRequests, nativeBidderRequest)[0]; - expect(request.url).to.equal(PROD_PREBID_ENDPOINT_URL); - expect(request.method).to.equal('POST'); - }); - - it('sends video bid request to ENDPOINT via POST', function () { - const request = spec.buildRequests(videoBidRequests, videoBidderRequest)[0]; - expect(request.url).to.equal(PROD_PREBID_ENDPOINT_URL); - expect(request.method).to.equal('POST'); - }); - }); - describe('interpretResponse', function () { - let bidResponses = { - id: 'da32def7-6779-403c-ada7-0b201dbc9744', - seatbid: [ - { - bid: [ - { - id: 'id1', - impid: 'banner-impid', - price: 1.4, - adm: 'adm', - adid: '66658', - crid: 'asd5ddbf014cac993.66466212', - dealid: 'asd5ddbf014cac993.66466212', - w: 300, - h: 250, - nurl: 'winUrl', - ext: { - prebid: { - type: 'banner' - } - } - }, - { - id: '5caccc1f-94a6-4230-a1f9-6186ee65da99', - impid: 'video-impid', - price: 1.4, - nurl: 'winUrl', - adm: 'adm', - adid: '980', - crid: '2394', - w: 300, - h: 250, - ext: { - prebid: { - 'type': 'video' - }, - bidder: { - cacheKey: 'cache_key', - vastUrl: 'vastUrl' - } - } - }, - { - id: '74973faf-cce7-4eff-abd0-b59b8e91ca87', - impid: 'native-impid', - price: 50, - nurl: 'winUrl', - adm: '{"native":{"link":{"url":"url","clicktrackers":[]},"assets":[{"id":1,"required":1,"img":{},"video":{},"data":{},"title":{"text":"TITLE"},"link":{}},{"id":1,"required":1,"img":{},"video":{},"data":{"type":2,"value":"Lorem Ipsum Lorem Ipsum Lorem Ipsum."},"title":{},"link":{}},{"id":1,"required":1,"img":{},"video":{},"data":{"type":12,"value":"Install Here"},"title":{},"link":{}},{"id":1,"required":1,"img":{"type":3,"url":"urk","w":990,"h":505},"video":{},"data":{},"title":{},"link":{}}],"imptrackers":[]}}', - adid: '968', - crid: '2370', - w: 300, - h: 250, - ext: { - prebid: { - type: 'native' - }, - bidder: null - } - }, - { - id: '5caccc1f-94a6-4230-a1f9-6186ee65da99', - impid: 'video-outstream-impid', - price: 1.4, - nurl: 'winUrl', - adm: 'adm', - adid: '980', - crid: '2394', - w: 300, - h: 250, - ext: { - prebid: { - 'type': 'video' - }, - bidder: { - cacheKey: 'cache_key', - vastUrl: 'vastUrl' - } - } - }, - ], - seat: 'dailyhunt' - } - ], - ext: { - responsetimemillis: { - dailyhunt: 119 - } - } - }; - - it('should get correct bid response', function () { - let expectedResponse = [ - { - requestId: '1', - cpm: 1.4, - creativeId: 'asd5ddbf014cac993.66466212', - width: 300, - height: 250, - ttl: 360, - netRevenue: true, - currency: 'USD', - ad: 'adm', - mediaType: 'banner', - winUrl: 'winUrl', - adomain: 'dailyhunt' - }, - { - requestId: '2', - cpm: 1.4, - creativeId: '2394', - width: 300, - height: 250, - ttl: 360, - netRevenue: true, - currency: 'USD', - mediaType: 'video', - winUrl: 'winUrl', - adomain: 'dailyhunt', - videoCacheKey: 'cache_key', - vastUrl: 'vastUrl', - }, - { - requestId: '3', - cpm: 1.4, - creativeId: '2370', - width: 300, - height: 250, - ttl: 360, - netRevenue: true, - currency: 'USD', - mediaType: 'native', - winUrl: 'winUrl', - adomain: 'dailyhunt', - native: { - clickUrl: 'https%3A%2F%2Fmontu1996.github.io%2F', - clickTrackers: [], - impressionTrackers: [], - javascriptTrackers: [], - title: 'TITLE', - body: 'Lorem Ipsum Lorem Ipsum Lorem Ipsum.', - cta: 'Install Here', - image: { - url: 'url', - height: 505, - width: 990 - } - } - }, - { - requestId: '4', - cpm: 1.4, - creativeId: '2394', - width: 300, - height: 250, - ttl: 360, - netRevenue: true, - currency: 'USD', - mediaType: 'video', - winUrl: 'winUrl', - adomain: 'dailyhunt', - vastXml: 'adm', - }, - ]; - let bidderRequest = { - bids: [ - { - bidId: 'banner-impid', - adUnitCode: 'code1', - requestId: '1' - }, - { - bidId: 'video-impid', - adUnitCode: 'code2', - requestId: '2', - mediaTypes: { - video: { - context: 'instream' - } - } - }, - { - bidId: 'native-impid', - adUnitCode: 'code3', - requestId: '3' - }, - { - bidId: 'video-outstream-impid', - adUnitCode: 'code4', - requestId: '4', - mediaTypes: { - video: { - context: 'outstream' - } - } - }, - ] - } - let result = spec.interpretResponse({ body: bidResponses }, bidderRequest); - result.forEach((r, i) => { - expect(Object.keys(r)).to.have.members(Object.keys(expectedResponse[i])); - }); - }); - }) - describe('onBidWon', function () { - it('should hit win url when bid won', function () { - let bid = { - requestId: '1', - cpm: 1.4, - creativeId: 'asd5ddbf014cac993.66466212', - width: 300, - height: 250, - ttl: 360, - netRevenue: true, - currency: 'USD', - ad: 'adm', - mediaType: 'banner', - winUrl: 'winUrl' - }; - expect(spec.onBidWon(bid)).to.equal(undefined); - }); - }) -}) diff --git a/test/spec/modules/datablocksBidAdapter_spec.js b/test/spec/modules/datablocksBidAdapter_spec.js index ff7b0aad48c..0ec12905430 100644 --- a/test/spec/modules/datablocksBidAdapter_spec.js +++ b/test/spec/modules/datablocksBidAdapter_spec.js @@ -96,8 +96,8 @@ const bidderRequest = { refererInfo: { numIframes: 0, reachedTop: true, - referer: 'https://7560.v5demo.datablocks.net/test', - stack: ['https://7560.v5demo.datablocks.net/test'] + referer: 'https://v5demo.datablocks.net/test', + stack: ['https://v5demo.datablocks.net/test'] }, start: Date.now(), timeout: 10000 @@ -452,7 +452,7 @@ describe('DatablocksAdapter', function() { it('Returns valid URL', function() { expect(request.url).to.exist; - expect(request.url).to.equal('https://v5demo.datablocks.net/openrtb/?sid=7560'); + expect(request.url).to.equal('https://7560.v5demo.datablocks.net/openrtb/?sid=7560'); }); it('Creates an array of request objects', function() { diff --git a/test/spec/modules/dchain_spec.js b/test/spec/modules/dchain_spec.js deleted file mode 100644 index 45061c539c1..00000000000 --- a/test/spec/modules/dchain_spec.js +++ /dev/null @@ -1,329 +0,0 @@ -import { checkDchainSyntax, addBidResponseHook } from '../../../modules/dchain.js'; -import { config } from '../../../src/config.js'; -import { expect } from 'chai'; - -describe('dchain module', function () { - const STRICT = 'strict'; - const RELAX = 'relaxed'; - const OFF = 'off'; - - describe('checkDchainSyntax', function () { - let bid; - - beforeEach(function () { - bid = { - meta: { - dchain: { - 'ver': '1.0', - 'complete': 0, - 'ext': {}, - 'nodes': [{ - 'asi': 'domain.com', - 'bsid': '12345', - }, { - 'name': 'bidder', - 'domain': 'bidder.com', - 'ext': {} - }] - } - } - }; - }); - - it('Returns false if complete param is not 0 or 1', function () { - let dchainConfig = bid.meta.dchain; - dchainConfig.complete = 0; // integer - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.complete = 1; // integer - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.complete = '1'; // string - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.complete = 1.1; // float - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.complete = {}; // object - expect(checkDchainSyntax(bid, STRICT)).to.false; - delete dchainConfig.complete; // undefined - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.complete = true; // boolean - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.complete = []; // array - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if ver param is not a String', function () { - let dchainConfig = bid.meta.dchain; - dchainConfig.ver = 1; // integer - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.ver = '1'; // string - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.ver = 1.1; // float - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.ver = {}; // object - expect(checkDchainSyntax(bid, STRICT)).to.false; - delete dchainConfig.ver; // undefined - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.ver = true; // boolean - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.ver = []; // array - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if ext param is not an Object', function () { - let dchainConfig = bid.meta.dchain; - dchainConfig.ext = 1; // integer - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.ext = '1'; // string - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.ext = 1.1; // float - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.ext = {}; // object - expect(checkDchainSyntax(bid, STRICT)).to.true; - delete dchainConfig.ext; // undefined - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.ext = true; // boolean - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.ext = []; // array - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if nodes param is not an Array', function () { - let dchainConfig = bid.meta.dchain; - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes = 1; // integer - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes = '1'; // string - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes = 1.1; // float - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes = {}; // object - expect(checkDchainSyntax(bid, STRICT)).to.false; - delete dchainConfig.nodes; // undefined - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes = true; // boolean - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if unknown field is used in main dchain', function () { - let dchainConfig = bid.meta.dchain; - dchainConfig.test = '1'; // String - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if nodes[].asi is not a String', function () { - let dchainConfig = bid.meta.dchain; - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].asi = 1; // Integer - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].asi = 1.1; // float - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].asi = {}; // object - expect(checkDchainSyntax(bid, STRICT)).to.false; - delete dchainConfig.nodes[0].asi; // undefined - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].asi = true; // boolean - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].asi = []; // array - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if nodes[].bsid is not a String', function () { - let dchainConfig = bid.meta.dchain; - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].bsid = 1; // Integer - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].bsid = 1.1; // float - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].bsid = {}; // object - expect(checkDchainSyntax(bid, STRICT)).to.false; - delete dchainConfig.nodes[0].bsid; // undefined - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].bsid = true; // boolean - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].bsid = []; // array - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if nodes[].rid is not a String', function () { - let dchainConfig = bid.meta.dchain; - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].rid = 1; // Integer - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].rid = 1.1; // float - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].rid = {}; // object - expect(checkDchainSyntax(bid, STRICT)).to.false; - delete dchainConfig.nodes[0].rid; // undefined - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].rid = true; // boolean - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].rid = []; // array - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if nodes[].name is not a String', function () { - let dchainConfig = bid.meta.dchain; - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].name = 1; // Integer - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].name = 1.1; // float - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].name = {}; // object - expect(checkDchainSyntax(bid, STRICT)).to.false; - delete dchainConfig.nodes[0].name; // undefined - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].name = true; // boolean - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].name = []; // array - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if nodes[].domain is not a String', function () { - let dchainConfig = bid.meta.dchain; - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].domain = 1; // Integer - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].domain = 1.1; // float - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].domain = {}; // object - expect(checkDchainSyntax(bid, STRICT)).to.false; - delete dchainConfig.nodes[0].domain; // undefined - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].domain = true; // boolean - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].domain = []; // array - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if nodes[].ext is not an Object', function () { - let dchainConfig = bid.meta.dchain; - dchainConfig.nodes[0].ext = '1'; // String - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].ext = 1; // Integer - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].ext = 1.1; // float - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].ext = {}; // object - expect(checkDchainSyntax(bid, STRICT)).to.true; - delete dchainConfig.nodes[0].ext; // undefined - expect(checkDchainSyntax(bid, STRICT)).to.true; - dchainConfig.nodes[0].ext = true; // boolean - expect(checkDchainSyntax(bid, STRICT)).to.false; - dchainConfig.nodes[0].ext = []; // array - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Returns false if unknown field is used in nodes[]', function () { - let dchainConfig = bid.meta.dchain; - dchainConfig.nodes[0].test = '1'; // String - expect(checkDchainSyntax(bid, STRICT)).to.false; - }); - - it('Relaxed mode: returns true even for invalid config', function () { - bid.meta.dchain = { - ver: 1.1, - complete: '0', - nodes: [{ - name: 'asdf', - domain: ['domain.com'] - }] - }; - - expect(checkDchainSyntax(bid, RELAX)).to.true; - }); - }); - - describe('addBidResponseHook', function () { - let bid; - let adUnitCode = 'adUnit1'; - - beforeEach(function () { - bid = { - bidderCode: 'bidderA', - meta: { - dchain: { - 'ver': '1.0', - 'complete': 0, - 'ext': {}, - 'nodes': [{ - 'asi': 'domain.com', - 'bsid': '12345', - }, { - 'name': 'bidder', - 'domain': 'bidder.com', - 'ext': {} - }] - }, - networkName: 'myNetworkName', - networkId: 8475 - } - }; - }); - - afterEach(function () { - config.resetConfig(); - }); - - it('good strict config should append a node object to existing bid.meta.dchain object', function () { - function testCallback(adUnitCode, bid) { - expect(bid.meta.dchain).to.exist; - expect(bid.meta.dchain.nodes[1]).to.exist.and.to.deep.equal({ - 'name': 'bidder', - 'domain': 'bidder.com', - 'ext': {} - }); - expect(bid.meta.dchain.nodes[2]).to.exist.and.to.deep.equal({ asi: 'bidderA' }); - } - - config.setConfig({ dchain: { validation: STRICT } }); - addBidResponseHook(testCallback, adUnitCode, bid); - }); - - it('bad strict config should delete the bid.meta.dchain object', function () { - function testCallback(adUnitCode, bid) { - expect(bid.meta.dchain).to.not.exist; - } - - config.setConfig({ dchain: { validation: STRICT } }); - bid.meta.dchain.complete = 3; - addBidResponseHook(testCallback, adUnitCode, bid); - }); - - it('relaxed config should allow bid.meta.dchain to proceed, even with bad values', function () { - function testCallback(adUnitCode, bid) { - expect(bid.meta.dchain).to.exist; - expect(bid.meta.dchain.complete).to.exist.and.to.equal(3); - expect(bid.meta.dchain.nodes[2]).to.exist.and.to.deep.equal({ asi: 'bidderA' }); - } - - config.setConfig({ dchain: { validation: RELAX } }); - bid.meta.dchain.complete = 3; - addBidResponseHook(testCallback, adUnitCode, bid); - }); - - it('off config should allow the bid.meta.dchain to proceed', function () { - // check for missing nodes - function testCallback(adUnitCode, bid) { - expect(bid.meta.dchain).to.exist; - expect(bid.meta.dchain.complete).to.exist.and.to.equal(0); - expect(bid.meta.dchain.nodes).to.exist.and.to.deep.equal({ test: 123 }); - } - - config.setConfig({ dchain: { validation: OFF } }); - bid.meta.dchain.nodes = { test: 123 }; - addBidResponseHook(testCallback, adUnitCode, bid); - }); - - it('no bidder dchain', function () { - function testCallback(adUnitCode, bid) { - expect(bid.meta.dchain).to.exist; - expect(bid.meta.dchain.ver).to.exist.and.to.equal('1.0'); - expect(bid.meta.dchain.complete).to.exist.and.to.equal(0); - expect(bid.meta.dchain.nodes).to.exist.and.to.deep.equal([{ name: 'myNetworkName', bsid: '8475' }, { name: 'bidderA' }]); - } - - delete bid.meta.dchain; - config.setConfig({ dchain: { validation: RELAX } }); - addBidResponseHook(testCallback, adUnitCode, bid); - }); - }); -}); diff --git a/test/spec/modules/debugging_mod_spec.js b/test/spec/modules/debugging_mod_spec.js deleted file mode 100644 index 79866d023e9..00000000000 --- a/test/spec/modules/debugging_mod_spec.js +++ /dev/null @@ -1,451 +0,0 @@ -import {expect} from 'chai'; -import {BidInterceptor} from '../../../modules/debugging/bidInterceptor.js'; -import {bidderBidInterceptor} from '../../../modules/debugging/index.js'; -import {pbsBidInterceptor} from '../../../modules/debugging/pbsInterceptor.js'; - -describe('bid interceptor', () => { - let interceptor, mockSetTimeout; - beforeEach(() => { - mockSetTimeout = sinon.stub().callsFake((fn) => fn()); - interceptor = new BidInterceptor({setTimeout: mockSetTimeout}); - }); - - function setRules(...rules) { - interceptor.updateConfig({ - intercept: rules - }); - } - - describe('serializeConfig', () => { - Object.entries({ - regexes: /pat/, - functions: () => ({}) - }).forEach(([test, arg]) => { - it(`should filter out ${test}`, () => { - const valid = [{key1: 'value'}, {key2: 'value'}]; - const ser = interceptor.serializeConfig([...valid, {outer: {inner: arg}}]); - expect(ser).to.eql(valid); - }); - }); - }); - - describe('match()', () => { - Object.entries({ - value: {key: 'value'}, - regex: {key: /^value$/}, - 'function': (o) => o.key === 'value' - }).forEach(([test, matcher]) => { - describe(`by ${test}`, () => { - it('should work on matching top-level properties', () => { - setRules({when: matcher}); - const rule = interceptor.match({key: 'value'}); - expect(rule).to.not.eql(null); - }); - - it('should work on matching nested properties', () => { - setRules({when: {outer: {inner: matcher}}}); - const rule = interceptor.match({outer: {inner: {key: 'value'}}}); - expect(rule).to.not.eql(null); - }); - - it('should not work on non-matching inputs', () => { - setRules({when: matcher}); - expect(interceptor.match({key: 'different-value'})).to.not.be.ok; - expect(interceptor.match({differentKey: 'value'})).to.not.be.ok; - }); - }); - }); - - it('should respect rule order', () => { - setRules({when: {key: 'value'}}, {when: {}}, {when: {}}); - const rule = interceptor.match({}); - expect(rule.no).to.equal(2); - }); - - it('should pass extra arguments to property function matchers', () => { - let matchDef = { - key: sinon.stub(), - outer: {inner: {key: sinon.stub()}} - }; - const extraArgs = [{}, {}]; - setRules({when: matchDef}); - interceptor.match({key: {}, outer: {inner: {key: {}}}}, ...extraArgs); - [matchDef.key, matchDef.outer.inner.key].forEach((fn) => { - expect(fn.calledOnceWith(sinon.match.any, ...extraArgs.map(sinon.match.same))).to.be.true; - }); - }); - - it('should pass extra arguments to single-function matcher', () => { - let matchDef = sinon.stub(); - setRules({when: matchDef}); - const args = [{}, {}, {}]; - interceptor.match(...args); - expect(matchDef.calledOnceWith(...args.map(sinon.match.same))).to.be.true; - }); - }); - - describe('rule', () => { - function matchingRule({replace, options}) { - setRules({when: {}, then: replace, options: options}); - return interceptor.match({}); - } - - describe('.replace()', () => { - const REQUIRED_KEYS = [ - // https://docs.prebid.org/dev-docs/bidder-adaptor.html#bidder-adaptor-Interpreting-the-Response - 'requestId', 'cpm', 'currency', 'width', 'height', 'ttl', - 'creativeId', 'netRevenue', 'meta', 'ad' - ]; - it('should include required bid response keys by default', () => { - expect(matchingRule({}).replace({})).to.include.keys(REQUIRED_KEYS); - }); - - Object.entries({ - value: {key: 'value'}, - 'function': () => ({key: 'value'}) - }).forEach(([test, replDef]) => { - describe(`by ${test}`, () => { - it('should merge top-level properties with replace definition', () => { - const result = matchingRule({replace: replDef}).replace({}); - expect(result).to.include.keys(REQUIRED_KEYS); - expect(result.key).to.equal('value'); - }); - - it('should merge nested properties with replace definition', () => { - const result = matchingRule({replace: {outer: {inner: replDef}}}).replace({}); - expect(result).to.include.keys(REQUIRED_KEYS); - expect(result.outer.inner).to.eql({key: 'value'}); - }); - }); - }); - - it('should pass extra arguments to single function replacer', () => { - const replDef = sinon.stub(); - const args = [{}, {}, {}]; - matchingRule({replace: replDef}).replace(...args); - expect(replDef.calledOnceWith(...args.map(sinon.match.same))).to.be.true; - }); - - it('should pass extra arguments to function property replacers', () => { - const replDef = { - key: sinon.stub(), - outer: {inner: {key: sinon.stub()}} - }; - const args = [{}, {}, {}]; - matchingRule({replace: replDef}).replace(...args); - [replDef.key, replDef.outer.inner.key].forEach((repl) => { - expect(repl.calledOnceWith(...args.map(sinon.match.same))).to.be.true; - }); - }); - }); - - describe('.options', () => { - it('should include default rule options', () => { - const optDef = {someOption: 'value'}; - const ruleOptions = matchingRule({options: optDef}).options; - expect(ruleOptions).to.include(optDef); - expect(ruleOptions).to.include(interceptor.DEFAULT_RULE_OPTIONS); - }); - - it('should override defaults', () => { - const optDef = {delay: 123}; - const ruleOptions = matchingRule({options: optDef}).options; - expect(ruleOptions).to.eql(optDef); - }); - }); - }); - - describe('intercept()', () => { - let done, addBid; - - function intercept(args = {}) { - const bidRequest = {bids: args.bids || []}; - return interceptor.intercept(Object.assign({bidRequest, done, addBid}, args)); - } - - beforeEach(() => { - done = sinon.spy(); - addBid = sinon.spy(); - }); - - describe('on no match', () => { - it('should return untouched bids and bidRequest', () => { - const bids = [{}, {}]; - const bidRequest = {}; - const result = intercept({bids, bidRequest}); - expect(result.bids).to.equal(bids); - expect(result.bidRequest).to.equal(bidRequest); - }); - - it('should call done() immediately', () => { - intercept(); - expect(done.calledOnce).to.be.true; - expect(mockSetTimeout.args[0][1]).to.equal(0); - }); - - it('should not call addBid', () => { - intercept(); - expect(addBid.called).to.not.be.ok; - }); - }); - - describe('on match', () => { - let match1, match2, repl1, repl2; - const DELAY_1 = 123; - const DELAY_2 = 321; - const REQUEST = { - bids: [ - {id: 1, match: false}, - {id: 2, match: 1}, - {id: 3, match: 2} - ] - }; - - beforeEach(() => { - match1 = sinon.stub().callsFake((bid) => bid.match === 1); - match2 = sinon.stub().callsFake((bid) => bid.match === 2); - repl1 = sinon.stub().returns({replace: 1}); - repl2 = sinon.stub().returns({replace: 2}); - setRules( - {when: match1, then: repl1, options: {delay: DELAY_1}}, - {when: match2, then: repl2, options: {delay: DELAY_2}}, - ); - }); - - it('should return only non-matching bids', () => { - const {bids, bidRequest} = intercept({bidRequest: REQUEST}); - expect(bids).to.eql([REQUEST.bids[0]]); - expect(bidRequest.bids).to.eql([REQUEST.bids[0]]); - }); - - it('should call addBid for each matching bid', () => { - intercept({bidRequest: REQUEST}); - expect(addBid.callCount).to.equal(2); - expect(addBid.calledWith(sinon.match({replace: 1, isDebug: true}), REQUEST.bids[1])).to.be.true; - expect(addBid.calledWith(sinon.match({replace: 2, isDebug: true}), REQUEST.bids[2])).to.be.true; - [DELAY_1, DELAY_2].forEach((delay) => { - expect(mockSetTimeout.calledWith(sinon.match.any, delay)).to.be.true; - }); - }); - - it('should call done()', () => { - intercept({bidRequest: REQUEST}); - expect(done.calledOnce).to.be.true; - }); - - it('should pass bid and bidRequest to match and replace functions', () => { - intercept({bidRequest: REQUEST}); - Object.entries({ - 1: [match1, repl1], - 2: [match2, repl2] - }).forEach(([index, fns]) => { - fns.forEach((fn) => { - expect(fn.calledWith(REQUEST.bids[index], REQUEST)).to.be.true; - }); - }); - }); - }); - }); -}); - -describe('bidderBidInterceptor', () => { - let next, interceptBids, onCompletion, interceptResult, done, addBid; - - function interceptorArgs({spec = {}, bids = [], bidRequest = {}, ajax = {}, wrapCallback = {}, cbs = {}} = {}) { - return [next, interceptBids, spec, bids, bidRequest, ajax, wrapCallback, Object.assign({onCompletion}, cbs)]; - } - - beforeEach(() => { - next = sinon.spy(); - interceptBids = sinon.stub().callsFake((opts) => { - done = opts.done; - addBid = opts.addBid; - return interceptResult; - }); - onCompletion = sinon.spy(); - interceptResult = {bids: [], bidRequest: {}}; - }); - - it('should pass to interceptBid an addBid that triggers onBid', () => { - const onBid = sinon.spy(); - bidderBidInterceptor(...interceptorArgs({cbs: {onBid}})); - const bid = {}; - addBid(bid); - expect(onBid.calledWith(sinon.match.same(bid))).to.be.true; - }); - - describe('with no remaining bids', () => { - it('should pass a done callback that triggers onCompletion', () => { - bidderBidInterceptor(...interceptorArgs()); - expect(onCompletion.calledOnce).to.be.false; - interceptBids.args[0][0].done(); - expect(onCompletion.calledOnce).to.be.true; - }); - - it('should not call next()', () => { - bidderBidInterceptor(...interceptorArgs()); - expect(next.called).to.be.false; - }); - }); - - describe('with remaining bids', () => { - const REMAINING_BIDS = [{id: 1}, {id: 2}]; - beforeEach(() => { - interceptResult = {bids: REMAINING_BIDS, bidRequest: {bids: REMAINING_BIDS}}; - }); - - it('should call next', () => { - const callbacks = { - onResponse: {}, - onRequest: {}, - onBid: {} - }; - const args = interceptorArgs({cbs: callbacks}); - const expectedNextArgs = [ - args[2], - interceptResult.bids, - interceptResult.bidRequest, - ...args.slice(5, args.length - 1), - ].map(sinon.match.same) - .concat([sinon.match({ - onResponse: sinon.match.same(callbacks.onResponse), - onRequest: sinon.match.same(callbacks.onRequest), - onBid: sinon.match.same(callbacks.onBid) - })]); - bidderBidInterceptor(...args); - expect(next.calledOnceWith(...expectedNextArgs)).to.be.true; - }); - - it('should trigger onCompletion once both interceptBids.done and next.cbs.onCompletion are called ', () => { - bidderBidInterceptor(...interceptorArgs()); - expect(onCompletion.calledOnce).to.be.false; - next.args[0][next.args[0].length - 1].onCompletion(); - expect(onCompletion.calledOnce).to.be.false; - done(); - expect(onCompletion.calledOnce).to.be.true; - }); - }); -}); - -describe('pbsBidInterceptor', () => { - const EMPTY_INT_RES = {bids: [], bidRequest: {bids: []}}; - let next, interceptBids, s2sBidRequest, bidRequests, ajax, onResponse, onError, onBid, interceptResults, - addBids, dones, reqIdx; - - beforeEach(() => { - reqIdx = 0; - [addBids, dones] = [[], []]; - next = sinon.spy(); - ajax = sinon.spy(); - onResponse = sinon.spy(); - onError = sinon.spy(); - onBid = sinon.spy(); - interceptBids = sinon.stub().callsFake((opts) => { - addBids.push(opts.addBid); - dones.push(opts.done); - return interceptResults[reqIdx++]; - }); - s2sBidRequest = {}; - bidRequests = [{bids: []}, {bids: []}]; - interceptResults = [EMPTY_INT_RES, EMPTY_INT_RES]; - }); - - function callInterceptor() { - return pbsBidInterceptor(next, interceptBids, s2sBidRequest, bidRequests, ajax, {onResponse, onError, onBid}); - } - - it('passes addBids that trigger onBid', () => { - callInterceptor(); - bidRequests.forEach((_, i) => { - const bid = {adUnitCode: i, prop: i}; - const bidRequest = {req: i}; - addBids[i](bid, bidRequest); - expect(onBid.calledWith({adUnit: i, bid: sinon.match(bid)})); - }); - }); - - describe('on no match', () => { - it('should not call next', () => { - callInterceptor(); - expect(next.called).to.be.false; - }); - - it('should pass done callbacks that trigger a dummy onResponse once they all run', () => { - callInterceptor(); - expect(onResponse.called).to.be.false; - bidRequests.forEach((_, i) => { - dones[i](); - expect(onResponse.called).to.equal(i === bidRequests.length - 1); - }); - expect(onResponse.calledWith(true, [])).to.be.true; - }); - }); - - describe('on match', () => { - let matchingBids; - beforeEach(() => { - matchingBids = [ - [{bidId: 1, matching: true}, {bidId: 2, matching: true}], - [], - [{bidId: 3, matching: true}] - ]; - interceptResults = matchingBids.map((bids) => ({bids, bidRequest: {bids}})); - s2sBidRequest = { - ad_units: [ - {bids: [{bid_id: 1, matching: true}, {bid_id: 3, matching: true}, {bid_id: 100}, {bid_id: 101}]}, - {bids: [{bid_id: 2, matching: true}, {bid_id: 110}, {bid_id: 111}]}, - {bids: [{bid_id: 120}]} - ] - }; - bidRequests = matchingBids.map((mBids, i) => [ - {bidId: 100 + (i * 10)}, - {bidId: 101 + (i * 10)}, - ...mBids - ]); - }); - - it('should call next', () => { - callInterceptor(); - expect(next.calledOnceWith( - sinon.match.any, - sinon.match.any, - ajax, - sinon.match({ - onError, - onBid - }) - )).to.be.true; - }); - - it('should filter out intercepted bids from s2sBidRequest', () => { - callInterceptor(); - const interceptedS2SReq = next.args[0][0]; - const allMatching = interceptedS2SReq.ad_units.every((u) => u.bids.length > 0 && u.bids.every((b) => b.matching)); - expect(allMatching).to.be.true; - }); - - it('should pass bidRequests as returned by interceptBids', () => { - callInterceptor(); - const passedBidReqs = next.args[0][1]; - interceptResults - .filter((r) => r.bids.length > 0) - .forEach(({bidRequest}, i) => { - expect(passedBidReqs[i]).to.equal(bidRequest); - }); - }); - - it('should pass an onResponse that triggers original onResponse only once all intercept dones are called', () => { - callInterceptor(); - const interceptedOnResponse = next.args[0][next.args[0].length - 1].onResponse; - expect(onResponse.called).to.be.false; - const responseArgs = ['dummy', 'args']; - interceptedOnResponse(...responseArgs); - expect(onResponse.called).to.be.false; - dones.forEach((f, i) => { - f(); - expect(onResponse.called).to.equal(i === dones.length - 1); - }); - expect(onResponse.calledOnceWith(...responseArgs)).to.be.true; - }); - }); -}); diff --git a/test/spec/modules/deepintentBidAdapter_spec.js b/test/spec/modules/deepintentBidAdapter_spec.js index d2a351b4089..fcf7056fb3f 100644 --- a/test/spec/modules/deepintentBidAdapter_spec.js +++ b/test/spec/modules/deepintentBidAdapter_spec.js @@ -3,8 +3,8 @@ import {spec} from 'modules/deepintentBidAdapter.js'; import * as utils from '../../../src/utils.js'; describe('Deepintent adapter', function () { - let request, videoBidRequests; - let bannerResponse, videoBidResponse, invalidResponse; + let request; + let bannerResponse; beforeEach(function () { request = [ @@ -32,38 +32,6 @@ describe('Deepintent adapter', function () { } } ]; - videoBidRequests = - [ - { - code: 'video1', - mediaTypes: { - video: { - playerSize: [640, 480], - context: 'instream' - } - }, - bidder: 'deepintent', - bidId: '22bddb28db77d', - params: { - tagId: '100013', - video: { - mimes: ['video/mp4', 'video/x-flv'], - skippable: true, - testwrongparam: 3, - testwrongparam1: 'wrong', - minduration: 5, - maxduration: 30, - startdelay: 5, - playbackmethod: [1, 3], - api: [1, 2], - protocols: [2, 3], - battr: [13, 14], - minbitrate: 10, - maxbitrate: 10 - } - } - } - ]; bannerResponse = { 'body': { 'id': '303e1fae-9677-41e2-9a92-15a23445363f', @@ -85,47 +53,7 @@ describe('Deepintent adapter', function () { }], 'bidid': '0b08b09f-aaa1-4c14-b1c8-7debb1a7c1cd' } - }; - invalidResponse = { - 'body': { - 'id': '303e1fae-9677-41e2-9a92-15a23445363f', - 'seatbid': [{ - 'bid': [{ - 'id': '11447bb1-a266-470d-b0d7-8810f5b1b75f', - 'impid': 'a7e92b9b-d9db-4de8-9c3f-f90737335445', - 'price': 0.6, - 'adid': '10001', - 'adm': 'invalid response', - 'adomain': ['deepintent.com'], - 'cid': '103389', - 'crid': '13665', - 'w': 300, - 'h': 250, - 'dealId': 'dee_12312stdszzsx' - }], - 'seat': '10000' - }], - 'bidid': '0b08b09f-aaa1-4c14-b1c8-7debb1a7c1cd' - } - }; - videoBidResponse = { - 'body': { - 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', - 'seatbid': [{ - 'bid': [{ - 'id': '74858439-49D7-4169-BA5D-44A046315B2F', - 'impid': '22bddb28db77d', - 'price': 1.3, - 'adm': 'Acudeo CompatibleVAST 2.0 Instream Test 1VAST 2.0 Instream Test 1https://dsptracker.com/{PSPM}00:00:04https://www.deepintent.com', - 'h': 250, - 'w': 300, - 'ext': { - 'deal_channel': 6 - } - }] - }] - } - }; + } }); describe('validations', function () { @@ -160,45 +88,6 @@ describe('Deepintent adapter', function () { isValid = spec.isBidRequestValid(bid); expect(isValid).to.equals(false); }); - it('should check for context if video is present', function() { - let bid = { - bidder: 'deepintent', - params: { - tagId: '12345', - video: { - mimes: ['video/mp4', 'video/x-flv'], - skippable: true, - } - }, - mediaTypes: { - video: { - playerSize: [640, 480], - context: 'instream' - } - }, - }, - isValid = spec.isBidRequestValid(bid); - expect(isValid).to.equal(true); - }); - it('should error out if context is not present and is Video', function() { - let bid = { - bidder: 'deepintent', - params: { - tagId: '12345', - video: { - mimes: ['video/mp4', 'video/x-flv'], - skippable: true, - } - }, - mediaTypes: { - video: { - playerSize: [640, 480] - } - }, - }, - isValid = spec.isBidRequestValid(bid); - expect(isValid).to.equal(false); - }) }); describe('request check', function () { it('unmutaable bid request check', function () { @@ -290,28 +179,6 @@ describe('Deepintent adapter', function () { expect(data2.regs).to.equal(undefined); expect(data2.user.ext).to.equal(undefined); }); - it('bid request check: Video params check ', function() { - let bRequest = spec.buildRequests(videoBidRequests); - let data = JSON.parse(bRequest.data); - expect(data.imp[0].video).to.be.a('object'); - expect(data.imp[0].video.minduration).to.be.a('number'); - expect(data.imp[0].video.maxduration).to.be.a('number'); - expect(data.imp[0].video.startdelay).to.be.a('number'); - expect(data.imp[0].video.playbackmethod).to.be.an('array'); - expect(data.imp[0].video.api).to.be.an('array'); - expect(data.imp[0].video.protocols).to.be.an('array'); - expect(data.imp[0].video.battr).to.be.an('array'); - expect(data.imp[0].video.minbitrate).to.be.a('number'); - expect(data.imp[0].video.maxbitrate).to.be.a('number'); - expect(data.imp[0].video.w).to.be.a('number'); - }); - it('bid request param check : invalid video params', function() { - let bRequest = spec.buildRequests(videoBidRequests); - let data = JSON.parse(bRequest.data); - expect(data.imp[0].video).to.be.a('object'); - expect(data.imp[0].video.testwrongparam).to.equal(undefined); - expect(data.imp[0].video.testwrongparam1).to.equal(undefined); - }); }); describe('user sync check', function () { it('user sync url check', function () { @@ -335,27 +202,10 @@ describe('Deepintent adapter', function () { expect(bResponse[0].height).to.equal(bannerResponse.body.seatbid[0].bid[0].h); expect(bResponse[0].currency).to.equal('USD'); expect(bResponse[0].netRevenue).to.equal(false); - expect(bResponse[0].mediaType).to.equal('banner'); expect(bResponse[0].meta.advertiserDomains).to.deep.equal(['deepintent.com']); expect(bResponse[0].ttl).to.equal(300); expect(bResponse[0].creativeId).to.equal(bannerResponse.body.seatbid[0].bid[0].crid); expect(bResponse[0].dealId).to.equal(bannerResponse.body.seatbid[0].bid[0].dealId); }); - it('bid response check: valid video bid response', function() { - let request = spec.buildRequests(videoBidRequests); - let response = spec.interpretResponse(videoBidResponse, request); - expect(response[0].mediaType).to.equal('video'); - expect(response[0].vastXml).to.not.equal(undefined); - }); - it('invalid bid response check ', function() { - let bRequest = spec.buildRequests(request); - let response = spec.interpretResponse(invalidResponse, bRequest); - expect(response[0].mediaType).to.equal(undefined); - }); - it('invalid bid response check ', function() { - let bRequest = spec.buildRequests(videoBidRequests); - let response = spec.interpretResponse(invalidResponse, bRequest); - expect(response[0].mediaType).to.equal(undefined); - }); }) }); diff --git a/test/spec/modules/deepintentDpesIdsystem_spec.js b/test/spec/modules/deepintentDpesIdsystem_spec.js index 4c26b118a98..7ea5553393c 100644 --- a/test/spec/modules/deepintentDpesIdsystem_spec.js +++ b/test/spec/modules/deepintentDpesIdsystem_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import {find} from 'src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; import { storage, deepintentDpesSubmodule } from 'modules/deepintentDpesIdSystem.js'; import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; import { config } from 'src/config.js'; diff --git a/test/spec/modules/deltaprojectsBidAdapter_spec.js b/test/spec/modules/deltaprojectsBidAdapter_spec.js deleted file mode 100644 index 382415eab62..00000000000 --- a/test/spec/modules/deltaprojectsBidAdapter_spec.js +++ /dev/null @@ -1,399 +0,0 @@ -import { expect } from 'chai'; -import { - BIDDER_CODE, - BIDDER_ENDPOINT_URL, - spec, USERSYNC_URL, - getBidFloor -} from 'modules/deltaprojectsBidAdapter.js'; - -const BID_REQ_REFER = 'http://example.com/page?param=val'; - -describe('deltaprojectsBidAdapter', function() { - describe('isBidRequestValid', function () { - function makeBid() { - return { - bidder: BIDDER_CODE, - params: { - publisherId: '12345' - }, - adUnitCode: 'adunit-code', - sizes: [ - [300, 250], - ], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - }; - } - - it('should return true when bidder set correctly', function () { - expect(spec.isBidRequestValid(makeBid())).to.equal(true); - }); - - it('should return false when bid request is null', function () { - expect(spec.isBidRequestValid(undefined)).to.equal(false); - }); - - it('should return false when bidder not set correctly', function () { - let bid = makeBid(); - delete bid.bidder; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when publisher id is not set', function () { - let bid = makeBid(); - delete bid.params.publisherId; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - const BIDREQ = { - bidder: BIDDER_CODE, - params: { - tagId: '403370', - siteId: 'example.com', - }, - sizes: [ - [300, 250], - ], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - } - const bidRequests = [BIDREQ]; - const bannerRequest = spec.buildRequests(bidRequests, {refererInfo: { referer: BID_REQ_REFER }})[0]; - const bannerRequestBody = bannerRequest.data; - - it('send bid request with test tag if it is set in the param', function () { - const TEST_TAG = 1; - const bidRequest = Object.assign({}, BIDREQ, { - params: { ...BIDREQ.params, test: TEST_TAG }, - }); - const bidderRequest = { refererInfo: { referer: BID_REQ_REFER } }; - const request = spec.buildRequests([bidRequest], bidderRequest)[0]; - expect(request.data.test).to.equal(TEST_TAG); - }); - - it('send bid request with correct timeout', function () { - const TMAX = 10; - const bidderRequest = { refererInfo: { referer: BID_REQ_REFER }, timeout: TMAX }; - const request = spec.buildRequests(bidRequests, bidderRequest)[0]; - expect(request.data.tmax).to.equal(TMAX); - }); - - it('send bid request to the correct endpoint URL', function () { - expect(bannerRequest.url).to.equal(BIDDER_ENDPOINT_URL); - }); - - it('sends bid request to our endpoint via POST', function () { - expect(bannerRequest.method).to.equal('POST'); - }); - - it('sends screen dimensions', function () { - expect(bannerRequestBody.device.w).to.equal(screen.width); - expect(bannerRequestBody.device.h).to.equal(screen.height); - }); - - it('includes the ad size in the bid request', function () { - expect(bannerRequestBody.imp[0].banner.format[0].w).to.equal(BIDREQ.sizes[0][0]); - expect(bannerRequestBody.imp[0].banner.format[0].h).to.equal(BIDREQ.sizes[0][1]); - }); - - it('sets domain and href correctly', function () { - expect(bannerRequestBody.site.domain).to.equal(BIDREQ.params.siteId); - expect(bannerRequestBody.site.page).to.equal(BID_REQ_REFER); - }); - - const gdprBidRequests = [{ - bidder: BIDDER_CODE, - params: { - tagId: '403370', - siteId: 'example.com' - }, - sizes: [ - [300, 250] - ], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475' - }]; - const consentString = 'BOJ/P2HOJ/P2HABABMAAAAAZ+A=='; - - const GDPR_REQ_REFERER = 'http://localhost:9876/' - function getGdprRequestBody(gdprApplies, consentString) { - const gdprRequest = spec.buildRequests(gdprBidRequests, { - gdprConsent: { - gdprApplies: gdprApplies, - consentString: consentString, - }, - refererInfo: { - referer: GDPR_REQ_REFERER, - }, - })[0]; - return gdprRequest.data; - } - - it('should handle gdpr applies being present and true', function() { - const gdprRequestBody = getGdprRequestBody(true, consentString); - expect(gdprRequestBody.regs.ext.gdpr).to.equal(1); - expect(gdprRequestBody.user.ext.consent).to.equal(consentString); - }) - - it('should handle gdpr applies being present and false', function() { - const gdprRequestBody = getGdprRequestBody(false, consentString); - expect(gdprRequestBody.regs.ext.gdpr).to.equal(0); - expect(gdprRequestBody.user.ext.consent).to.equal(consentString); - }) - - it('should handle gdpr applies being undefined', function() { - const gdprRequestBody = getGdprRequestBody(undefined, consentString); - expect(gdprRequestBody.regs).to.deep.equal({ext: {}}); - expect(gdprRequestBody.user.ext.consent).to.equal(consentString); - }) - - it('should handle gdpr consent being undefined', function() { - const gdprRequest = spec.buildRequests(gdprBidRequests, {refererInfo: { referer: GDPR_REQ_REFERER }})[0]; - const gdprRequestBody = gdprRequest.data; - expect(gdprRequestBody.regs).to.deep.equal({ ext: {} }); - expect(gdprRequestBody.user).to.deep.equal({ ext: {} }); - }) - }); - - describe('interpretResponse', function () { - const bidRequests = [ - { - bidder: BIDDER_CODE, - params: { - tagId: '403370', - siteId: 'example.com', - currency: 'USD', - }, - sizes: [ - [300, 250], - ], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - }, - ]; - const request = spec.buildRequests(bidRequests, {refererInfo: { referer: BID_REQ_REFER }})[0]; - function makeResponse() { - return { - body: { - id: '5e5c23a5ba71e78', - seatbid: [ - { - bid: [ - { - id: '6vmb3isptf', - crid: 'deltaprojectscreative', - impid: '322add653672f68', - price: 1.22, - adm: '', - attr: [5], - h: 90, - nurl: 'http://nurl', - w: 728, - } - ], - seat: 'MOCK' - } - ], - bidid: '5e5c23a5ba71e78', - cur: 'USD' - } - }; - } - const expectedBid = { - requestId: '322add653672f68', - cpm: 1.22, - width: 728, - height: 90, - creativeId: 'deltaprojectscreative', - dealId: null, - currency: 'USD', - netRevenue: true, - mediaType: 'banner', - ttl: 60, - ad: '
' - }; - - it('should get incorrect bid response if response body is missing', function () { - let response = makeResponse(); - delete response.body; - let result = spec.interpretResponse(response, request); - expect(result.length).to.equal(0); - }); - - it('should get incorrect bid response if id or seat id of response body is missing', function () { - let response1 = makeResponse(); - delete response1.body.id; - let result1 = spec.interpretResponse(response1, request); - expect(result1.length).to.equal(0); - - let response2 = makeResponse(); - delete response2.body.seatbid; - let result2 = spec.interpretResponse(response2, request); - expect(result2.length).to.equal(0); - }); - - it('should get the correct bid response', function () { - let result = spec.interpretResponse(makeResponse(), request); - expect(result.length).to.equal(1); - expect(result[0]).to.deep.equal(expectedBid); - }); - - it('should handle a missing crid', function () { - let noCridResponse = makeResponse(); - delete noCridResponse.body.seatbid[0].bid[0].crid; - const fallbackCrid = noCridResponse.body.seatbid[0].bid[0].id; - let noCridResult = Object.assign({}, expectedBid, {'creativeId': fallbackCrid}); - let result = spec.interpretResponse(noCridResponse, request); - expect(result.length).to.equal(1); - expect(result[0]).to.deep.equal(noCridResult); - }); - - it('should handle a missing nurl', function () { - let noNurlResponse = makeResponse(); - delete noNurlResponse.body.seatbid[0].bid[0].nurl; - let noNurlResult = Object.assign({}, expectedBid); - noNurlResult.ad = ''; - let result = spec.interpretResponse(noNurlResponse, request); - expect(result.length).to.equal(1); - expect(result[0]).to.deep.equal(noNurlResult); - }); - - it('handles empty bid response', function () { - let response = { - body: { - id: '5e5c23a5ba71e78', - seatbid: [] - } - }; - let result = spec.interpretResponse(response, request); - expect(result.length).to.equal(0); - }); - - it('should keep custom properties', () => { - const customProperties = {test: 'a test message', param: {testParam: 1}}; - const expectedResult = Object.assign({}, expectedBid, {[spec.code]: customProperties}); - const response = makeResponse(); - response.body.seatbid[0].bid[0].ext = customProperties; - const result = spec.interpretResponse(response, request); - expect(result.length).to.equal(1); - expect(result[0]).to.deep.equal(expectedResult); - }); - }); - - describe('onBidWon', function () { - const OPEN_RTB_RESP = { - body: { - id: 'abc', - seatbid: [ - { - bid: [ - { - 'id': 'abc*123*456', - 'impid': 'xxxxxxx', - 'price': 46.657196, - 'adm': '', - 'adid': '56380110', - 'cid': '44724710', - 'crid': '443801010', - 'w': 300, - 'h': 250, - 'ext': { - 'prebid': { - 'targeting': { - 'hb_bidder': 'luponmedia', - 'hb_pb': '0.40', - 'hb_size': '300x250' - }, - 'type': 'banner' - } - } - } - ], - 'seat': 'luponmedia' - } - ], - 'cur': 'USD', - 'ext': { - 'responsetimemillis': { - 'luponmedia': 233 - }, - 'tmaxrequest': 1500, - 'usersyncs': { - 'status': 'ok', - 'bidder_status': [] - } - } - }; - - let expectedResponse = [ - { - 'requestId': '2a122246ef72ea', - 'cpm': '0.43', - 'width': 300, - 'height': 250, - 'creativeId': '443801010', - 'currency': 'USD', - 'dealId': '23425', - 'netRevenue': false, - 'ttl': 300, - 'referrer': '', - 'ad': ' ' - } - ]; - - let bidderRequest = { - 'data': '{"site":{"page":"https://novi.ba/clanak/176067/fast-car-beginner-s-guide-to-tuning-turbo-engines"}}' - }; - - let result = spec.interpretResponse({ body: response }, bidderRequest); - expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); - }); - - it('handles nobid responses', function () { - let noBidResponse = []; - - let noBidBidderRequest = { - 'data': '{"site":{"page":""}}' - } - let noBidResult = spec.interpretResponse({ body: noBidResponse }, noBidBidderRequest); - expect(noBidResult.length).to.equal(0); - }); - }); - - describe('getUserSyncs', function () { - const bidResponse1 = { - 'body': { - 'ext': { - 'responsetimemillis': { - 'luponmedia': 233 - }, - 'tmaxrequest': 1500, - 'usersyncs': { - 'status': 'ok', - 'bidder_status': [ - { - 'bidder': 'luponmedia', - 'no_cookie': true, - 'usersync': { - 'url': 'https://adxpremium.services/api/usersync', - 'type': 'redirect' - } - }, - { - 'bidder': 'luponmedia', - 'no_cookie': true, - 'usersync': { - 'url': 'https://adxpremium.services/api/iframeusersync', - 'type': 'iframe' - } - } - ] - } - } - } - }; - - const bidResponse2 = { - 'body': { - 'ext': { - 'responsetimemillis': { - 'luponmedia': 233 - }, - 'tmaxrequest': 1500, - 'usersyncs': { - 'status': 'no_cookie', - 'bidder_status': [] - } - } - } - }; - - it('should use a sync url from first response (pixel and iframe)', function () { - const syncs = spec.getUserSyncs({ pixelEnabled: true, iframeEnabled: true }, [bidResponse1, bidResponse2]); - expect(syncs).to.deep.equal([ - { - type: 'image', - url: 'https://adxpremium.services/api/usersync' - }, - { - type: 'iframe', - url: 'https://adxpremium.services/api/iframeusersync' - } - ]); - }); - - it('handle empty response (e.g. timeout)', function () { - const syncs = spec.getUserSyncs({ pixelEnabled: true, iframeEnabled: true }, []); - expect(syncs).to.deep.equal([]); - }); - - it('returns empty syncs when not pixel enabled and not iframe enabled', function () { - const syncs = spec.getUserSyncs({ pixelEnabled: false, iframeEnabled: false }, [bidResponse1]); - expect(syncs).to.deep.equal([]); - }); - - it('returns pixel syncs when pixel enabled and not iframe enabled', function() { - resetUserSync(); - - const syncs = spec.getUserSyncs({ pixelEnabled: true, iframeEnabled: false }, [bidResponse1]); - expect(syncs).to.deep.equal([ - { - type: 'image', - url: 'https://adxpremium.services/api/usersync' - } - ]); - }); - - it('returns iframe syncs when not pixel enabled and iframe enabled', function() { - resetUserSync(); - - const syncs = spec.getUserSyncs({ pixelEnabled: false, iframeEnabled: true }, [bidResponse1]); - expect(syncs).to.deep.equal([ - { - type: 'iframe', - url: 'https://adxpremium.services/api/iframeusersync' - } - ]); - }); - }); - - describe('hasValidSupplyChainParams', function () { - it('returns true if schain is valid', function () { - const schain = { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'novi.ba', - 'sid': '199424', - 'hp': 1 - } - ] - }; - - const checkSchain = hasValidSupplyChainParams(schain); - expect(checkSchain).to.equal(true); - }); - - it('returns false if schain is invalid', function () { - const schain = { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'invalid': 'novi.ba' - } - ] - }; - - const checkSchain = hasValidSupplyChainParams(schain); - expect(checkSchain).to.equal(false); - }); - }); - - describe('onBidWon', function () { - const bidWonEvent = { - 'bidderCode': 'luponmedia', - 'width': 300, - 'height': 250, - 'statusMessage': 'Bid available', - 'adId': '105bbf8c54453ff', - 'requestId': '934b8752185955', - 'mediaType': 'banner', - 'source': 'client', - 'cpm': 0.364, - 'creativeId': '443801010', - 'currency': 'USD', - 'netRevenue': false, - 'ttl': 300, - 'referrer': '', - 'ad': '', - 'auctionId': '926a8ea3-3dd4-4bf2-95ab-c85c2ce7e99b', - 'responseTimestamp': 1598527728026, - 'requestTimestamp': 1598527727629, - 'bidder': 'luponmedia', - 'adUnitCode': 'div-gpt-ad-1533155193780-5', - 'timeToRespond': 397, - 'size': '300x250', - 'status': 'rendered' - }; - - let ajaxStub; - - beforeEach(() => { - ajaxStub = sinon.stub(spec, 'sendWinningsToServer') - }) - - afterEach(() => { - ajaxStub.restore() - }) - - it('calls luponmedia\'s callback endpoint', () => { - const result = spec.onBidWon(bidWonEvent); - expect(result).to.equal(undefined); - expect(ajaxStub.calledOnce).to.equal(true); - expect(ajaxStub.firstCall.args[0]).to.deep.equal(JSON.stringify(bidWonEvent)); - }); - }); -}); diff --git a/test/spec/modules/malltvAnalyticsAdapter_spec.js b/test/spec/modules/malltvAnalyticsAdapter_spec.js index c96069df0f9..599ac6e4256 100644 --- a/test/spec/modules/malltvAnalyticsAdapter_spec.js +++ b/test/spec/modules/malltvAnalyticsAdapter_spec.js @@ -4,7 +4,7 @@ import { } from 'modules/malltvAnalyticsAdapter.js' import { expect } from 'chai' import { getCpmInEur } from '../../../modules/malltvAnalyticsAdapter' -import * as events from 'src/events' +import events from 'src/events' import constants from 'src/constants.json' const auctionId = 'b0b39610-b941-4659-a87c-de9f62d3e13e' diff --git a/test/spec/modules/mass_spec.js b/test/spec/modules/mass_spec.js index 3b5d89b0a8c..a4a87ce113f 100644 --- a/test/spec/modules/mass_spec.js +++ b/test/spec/modules/mass_spec.js @@ -60,9 +60,17 @@ const mockedNonMassBids = [ }, ]; +// mock bidder request: +const mockedBidderRequest = { + bidderCode: 'ix', + bidderRequestId: 'bidder-request-id-1' +}; + const noop = function() {}; describe('MASS Module', function() { + let bidderRequest = Object.assign({}, mockedBidderRequest); + it('should be enabled by default', function() { expect(isEnabled).to.equal(true); }); @@ -78,7 +86,9 @@ describe('MASS Module', function() { const originalBid = Object.assign({}, mockedBid); const bid = Object.assign({}, originalBid); - addBidResponseHook(noop, 'ad-code-id', bid); + bidderRequest.bids = [bid]; + + addBidResponseHook.call({bidderRequest}, noop, 'ad-code-id', bid); expect(bid).to.deep.equal(originalBid); }); @@ -90,7 +100,9 @@ describe('MASS Module', function() { const originalBid = Object.assign({}, mockedBid); const bid = Object.assign({}, originalBid); - addBidResponseHook(noop, 'ad-code-id', bid); + bidderRequest.bids = [bid]; + + addBidResponseHook.call({bidderRequest}, noop, 'ad-code-id', bid); expect(bid.ad).to.not.equal(originalBid.ad); diff --git a/test/spec/modules/mediafuseBidAdapter_spec.js b/test/spec/modules/mediafuseBidAdapter_spec.js deleted file mode 100644 index f4defa293e1..00000000000 --- a/test/spec/modules/mediafuseBidAdapter_spec.js +++ /dev/null @@ -1,1442 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/mediafuseBidAdapter.js'; -import { newBidder } from 'src/adapters/bidderFactory.js'; -import * as bidderFactory from 'src/adapters/bidderFactory.js'; -import { auctionManager } from 'src/auctionManager.js'; -import { deepClone } from 'src/utils.js'; -import { config } from 'src/config.js'; - -const ENDPOINT = 'https://ib.adnxs.com/ut/v3/prebid'; - -describe('MediaFuseAdapter', function () { - const adapter = newBidder(spec); - - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', function () { - let bid = { - 'bidder': 'mediafuse', - 'params': { - 'placementId': '10433394' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }; - - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return true when required params found', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - 'member': '1234', - 'invCode': 'ABCD' - }; - - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when required params are not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - 'placementId': 0 - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - let getAdUnitsStub; - let bidRequests = [ - { - 'bidder': 'mediafuse', - 'params': { - 'placementId': '10433394' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'transactionId': '04f2659e-c005-4eb1-a57c-fa93145e3843' - } - ]; - - beforeEach(function() { - getAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits').callsFake(function() { - return []; - }); - }); - - afterEach(function() { - getAdUnitsStub.restore(); - }); - - it('should parse out private sizes', function () { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - privateSizes: [300, 250] - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].private_sizes).to.exist; - expect(payload.tags[0].private_sizes).to.deep.equal([{width: 300, height: 250}]); - }); - - it('should add publisher_id in request', function() { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - publisherId: '1231234' - } - }); - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].publisher_id).to.exist; - expect(payload.tags[0].publisher_id).to.deep.equal(1231234); - expect(payload.publisher_id).to.exist; - expect(payload.publisher_id).to.deep.equal(1231234); - }) - - it('should add source and verison to the tag', function () { - const request = spec.buildRequests(bidRequests); - const payload = JSON.parse(request.data); - expect(payload.sdk).to.exist; - expect(payload.sdk).to.deep.equal({ - source: 'pbjs', - version: '$prebid.version$' - }); - }); - - it('should populate the ad_types array on all requests', function () { - let adUnits = [{ - code: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - bids: [{ - bidder: 'mediafuse', - params: { - placementId: '10433394' - } - }], - transactionId: '04f2659e-c005-4eb1-a57c-fa93145e3843' - }]; - - ['banner', 'video', 'native'].forEach(type => { - getAdUnitsStub.callsFake(function(...args) { - return adUnits; - }); - - const bidRequest = Object.assign({}, bidRequests[0]); - bidRequest.mediaTypes = {}; - bidRequest.mediaTypes[type] = {}; - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].ad_types).to.deep.equal([type]); - - if (type === 'banner') { - delete adUnits[0].mediaTypes; - } - }); - }); - - it('should not populate the ad_types array when adUnit.mediaTypes is undefined', function() { - const bidRequest = Object.assign({}, bidRequests[0]); - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].ad_types).to.not.exist; - }); - - it('should populate the ad_types array on outstream requests', function () { - const bidRequest = Object.assign({}, bidRequests[0]); - bidRequest.mediaTypes = {}; - bidRequest.mediaTypes.video = {context: 'outstream'}; - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].ad_types).to.deep.equal(['video']); - expect(payload.tags[0].hb_source).to.deep.equal(1); - }); - - it('sends bid request to ENDPOINT via POST', function () { - const request = spec.buildRequests(bidRequests); - expect(request.url).to.equal(ENDPOINT); - expect(request.method).to.equal('POST'); - }); - - it('should attach valid video params to the tag', function () { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - video: { - id: 123, - minduration: 100, - foobar: 'invalid' - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags[0].video).to.deep.equal({ - id: 123, - minduration: 100 - }); - expect(payload.tags[0].hb_source).to.deep.equal(1); - }); - - it('should include ORTB video values when video params were not set', function() { - let bidRequest = deepClone(bidRequests[0]); - bidRequest.params = { - placementId: '1234235', - video: { - skippable: true, - playback_method: ['auto_play_sound_off', 'auto_play_sound_unknown'], - context: 'outstream' - } - }; - bidRequest.mediaTypes = { - video: { - playerSize: [640, 480], - context: 'outstream', - mimes: ['video/mp4'], - skip: 0, - minduration: 5, - api: [1, 5, 6], - playbackmethod: [2, 4] - } - }; - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].video).to.deep.equal({ - minduration: 5, - playback_method: 2, - skippable: true, - context: 4 - }); - expect(payload.tags[0].video_frameworks).to.deep.equal([1, 4]) - }); - - it('should add video property when adUnit includes a renderer', function () { - const videoData = { - mediaTypes: { - video: { - context: 'outstream', - mimes: ['video/mp4'] - } - }, - params: { - placementId: '10433394', - video: { - skippable: true, - playback_method: ['auto_play_sound_off'] - } - } - }; - - let bidRequest1 = deepClone(bidRequests[0]); - bidRequest1 = Object.assign({}, bidRequest1, videoData, { - renderer: { - url: 'https://test.renderer.url', - render: function () {} - } - }); - - let bidRequest2 = deepClone(bidRequests[0]); - bidRequest2.adUnitCode = 'adUnit_code_2'; - bidRequest2 = Object.assign({}, bidRequest2, videoData); - - const request = spec.buildRequests([bidRequest1, bidRequest2]); - const payload = JSON.parse(request.data); - expect(payload.tags[0].video).to.deep.equal({ - skippable: true, - playback_method: 2, - custom_renderer_present: true - }); - expect(payload.tags[1].video).to.deep.equal({ - skippable: true, - playback_method: 2 - }); - }); - - it('should attach valid user params to the tag', function () { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - user: { - externalUid: '123', - segments: [123, { id: 987, value: 876 }], - foobar: 'invalid' - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.user).to.exist; - expect(payload.user).to.deep.equal({ - external_uid: '123', - segments: [{id: 123}, {id: 987, value: 876}] - }); - }); - - it('should attach reserve param when either bid param or getFloor function exists', function () { - let getFloorResponse = { currency: 'USD', floor: 3 }; - let request, payload = null; - let bidRequest = deepClone(bidRequests[0]); - - // 1 -> reserve not defined, getFloor not defined > empty - request = spec.buildRequests([bidRequest]); - payload = JSON.parse(request.data); - - expect(payload.tags[0].reserve).to.not.exist; - - // 2 -> reserve is defined, getFloor not defined > reserve is used - bidRequest.params = { - 'placementId': '10433394', - 'reserve': 0.5 - }; - request = spec.buildRequests([bidRequest]); - payload = JSON.parse(request.data); - - expect(payload.tags[0].reserve).to.exist.and.to.equal(0.5); - - // 3 -> reserve is defined, getFloor is defined > getFloor is used - bidRequest.getFloor = () => getFloorResponse; - - request = spec.buildRequests([bidRequest]); - payload = JSON.parse(request.data); - - expect(payload.tags[0].reserve).to.exist.and.to.equal(3); - }); - - it('should duplicate adpod placements into batches and set correct maxduration', function() { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - - // 300 / 15 = 20 total - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(5); - - expect(payload1.tags[0]).to.deep.equal(payload1.tags[1]); - expect(payload1.tags[0].video.maxduration).to.equal(30); - - expect(payload2.tags[0]).to.deep.equal(payload1.tags[1]); - expect(payload2.tags[0].video.maxduration).to.equal(30); - }); - - it('should round down adpod placements when numbers are uneven', function() { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 123, - durationRangeSec: [45], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags.length).to.equal(2); - }); - - it('should duplicate adpod placements when requireExactDuration is set', function() { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - requireExactDuration: true, - } - } - } - ); - - // 20 total placements with 15 max impressions = 2 requests - const request = spec.buildRequests([bidRequest]); - expect(request.length).to.equal(2); - - // 20 spread over 2 requests = 15 in first request, 5 in second - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(5); - - // 10 placements should have max/min at 15 - // 10 placemenst should have max/min at 30 - const payload1tagsWith15 = payload1.tags.filter(tag => tag.video.maxduration === 15); - const payload1tagsWith30 = payload1.tags.filter(tag => tag.video.maxduration === 30); - expect(payload1tagsWith15.length).to.equal(10); - expect(payload1tagsWith30.length).to.equal(5); - - // 5 placemenst with min/max at 30 were in the first request - // so 5 remaining should be in the second - const payload2tagsWith30 = payload2.tags.filter(tag => tag.video.maxduration === 30); - expect(payload2tagsWith30.length).to.equal(5); - }); - - it('should set durations for placements when requireExactDuration is set and numbers are uneven', function() { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 105, - durationRangeSec: [15, 30, 60], - requireExactDuration: true, - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags.length).to.equal(7); - - const tagsWith15 = payload.tags.filter(tag => tag.video.maxduration === 15); - const tagsWith30 = payload.tags.filter(tag => tag.video.maxduration === 30); - const tagsWith60 = payload.tags.filter(tag => tag.video.maxduration === 60); - expect(tagsWith15.length).to.equal(3); - expect(tagsWith30.length).to.equal(3); - expect(tagsWith60.length).to.equal(1); - }); - - it('should break adpod request into batches', function() { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 225, - durationRangeSec: [5], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - const payload3 = JSON.parse(request[2].data); - - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(15); - expect(payload3.tags.length).to.equal(15); - }); - - it('should contain hb_source value for adpod', function() { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - } - } - } - ); - const request = spec.buildRequests([bidRequest])[0]; - const payload = JSON.parse(request.data); - expect(payload.tags[0].hb_source).to.deep.equal(7); - }); - - it('should contain hb_source value for other media', function() { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'banner', - params: { - sizes: [[300, 250], [300, 600]], - placementId: 13144370 - } - } - ); - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags[0].hb_source).to.deep.equal(1); - }); - - it('adds brand_category_exclusion to request when set', function() { - let bidRequest = Object.assign({}, bidRequests[0]); - sinon - .stub(config, 'getConfig') - .withArgs('adpod.brandCategoryExclusion') - .returns(true); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.brand_category_uniqueness).to.equal(true); - - config.getConfig.restore(); - }); - - it('adds auction level keywords to request when set', function() { - let bidRequest = Object.assign({}, bidRequests[0]); - sinon - .stub(config, 'getConfig') - .withArgs('mediafuseAuctionKeywords') - .returns({ - gender: 'm', - music: ['rock', 'pop'], - test: '' - }); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.keywords).to.deep.equal([{ - 'key': 'gender', - 'value': ['m'] - }, { - 'key': 'music', - 'value': ['rock', 'pop'] - }, { - 'key': 'test' - }]); - - config.getConfig.restore(); - }); - - it('should attach native params to the request', function () { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - title: {required: true}, - body: {required: true}, - body2: {required: true}, - image: {required: true, sizes: [100, 100]}, - icon: {required: true}, - cta: {required: false}, - rating: {required: true}, - sponsoredBy: {required: true}, - privacyLink: {required: true}, - displayUrl: {required: true}, - address: {required: true}, - downloads: {required: true}, - likes: {required: true}, - phone: {required: true}, - price: {required: true}, - salePrice: {required: true} - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - title: {required: true}, - description: {required: true}, - desc2: {required: true}, - main_image: {required: true, sizes: [{ width: 100, height: 100 }]}, - icon: {required: true}, - ctatext: {required: false}, - rating: {required: true}, - sponsored_by: {required: true}, - privacy_link: {required: true}, - displayurl: {required: true}, - address: {required: true}, - downloads: {required: true}, - likes: {required: true}, - phone: {required: true}, - price: {required: true}, - saleprice: {required: true}, - privacy_supported: true - }); - expect(payload.tags[0].hb_source).to.equal(1); - }); - - it('should always populated tags[].sizes with 1,1 for native if otherwise not defined', function () { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - image: { required: true } - } - } - ); - bidRequest.sizes = [[150, 100], [300, 250]]; - - let request = spec.buildRequests([bidRequest]); - let payload = JSON.parse(request.data); - expect(payload.tags[0].sizes).to.deep.equal([{width: 150, height: 100}, {width: 300, height: 250}]); - - delete bidRequest.sizes; - - request = spec.buildRequests([bidRequest]); - payload = JSON.parse(request.data); - - expect(payload.tags[0].sizes).to.deep.equal([{width: 1, height: 1}]); - }); - - it('should convert keyword params to proper form and attaches to request', function () { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - keywords: { - single: 'val', - singleArr: ['val'], - singleArrNum: [5], - multiValMixed: ['value1', 2, 'value3'], - singleValNum: 123, - emptyStr: '', - emptyArr: [''], - badValue: {'foo': 'bar'} // should be dropped - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].keywords).to.deep.equal([{ - 'key': 'single', - 'value': ['val'] - }, { - 'key': 'singleArr', - 'value': ['val'] - }, { - 'key': 'singleArrNum', - 'value': ['5'] - }, { - 'key': 'multiValMixed', - 'value': ['value1', '2', 'value3'] - }, { - 'key': 'singleValNum', - 'value': ['123'] - }, { - 'key': 'emptyStr' - }, { - 'key': 'emptyArr' - }]); - }); - - it('should add payment rules to the request', function () { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - usePaymentRule: true - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].use_pmt_rule).to.equal(true); - }); - - it('should add gpid to the request', function () { - let testGpid = '/12345/my-gpt-tag-0'; - let bidRequest = deepClone(bidRequests[0]); - bidRequest.ortb2Imp = { ext: { data: { pbadslot: testGpid } } }; - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].gpid).to.exist.and.equal(testGpid) - }); - - it('should add gdpr consent information to the request', function () { - let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; - let bidderRequest = { - 'bidderCode': 'mediafuse', - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000, - 'gdprConsent': { - consentString: consentString, - gdprApplies: true, - addtlConsent: '1~7.12.35.62.66.70.89.93.108' - } - }; - bidderRequest.bids = bidRequests; - - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.options).to.deep.equal({withCredentials: true}); - const payload = JSON.parse(request.data); - - expect(payload.gdpr_consent).to.exist; - expect(payload.gdpr_consent.consent_string).to.exist.and.to.equal(consentString); - expect(payload.gdpr_consent.consent_required).to.exist.and.to.be.true; - expect(payload.gdpr_consent.addtl_consent).to.exist.and.to.deep.equal([7, 12, 35, 62, 66, 70, 89, 93, 108]); - }); - - it('should add us privacy string to payload', function() { - let consentString = '1YA-'; - let bidderRequest = { - 'bidderCode': 'mediafuse', - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000, - 'uspConsent': consentString - }; - bidderRequest.bids = bidRequests; - - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - - expect(payload.us_privacy).to.exist; - expect(payload.us_privacy).to.exist.and.to.equal(consentString); - }); - - it('supports sending hybrid mobile app parameters', function () { - let appRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - app: { - id: 'B1O2W3M4AN.com.prebid.webview', - geo: { - lat: 40.0964439, - lng: -75.3009142 - }, - device_id: { - idfa: '4D12078D-3246-4DA4-AD5E-7610481E7AE', // Apple advertising identifier - aaid: '38400000-8cf0-11bd-b23e-10b96e40000d', // Android advertising identifier - md5udid: '5756ae9022b2ea1e47d84fead75220c8', // MD5 hash of the ANDROID_ID - sha1udid: '4DFAA92388699AC6539885AEF1719293879985BF', // SHA1 hash of the ANDROID_ID - windowsadid: '750c6be243f1c4b5c9912b95a5742fc5' // Windows advertising identifier - } - } - } - } - ); - const request = spec.buildRequests([appRequest]); - const payload = JSON.parse(request.data); - expect(payload.app).to.exist; - expect(payload.app).to.deep.equal({ - appid: 'B1O2W3M4AN.com.prebid.webview' - }); - expect(payload.device.device_id).to.exist; - expect(payload.device.device_id).to.deep.equal({ - aaid: '38400000-8cf0-11bd-b23e-10b96e40000d', - idfa: '4D12078D-3246-4DA4-AD5E-7610481E7AE', - md5udid: '5756ae9022b2ea1e47d84fead75220c8', - sha1udid: '4DFAA92388699AC6539885AEF1719293879985BF', - windowsadid: '750c6be243f1c4b5c9912b95a5742fc5' - }); - expect(payload.device.geo).to.exist; - expect(payload.device.geo).to.deep.equal({ - lat: 40.0964439, - lng: -75.3009142 - }); - }); - - it('should add referer info to payload', function () { - const bidRequest = Object.assign({}, bidRequests[0]) - const bidderRequest = { - refererInfo: { - referer: 'https://example.com/page.html', - reachedTop: true, - numIframes: 2, - stack: [ - 'https://example.com/page.html', - 'https://example.com/iframe1.html', - 'https://example.com/iframe2.html' - ] - } - } - const request = spec.buildRequests([bidRequest], bidderRequest); - const payload = JSON.parse(request.data); - - expect(payload.referrer_detection).to.exist; - expect(payload.referrer_detection).to.deep.equal({ - rd_ref: 'https%3A%2F%2Fexample.com%2Fpage.html', - rd_top: true, - rd_ifs: 2, - rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') - }); - }); - - it('should populate schain if available', function () { - const bidRequest = Object.assign({}, bidRequests[0], { - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - 'asi': 'blob.com', - 'sid': '001', - 'hp': 1 - } - ] - } - }); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.schain).to.deep.equal({ - ver: '1.0', - complete: 1, - nodes: [ - { - 'asi': 'blob.com', - 'sid': '001', - 'hp': 1 - } - ] - }); - }); - - it('should populate coppa if set in config', function () { - let bidRequest = Object.assign({}, bidRequests[0]); - sinon.stub(config, 'getConfig') - .withArgs('coppa') - .returns(true); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.user.coppa).to.equal(true); - - config.getConfig.restore(); - }); - - it('should set the X-Is-Test customHeader if test flag is enabled', function () { - let bidRequest = Object.assign({}, bidRequests[0]); - sinon.stub(config, 'getConfig') - .withArgs('apn_test') - .returns(true); - - const request = spec.buildRequests([bidRequest]); - expect(request.options.customHeaders).to.deep.equal({'X-Is-Test': 1}); - - config.getConfig.restore(); - }); - - it('should always set withCredentials: true on the request.options', function () { - let bidRequest = Object.assign({}, bidRequests[0]); - const request = spec.buildRequests([bidRequest]); - expect(request.options.withCredentials).to.equal(true); - }); - - it('should set simple domain variant if purpose 1 consent is not given', function () { - let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; - let bidderRequest = { - 'bidderCode': 'mediafuse', - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000, - 'gdprConsent': { - consentString: consentString, - gdprApplies: true, - apiVersion: 2, - vendorData: { - purpose: { - consents: { - 1: false - } - } - } - } - }; - bidderRequest.bids = bidRequests; - - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.equal('https://ib.adnxs-simple.com/ut/v3/prebid'); - }); - - it('should populate eids when supported userIds are available', function () { - const bidRequest = Object.assign({}, bidRequests[0], { - userId: { - tdid: 'sample-userid', - uid2: { id: 'sample-uid2-value' }, - criteoId: 'sample-criteo-userid', - netId: 'sample-netId-userid', - idl_env: 'sample-idl-userid', - flocId: { - id: 'sample-flocid-value', - version: 'chrome.1.0' - } - } - }); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.eids).to.deep.include({ - source: 'adserver.org', - id: 'sample-userid', - rti_partner: 'TDID' - }); - - expect(payload.eids).to.deep.include({ - source: 'criteo.com', - id: 'sample-criteo-userid', - }); - - expect(payload.eids).to.deep.include({ - source: 'chrome.com', - id: 'sample-flocid-value' - }); - - expect(payload.eids).to.deep.include({ - source: 'netid.de', - id: 'sample-netId-userid', - }); - - expect(payload.eids).to.deep.include({ - source: 'liveramp.com', - id: 'sample-idl-userid' - }); - - expect(payload.eids).to.deep.include({ - source: 'uidapi.com', - id: 'sample-uid2-value', - rti_partner: 'UID2' - }); - }); - - it('should populate iab_support object at the root level if omid support is detected', function () { - // with bid.params.frameworks - let bidRequest_A = Object.assign({}, bidRequests[0], { - params: { - frameworks: [1, 2, 5, 6], - video: { - frameworks: [1, 2, 5, 6] - } - } - }); - let request = spec.buildRequests([bidRequest_A]); - let payload = JSON.parse(request.data); - expect(payload.iab_support).to.be.an('object'); - expect(payload.iab_support).to.deep.equal({ - omidpn: 'Mediafuse', - omidpv: '$prebid.version$' - }); - expect(payload.tags[0].banner_frameworks).to.be.an('array'); - expect(payload.tags[0].banner_frameworks).to.deep.equal([1, 2, 5, 6]); - expect(payload.tags[0].video_frameworks).to.be.an('array'); - expect(payload.tags[0].video_frameworks).to.deep.equal([1, 2, 5, 6]); - expect(payload.tags[0].video.frameworks).to.not.exist; - - // without bid.params.frameworks - const bidRequest_B = Object.assign({}, bidRequests[0]); - request = spec.buildRequests([bidRequest_B]); - payload = JSON.parse(request.data); - expect(payload.iab_support).to.not.exist; - expect(payload.tags[0].banner_frameworks).to.not.exist; - expect(payload.tags[0].video_frameworks).to.not.exist; - - // with video.frameworks but it is not an array - const bidRequest_C = Object.assign({}, bidRequests[0], { - params: { - video: { - frameworks: "'1', '2', '3', '6'" - } - } - }); - request = spec.buildRequests([bidRequest_C]); - payload = JSON.parse(request.data); - expect(payload.iab_support).to.not.exist; - expect(payload.tags[0].banner_frameworks).to.not.exist; - expect(payload.tags[0].video_frameworks).to.not.exist; - }); - }) - - describe('interpretResponse', function () { - let bfStub; - let bidderSettingsStorage; - - before(function() { - bfStub = sinon.stub(bidderFactory, 'getIabSubCategory'); - bidderSettingsStorage = $$PREBID_GLOBAL$$.bidderSettings; - }); - - after(function() { - bfStub.restore(); - $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsStorage; - }); - - let response = { - 'version': '3.0.0', - 'tags': [ - { - 'uuid': '3db3773286ee59', - 'tag_id': 10433394, - 'auction_id': '4534722592064951574', - 'nobid': false, - 'no_ad_url': 'https://lax1-ib.adnxs.com/no-ad', - 'timeout_ms': 10000, - 'ad_profile_id': 27079, - 'ads': [ - { - 'content_source': 'rtb', - 'ad_type': 'banner', - 'buyer_member_id': 958, - 'creative_id': 29681110, - 'media_type_id': 1, - 'media_subtype_id': 1, - 'cpm': 0.5, - 'cpm_publisher_currency': 0.5, - 'publisher_currency_code': '$', - 'client_initiated_ad_counting': true, - 'viewability': { - 'config': '' - }, - 'rtb': { - 'banner': { - 'content': '', - 'width': 300, - 'height': 250 - }, - 'trackers': [ - { - 'impression_urls': [ - 'https://lax1-ib.adnxs.com/impression', - 'https://www.test.com/tracker' - ], - 'video_events': {} - } - ] - } - } - ] - } - ] - }; - - it('should get correct bid response', function () { - let expectedResponse = [ - { - 'requestId': '3db3773286ee59', - 'cpm': 0.5, - 'creativeId': 29681110, - 'dealId': undefined, - 'width': 300, - 'height': 250, - 'ad': '', - 'mediaType': 'banner', - 'currency': 'USD', - 'ttl': 300, - 'netRevenue': true, - 'adUnitCode': 'code', - 'mediafuse': { - 'buyerMemberId': 958 - }, - 'meta': { - 'dchain': { - 'ver': '1.0', - 'complete': 0, - 'nodes': [{ - 'bsid': '958' - }] - } - } - } - ]; - let bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code' - }] - }; - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); - }); - - it('should reject 0 cpm bids', function () { - let zeroCpmResponse = deepClone(response); - zeroCpmResponse.tags[0].ads[0].cpm = 0; - - let bidderRequest = { - bidderCode: 'mediafuse' - }; - - let result = spec.interpretResponse({ body: zeroCpmResponse }, { bidderRequest }); - expect(result.length).to.equal(0); - }); - - it('should allow 0 cpm bids if allowZeroCpmBids setConfig is true', function () { - $$PREBID_GLOBAL$$.bidderSettings = { - mediafuse: { - allowZeroCpmBids: true - } - }; - - let zeroCpmResponse = deepClone(response); - zeroCpmResponse.tags[0].ads[0].cpm = 0; - - let bidderRequest = { - bidderCode: 'mediafuse', - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code' - }] - }; - - let result = spec.interpretResponse({ body: zeroCpmResponse }, { bidderRequest }); - expect(result.length).to.equal(1); - expect(result[0].cpm).to.equal(0); - }); - - it('handles nobid responses', function () { - let response = { - 'version': '0.0.1', - 'tags': [{ - 'uuid': '84ab500420319d', - 'tag_id': 5976557, - 'auction_id': '297492697822162468', - 'nobid': true - }] - }; - let bidderRequest; - - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(result.length).to.equal(0); - }); - - it('handles outstream video responses', function () { - let response = { - 'tags': [{ - 'uuid': '84ab500420319d', - 'ads': [{ - 'ad_type': 'video', - 'cpm': 0.500000, - 'notify_url': 'imptracker.com', - 'rtb': { - 'video': { - 'content': '' - } - }, - 'javascriptTrackers': '' - }] - }] - }; - let bidderRequest = { - bids: [{ - bidId: '84ab500420319d', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'outstream' - } - } - }] - } - - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(result[0]).to.have.property('vastXml'); - expect(result[0]).to.have.property('vastImpUrl'); - expect(result[0]).to.have.property('mediaType', 'video'); - }); - - it('handles instream video responses', function () { - let response = { - 'tags': [{ - 'uuid': '84ab500420319d', - 'ads': [{ - 'ad_type': 'video', - 'cpm': 0.500000, - 'notify_url': 'imptracker.com', - 'rtb': { - 'video': { - 'asset_url': 'https://sample.vastURL.com/here/vid' - } - }, - 'javascriptTrackers': '' - }] - }] - }; - let bidderRequest = { - bids: [{ - bidId: '84ab500420319d', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'instream' - } - } - }] - } - - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(result[0]).to.have.property('vastUrl'); - expect(result[0]).to.have.property('vastImpUrl'); - expect(result[0]).to.have.property('mediaType', 'video'); - }); - - it('handles adpod responses', function () { - let response = { - 'tags': [{ - 'uuid': '84ab500420319d', - 'ads': [{ - 'ad_type': 'video', - 'brand_category_id': 10, - 'cpm': 0.500000, - 'notify_url': 'imptracker.com', - 'rtb': { - 'video': { - 'asset_url': 'https://sample.vastURL.com/here/adpod', - 'duration_ms': 30000, - } - }, - 'viewability': { - 'config': '' - } - }] - }] - }; - - let bidderRequest = { - bids: [{ - bidId: '84ab500420319d', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'adpod' - } - } - }] - }; - bfStub.returns('1'); - - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(result[0]).to.have.property('vastUrl'); - expect(result[0].video.context).to.equal('adpod'); - expect(result[0].video.durationSeconds).to.equal(30); - }); - - it('handles native responses', function () { - let response1 = deepClone(response); - response1.tags[0].ads[0].ad_type = 'native'; - response1.tags[0].ads[0].rtb.native = { - 'title': 'Native Creative', - 'desc': 'Cool description great stuff', - 'desc2': 'Additional body text', - 'ctatext': 'Do it', - 'sponsored': 'MediaFuse', - 'icon': { - 'width': 0, - 'height': 0, - 'url': 'https://cdn.adnxs.com/icon.png' - }, - 'main_img': { - 'width': 2352, - 'height': 1516, - 'url': 'https://cdn.adnxs.com/img.png' - }, - 'link': { - 'url': 'https://www.mediafuse.com', - 'fallback_url': '', - 'click_trackers': ['https://nym1-ib.adnxs.com/click'] - }, - 'impression_trackers': ['https://example.com'], - 'rating': '5', - 'displayurl': 'https://mediafuse.com/?url=display_url', - 'likes': '38908320', - 'downloads': '874983', - 'price': '9.99', - 'saleprice': 'FREE', - 'phone': '1234567890', - 'address': '28 W 23rd St, New York, NY 10010', - 'privacy_link': 'https://www.mediafuse.com/privacy-policy-agreement/', - 'javascriptTrackers': '' - }; - let bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code' - }] - } - - let result = spec.interpretResponse({ body: response1 }, {bidderRequest}); - expect(result[0].native.title).to.equal('Native Creative'); - expect(result[0].native.body).to.equal('Cool description great stuff'); - expect(result[0].native.cta).to.equal('Do it'); - expect(result[0].native.image.url).to.equal('https://cdn.adnxs.com/img.png'); - }); - - it('supports configuring outstream renderers', function () { - const outstreamResponse = deepClone(response); - outstreamResponse.tags[0].ads[0].rtb.video = {}; - outstreamResponse.tags[0].ads[0].renderer_url = 'renderer.js'; - - const bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - renderer: { - options: { - adText: 'configured' - } - }, - mediaTypes: { - video: { - context: 'outstream' - } - } - }] - }; - - const result = spec.interpretResponse({ body: outstreamResponse }, {bidderRequest}); - expect(result[0].renderer.config).to.deep.equal( - bidderRequest.bids[0].renderer.options - ); - }); - - it('should add deal_priority and deal_code', function() { - let responseWithDeal = deepClone(response); - responseWithDeal.tags[0].ads[0].ad_type = 'video'; - responseWithDeal.tags[0].ads[0].deal_priority = 5; - responseWithDeal.tags[0].ads[0].deal_code = '123'; - responseWithDeal.tags[0].ads[0].rtb.video = { - duration_ms: 1500, - player_width: 640, - player_height: 340, - }; - - let bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'adpod' - } - } - }] - } - let result = spec.interpretResponse({ body: responseWithDeal }, {bidderRequest}); - expect(Object.keys(result[0].mediafuse)).to.include.members(['buyerMemberId', 'dealPriority', 'dealCode']); - expect(result[0].video.dealTier).to.equal(5); - }); - - it('should add advertiser id', function() { - let responseAdvertiserId = deepClone(response); - responseAdvertiserId.tags[0].ads[0].advertiser_id = '123'; - - let bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code' - }] - } - let result = spec.interpretResponse({ body: responseAdvertiserId }, {bidderRequest}); - expect(Object.keys(result[0].meta)).to.include.members(['advertiserId']); - }); - - it('should add brand id', function() { - let responseBrandId = deepClone(response); - responseBrandId.tags[0].ads[0].brand_id = 123; - - let bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code' - }] - } - let result = spec.interpretResponse({ body: responseBrandId }, {bidderRequest}); - expect(Object.keys(result[0].meta)).to.include.members(['brandId']); - }); - - it('should add advertiserDomains', function() { - let responseAdvertiserId = deepClone(response); - responseAdvertiserId.tags[0].ads[0].adomain = ['123']; - - let bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code' - }] - } - let result = spec.interpretResponse({ body: responseAdvertiserId }, {bidderRequest}); - expect(Object.keys(result[0].meta)).to.include.members(['advertiserDomains']); - expect(Object.keys(result[0].meta.advertiserDomains)).to.deep.equal([]); - }); - }); -}); diff --git a/test/spec/modules/mediakeysBidAdapter_spec.js b/test/spec/modules/mediakeysBidAdapter_spec.js index 38f2a3f9de3..040c0abd566 100644 --- a/test/spec/modules/mediakeysBidAdapter_spec.js +++ b/test/spec/modules/mediakeysBidAdapter_spec.js @@ -1,11 +1,9 @@ import { expect } from 'chai'; -import {find} from 'src/polyfill.js'; import { spec } from 'modules/mediakeysBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import * as utils from 'src/utils.js'; import { config } from 'src/config.js'; import { BANNER, NATIVE, VIDEO } from '../../../src/mediaTypes.js'; -import { OUTSTREAM } from '../../../src/video.js'; describe('mediakeysBidAdapter', function () { const adapter = newBidder(spec); @@ -41,100 +39,39 @@ describe('mediakeysBidAdapter', function () { } }; - const bidNative = { - bidder: 'mediakeys', - params: {}, - mediaTypes: { - native: { - body: { - required: true - }, - title: { - required: true, - len: 800 - }, - sponsoredBy: { - required: true - }, - body2: { - required: true - }, - image: { - required: true, - sizes: [[300, 250], [300, 600], [100, 150]], - }, - icon: { - required: true, - sizes: [50, 50], - }, - }, - }, - nativeParams: { - body: { - required: true - }, - title: { - required: true, - len: 800 - }, - sponsoredBy: { - required: true - }, - body2: { - required: true - }, - image: { - required: true, - sizes: [[300, 250], [300, 600], [100, 150]], - }, - icon: { - required: true, - sizes: [50, 50], - }, - }, - adUnitCode: 'div-gpt-ad-1460505748561-0', - transactionId: '47789656-9e5c-4250-b7e0-2ce4cbe71a55', - bidId: '299320f4de980d', - bidderRequestId: '1c1b642f803242', - auctionId: '84212956-c377-40e8-b000-9885a06dc692', - src: 'client', - bidRequestsCount: 1, - bidderRequestsCount: 1, - bidderWinsCount: 0, - ortb2Imp: { - ext: { data: { something: 'test' } } - } - }; - - const bidVideo = { - bidder: 'mediakeys', - params: {}, - mediaTypes: { - video: { - context: OUTSTREAM, - playerSize: [480, 320] - } - }, - adUnitCode: 'div-gpt-ad-1460505748561-0', - transactionId: '47789656-9e5c-4250-b7e0-2ce4cbe71a55', - bidId: '299320f4de980d', - bidderRequestId: '1c1b642f803242', - auctionId: '84212956-c377-40e8-b000-9885a06dc692', - src: 'client', - bidRequestsCount: 1, - bidderRequestsCount: 1, - bidderWinsCount: 0, - ortb2Imp: { - ext: { data: { something: 'test' } } - } - }; - const bidderRequest = { bidderCode: 'mediakeys', auctionId: '84212956-c377-40e8-b000-9885a06dc692', bidderRequestId: '1c1b642f803242', bids: [ - bid + { + bidder: 'mediakeys', + params: {}, + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600], + ], + }, + }, + adUnitCode: 'div-gpt-ad-1460505748561-0', + transactionId: '47789656-9e5c-4250-b7e0-2ce4cbe71a55', + sizes: [ + [300, 250], + [300, 600], + ], + bidId: '299320f4de980d', + bidderRequestId: '1c1b642f803242', + auctionId: '84212956-c377-40e8-b000-9885a06dc692', + src: 'client', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + ortb2Imp: { + ext: { data: { something: 'test' } } + } + }, ], auctionStart: 1620973766319, timeout: 1000, @@ -179,25 +116,23 @@ describe('mediakeysBidAdapter', function () { it('should create imp for supported mediaType only', function() { const bidRequests = [utils.deepClone(bid)]; const bidderRequestCopy = utils.deepClone(bidderRequest); - bidderRequestCopy.bids = bidRequests; bidRequests[0].mediaTypes.video = { playerSize: [300, 250], - context: OUTSTREAM + context: 'outstream' } - bidRequests[0].mediaTypes.native = bidNative.mediaTypes.native; - bidRequests[0].nativeParams = bidNative.mediaTypes.native; - - bidderRequestCopy.bids = bidRequests[0]; + bidRequests[0].mediaTypes.native = { + type: 'image' + } const request = spec.buildRequests(bidRequests, bidderRequestCopy); const data = request.data; expect(data.imp.length).to.equal(1); expect(data.imp[0].banner).to.exist; - expect(data.imp[0].video).to.exist; - expect(data.imp[0].native).to.exist; + expect(data.imp[0].video).to.not.exist; + expect(data.imp[0].native).to.not.exist; }); it('should get expected properties with default values (no params set)', function () { @@ -226,205 +161,6 @@ describe('mediakeysBidAdapter', function () { expect(data.imp[0].ext.data.something).to.equal('test'); }); - describe('native imp', function() { - it('should get a native object in request', function() { - const bidRequests = [utils.deepClone(bidNative)]; - const bidderRequestCopy = utils.deepClone(bidderRequest); - bidderRequestCopy.bids = bidRequests; - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = request.data; - - expect(data.imp.length).to.equal(1); - expect(data.imp[0].id).to.equal(bidRequests[0].bidId); - expect(data.imp[0].native).to.exist; - expect(data.imp[0].native.request.ver).to.equal('1.2'); - expect(data.imp[0].native.request.context).to.equal(1); - expect(data.imp[0].native.request.plcmttype).to.equal(1); - expect(data.imp[0].native.request.assets.length).to.equal(6); - // find the asset body - const bodyAsset = find(data.imp[0].native.request.assets, asset => asset.id === 6); - expect(bodyAsset.data.type).to.equal(2); - }); - - it('should get a native object in request with properties filled with params values', function() { - const bidRequests = [utils.deepClone(bidNative)]; - bidRequests[0].params = { - native: { - context: 3, - plcmttype: 3, - } - } - const bidderRequestCopy = utils.deepClone(bidderRequest); - bidderRequestCopy.bids = bidRequests; - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = request.data; - - expect(data.imp.length).to.equal(1); - expect(data.imp[0].id).to.equal(bidRequests[0].bidId); - expect(data.imp[0].native).to.exist; - expect(data.imp[0].native.request.ver).to.equal('1.2'); - expect(data.imp[0].native.request.context).to.equal(3); - expect(data.imp[0].native.request.plcmttype).to.equal(3); - expect(data.imp[0].native.request.assets.length).to.equal(6); - }); - - it('should get a native object in request when native type ,image" has been set', function() { - const bidRequests = [utils.deepClone(bidNative)]; - bidRequests[0].mediaTypes.native = { type: 'image' }; - bidRequests[0].nativeParams = { - image: { required: true }, - title: { required: true }, - sponsoredBy: { required: true }, - clickUrl: { required: true }, // [1] Will be ignored as it is used in response validation only - body: { required: false }, - icon: { required: false }, - }; - - const bidderRequestCopy = utils.deepClone(bidderRequest); - bidderRequestCopy.bids = bidRequests; - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = request.data; - - expect(data.imp.length).to.equal(1); - expect(data.imp[0].id).to.equal(bidRequests[0].bidId); - expect(data.imp[0].native).to.exist; - expect(data.imp[0].native.request.ver).to.equal('1.2'); - expect(data.imp[0].native.request.context).to.equal(1); - expect(data.imp[0].native.request.plcmttype).to.equal(1); - expect(data.imp[0].native.request.assets.length).to.equal(5); // [1] clickUrl ignored - }); - - it('should log errors and ignore misformated assets', function() { - const bidRequests = [utils.deepClone(bidNative)]; - delete bidRequests[0].nativeParams.title.len; - bidRequests[0].nativeParams.unregistred = {required: true}; - - const bidderRequestCopy = utils.deepClone(bidderRequest); - bidderRequestCopy.bids = bidRequests; - - utilsMock.expects('logWarn').twice(); - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = request.data; - - expect(data.imp.length).to.equal(1); - expect(data.imp[0].id).to.equal(bidRequests[0].bidId); - expect(data.imp[0].native).to.exist; - expect(data.imp[0].native.request.assets.length).to.equal(5); - }); - }); - - describe('video imp', function() { - it('should get a video object in request', function() { - const bidRequests = [utils.deepClone(bidVideo)]; - const bidderRequestCopy = utils.deepClone(bidderRequest); - bidderRequestCopy.bids = bidRequests; - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = request.data; - - expect(data.imp.length).to.equal(1); - expect(data.imp[0].id).to.equal(bidRequests[0].bidId); - expect(data.imp[0].banner).to.not.exist; - expect(data.imp[0].video).to.exist; - expect(data.imp[0].video.w).to.equal(480); - expect(data.imp[0].video.h).to.equal(320); - }); - - it('should ignore and warn misformated ORTB video properties', function() { - const bidRequests = [utils.deepClone(bidVideo)]; - bidRequests[0].mediaTypes.video.unknown = 'foo'; - bidRequests[0].mediaTypes.video.placement = 10; - bidRequests[0].mediaTypes.video.skipmin = 5; - const bidderRequestCopy = utils.deepClone(bidderRequest); - bidderRequestCopy.bids = bidRequests; - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = request.data; - - expect(data.imp.length).to.equal(1); - expect(data.imp[0].id).to.equal(bidRequests[0].bidId); - expect(data.imp[0].banner).to.not.exist; - expect(data.imp[0].video).to.exist; - expect(data.imp[0].video.w).to.equal(480); - expect(data.imp[0].video.h).to.equal(320); - expect(data.imp[0].video.skipmin).to.equal(5); - expect(data.imp[0].video.placement).to.not.exist; - expect(data.imp[0].video.unknown).to.not.exist; - }); - - it('should merge adUnit mediaTypes level and bidder level params properties ', function() { - const bidRequests = [utils.deepClone(bidVideo)]; - bidRequests[0].mediaTypes.video.placement = 1; - bidRequests[0].mediaTypes.video.mimes = ['video/mpeg4']; - bidRequests[0].mediaTypes.video.protocols = [1]; - bidRequests[0].mediaTypes.video.minduration = 10; - bidRequests[0].mediaTypes.video.maxduration = 45; - bidRequests[0].mediaTypes.video.skipmin = 5; - bidRequests[0].mediaTypes.video.sequence = 3; - bidRequests[0].mediaTypes.video.linearity = 1; - bidRequests[0].mediaTypes.video.battr = [12]; - bidRequests[0].mediaTypes.video.maxextended = 10; - bidRequests[0].mediaTypes.video.minbitrate = 720; - bidRequests[0].mediaTypes.video.maxbitrate = 720; - bidRequests[0].mediaTypes.video.boxingallowed = 1; - bidRequests[0].mediaTypes.video.playbackmethod = [1]; - bidRequests[0].mediaTypes.video.playbackend = 2; - bidRequests[0].mediaTypes.video.delivery = 2; - bidRequests[0].mediaTypes.video.pos = 0; - bidRequests[0].mediaTypes.video.companionad = [{ w: 360, h: 80 }] - bidRequests[0].mediaTypes.video.api = [1]; - bidRequests[0].mediaTypes.video.companiontype = [1]; - - // bidder level - bidRequests[0].params.video = { - pos: 2, // override - skip: 1, - skipafter: 10, - startdelay: 3 - }; - - const bidderRequestCopy = utils.deepClone(bidderRequest); - bidderRequestCopy.bids = bidRequests; - - utilsMock.expects('logWarn').never(); - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = request.data; - - expect(data.imp.length).to.equal(1); - expect(data.imp[0].id).to.equal(bidRequests[0].bidId); - expect(data.imp[0].banner).to.not.exist; - expect(data.imp[0].video).to.exist; - - expect(Object.keys(data.imp[0].video).length).to.equal(23); // 21 ortb params (2 skipped) + computed width/height. - expect(data.imp[0].video.w).to.equal(480); - expect(data.imp[0].video.h).to.equal(320); - expect(data.imp[0].video.mimes[0]).to.equal('video/mpeg4'); - expect(data.imp[0].video.pos).to.equal(2); - expect(data.imp[0].video.skip).to.equal(1); - expect(data.imp[0].video.skipafter).to.equal(10); - expect(data.imp[0].video.startdelay).to.equal(3); - expect(data.imp[0].video.companionad).to.not.exist; - expect(data.imp[0].video.companiontype).to.not.exist; - }); - - it('should log warn message when OpenRTB validation fails ', function() { - const bidRequests = [utils.deepClone(bidVideo)]; - bidRequests[0].mediaTypes.video.placement = 'string'; - bidRequests[0].mediaTypes.video.api = 1; - const bidderRequestCopy = utils.deepClone(bidderRequest); - bidderRequestCopy.bids = bidRequests; - - utilsMock.expects('logWarn').twice(); - - spec.buildRequests(bidRequests, bidderRequestCopy); - }); - }); - it('should get expected properties with values from params', function () { const bidRequests = [utils.deepClone(bid)]; bidRequests[0].params = { @@ -529,25 +265,13 @@ describe('mediakeysBidAdapter', function () { expect(data.imp[0].bidfloor).to.not.exist; }); - it('should get the highest floorPrice found when bid have several mediaTypes', function() { + it('should get and set floor by mediatype', function() { const bidWithPriceFloors = utils.deepClone(bid); bidWithPriceFloors.mediaTypes.video = { playerSize: [600, 480] }; - bidWithPriceFloors.mediaTypes.native = { - body: { - required: true - } - }; - - bidWithPriceFloors.nativeParams = { - body: { - required: true - } - }; - bidWithPriceFloors.getFloor = getFloorTest; const bidRequests = [bidWithPriceFloors]; @@ -555,9 +279,10 @@ describe('mediakeysBidAdapter', function () { const data = request.data; expect(data.imp[0].banner).to.exist; - expect(data.imp[0].video).to.exist; - expect(data.imp[0].native).to.exist; - expect(data.imp[0].bidfloor).to.equal(5); + expect(data.imp[0].bidfloor).to.equal(1); + + // expect(data.imp[1].video).to.exist; + // expect(data.imp[1].bidfloor).to.equal(5); }); it('should set properties at payload level from FPD', function() { @@ -575,15 +300,12 @@ describe('mediakeysBidAdapter', function () { }, user: { yob: 1985, - gender: 'm', + gender: 'm' + }, + device: { geo: { country: 'FR', city: 'Marseille' - }, - ext: { - data: { - registered: true - } } } } @@ -599,9 +321,8 @@ describe('mediakeysBidAdapter', function () { expect(data.site.ext.data.category).to.equal('sport'); expect(data.user.yob).to.equal(1985); expect(data.user.gender).to.equal('m'); - expect(data.user.geo.country).to.equal('FR'); - expect(data.user.geo.city).to.equal('Marseille'); - expect(data.user.ext.data.registered).to.be.true; + expect(data.device.geo.country).to.equal('FR'); + expect(data.device.geo.city).to.equal('Marseille'); }); }); @@ -699,8 +420,8 @@ describe('mediakeysBidAdapter', function () { const bidRequests = [utils.deepClone(bid)]; const request = spec.buildRequests(bidRequests, bidderRequest); sinon.stub(utils, 'isArray').throws(); - utilsMock.expects('logError').once(); spec.interpretResponse(rawServerResponse, request); + utilsMock.expects('logError').once(); utils.isArray.restore(); }); @@ -762,108 +483,28 @@ describe('mediakeysBidAdapter', function () { }); }); - it('interprets video bid response', function () { - const vastUrl = 'https://url.local?req=content'; - const bidRequests = [utils.deepClone(bidVideo)]; + it('Build video response', function () { + const bidRequests = [utils.deepClone(bid)]; const request = spec.buildRequests(bidRequests, bidderRequest); - const rawServerResponseVideo = utils.deepClone(rawServerResponse); rawServerResponseVideo.body.seatbid[0].bid[0].ext.prebid.type = 'V'; - rawServerResponseVideo.body.seatbid[0].bid[0].ext.vast_url = vastUrl; - const response = spec.interpretResponse(rawServerResponseVideo, request); expect(response.length).to.equal(1); expect(response[0].mediaType).to.equal('video'); expect(response[0].meta.mediaType).to.equal('video'); - expect(response[0].vastXml).to.not.exist; - expect(response[0].vastUrl).to.equal(vastUrl + '&no_cache'); - expect(response[0].videoCacheKey).to.equal('no_cache'); }); - describe('Native response', function () { - let bidRequests; - let bidderRequestCopy; - let request; - let rawServerResponseNative; - let nativeObject; - - beforeEach(function() { - bidRequests = [utils.deepClone(bidNative)]; - bidderRequestCopy = utils.deepClone(bidderRequest); - bidderRequestCopy.bids = bidRequests; - - request = spec.buildRequests(bidRequests, bidderRequestCopy); - - nativeObject = { - ver: '1.2', - privacy: 'https://privacy.me', - assets: [ - { id: 5, data: { type: 1, value: 'Sponsor Brand' } }, - { id: 6, data: { type: 2, value: 'Brand Body' } }, - { id: 14, data: { type: 10, value: 'Brand Body 2' } }, - { id: 1, title: { text: 'Brand Title' } }, - { id: 2, img: { type: 3, url: 'https://url.com/img.jpg', w: 300, h: 250 } }, - { id: 3, img: { type: 1, url: 'https://url.com/ico.png', w: 50, h: 50 } }, - ], - link: { - url: 'https://brand.me', - clicktrackers: [ - 'https://click.me' - ] - }, - eventtrackers: [ - { event: 1, method: 1, url: 'https://click.me' }, - { event: 1, method: 2, url: 'https://click-script.me' } - ] - }; - - rawServerResponseNative = utils.deepClone(rawServerResponse); - rawServerResponseNative.body.seatbid[0].bid[0].ext.prebid.type = 'N'; - rawServerResponseNative.body.seatbid[0].bid[0].adm = JSON.stringify(nativeObject) - }); - - it('should ignore invalid native response', function() { - const nativeObjectCopy = utils.deepClone(nativeObject); - nativeObjectCopy.assets = []; - const rawServerResponseNativeCopy = utils.deepClone(rawServerResponseNative); - rawServerResponseNativeCopy.body.seatbid[0].bid[0].adm = JSON.stringify(nativeObjectCopy) - const response = spec.interpretResponse(rawServerResponseNativeCopy, request); - expect(response.length).to.equal(1); - expect(response[0].native).to.not.exist; - }); - - it('should build a classic Prebid.js native object for response', function() { - const rawServerResponseNativeCopy = utils.deepClone(rawServerResponseNative); - const response = spec.interpretResponse(rawServerResponseNativeCopy, request); - expect(response.length).to.equal(1); - expect(response[0].mediaType).to.equal('native'); - expect(response[0].meta.mediaType).to.equal('native'); - expect(response[0].native).to.exist; - expect(response[0].native.body).to.exist; - expect(response[0].native.privacyLink).to.exist; - expect(response[0].native.body2).to.exist; - expect(response[0].native.sponsoredBy).to.exist; - expect(response[0].native.image).to.exist; - expect(response[0].native.icon).to.exist; - expect(response[0].native.title).to.exist; - expect(response[0].native.clickUrl).to.exist; - expect(response[0].native.clickTrackers).to.exist; - expect(response[0].native.clickTrackers.length).to.equal(1); - expect(response[0].native.javascriptTrackers).to.equal(''); - expect(response[0].native.impressionTrackers).to.exist; - expect(response[0].native.impressionTrackers.length).to.equal(1); - }); + it('Build native response', function () { + const bidRequests = [utils.deepClone(bid)]; + const request = spec.buildRequests(bidRequests, bidderRequest); + const rawServerResponseVideo = utils.deepClone(rawServerResponse); + rawServerResponseVideo.body.seatbid[0].bid[0].ext.prebid.type = 'N'; + const response = spec.interpretResponse(rawServerResponseVideo, request); - it('should ignore eventtrackers with a unsupported type', function() { - const rawServerResponseNativeCopy = utils.deepClone(rawServerResponseNative); - const nativeObjectCopy = utils.deepClone(nativeObject); - nativeObjectCopy.eventtrackers[0].event = 2; - rawServerResponseNativeCopy.body.seatbid[0].bid[0].adm = JSON.stringify(nativeObjectCopy); - const response = spec.interpretResponse(rawServerResponseNativeCopy, request); - expect(response[0].native.impressionTrackers).to.exist; - expect(response[0].native.impressionTrackers.length).to.equal(0); - }) + expect(response.length).to.equal(1); + expect(response[0].mediaType).to.equal('native'); + expect(response[0].meta.mediaType).to.equal('native'); }); }); diff --git a/test/spec/modules/medianetAnalyticsAdapter_spec.js b/test/spec/modules/medianetAnalyticsAdapter_spec.js index 0ce26ab4863..41a6338225e 100644 --- a/test/spec/modules/medianetAnalyticsAdapter_spec.js +++ b/test/spec/modules/medianetAnalyticsAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import medianetAnalytics from 'modules/medianetAnalyticsAdapter.js'; import * as utils from 'src/utils.js'; import CONSTANTS from 'src/constants.json'; -import * as events from 'src/events.js'; +import events from 'src/events.js'; const { EVENTS: { AUCTION_INIT, BID_REQUESTED, BID_RESPONSE, NO_BID, BID_TIMEOUT, AUCTION_END, SET_TARGETING, BID_WON } @@ -11,25 +11,21 @@ const { const MOCK = { Ad_Units: [{'code': 'div-gpt-ad-1460505748561-0', 'mediaTypes': {'banner': {'sizes': [[300, 250]]}}, 'bids': [], 'ext': {'prop1': 'value1'}}], MULTI_FORMAT_TWIN_AD_UNITS: [{'code': 'div-gpt-ad-1460505748561-0', 'mediaTypes': {'banner': {'sizes': [[300, 250]]}, 'native': {'image': {'required': true, 'sizes': [150, 50]}}}, 'bids': [], 'ext': {'prop1': 'value1'}}, {'code': 'div-gpt-ad-1460505748561-0', 'mediaTypes': {'video': {'playerSize': [640, 480], 'context': 'instream'}}, 'bids': [], 'ext': {'prop1': 'value1'}}], - TWIN_AD_UNITS: [{'code': 'div-gpt-ad-1460505748561-0', 'mediaTypes': {'banner': {'sizes': [[300, 100]]}}, 'ask': '300x100', 'bids': [{'bidder': 'bidder1', 'params': {'siteId': '451465'}}]}, {'code': 'div-gpt-ad-1460505748561-0', 'mediaTypes': {'banner': {'sizes': [[300, 250], [300, 100]]}}, 'bids': [{'bidder': 'medianet', 'params': {'cid': 'TEST_CID', 'crid': '451466393'}}]}, {'code': 'div-gpt-ad-1460505748561-0', 'mediaTypes': {'banner': {'sizes': [[300, 250]]}}, 'bids': [{'bidder': 'bidder1', 'params': {'siteId': '451466'}}]}], AUCTION_INIT: {'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'timestamp': 1584563605739, 'timeout': 6000}, AUCTION_INIT_WITH_FLOOR: {'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'timestamp': 1584563605739, 'timeout': 6000, 'bidderRequests': [{'bids': [{ 'floorData': {'enforcements': {'enforceJS': true}} }]}]}, BID_REQUESTED: {'bidderCode': 'medianet', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'bids': [{'bidder': 'medianet', 'params': {'cid': 'TEST_CID', 'crid': '451466393'}, 'mediaTypes': {'banner': {'sizes': [[300, 250]], 'ext': ['asdads']}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'sizes': [[300, 250]], 'bidId': '28248b0e6aece2', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'src': 'client'}], 'auctionStart': 1584563605739, 'timeout': 6000, 'uspConsent': '1YY', 'start': 1584563605743}, MULTI_FORMAT_BID_REQUESTED: {'bidderCode': 'medianet', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'bids': [{'bidder': 'medianet', 'params': {'cid': 'TEST_CID', 'crid': '451466393'}, 'mediaTypes': {'banner': {'sizes': [[300, 250]]}, 'video': {'playerSize': [640, 480], 'context': 'instream'}, 'native': {'image': {'required': true, 'sizes': [150, 50]}, 'title': {'required': true, 'len': 80}}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'sizes': [[300, 250]], 'bidId': '28248b0e6aece2', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'src': 'client'}], 'auctionStart': 1584563605739, 'timeout': 6000, 'uspConsent': '1YY', 'start': 1584563605743}, - TWIN_AD_UNITS_BID_REQUESTED: [{'bidderCode': 'bidder1', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'bidderRequestId': '16f0746ff657b5', 'bids': [{'bidder': 'bidder1', 'params': {'siteId': '451465'}, 'mediaTypes': {'banner': {'sizes': [[300, 100]]}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '9615b5d1-7a4f-4c65-9464-4178b91da9e3', 'sizes': [[300, 100]], 'bidId': '2984d18e18bdfe', 'bidderRequestId': '16f0746ff657b5', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'src': 'client', 'bidRequestsCount': 3, 'bidderRequestsCount': 2, 'bidderWinsCount': 0}, {'bidder': 'bidder1', 'params': {'siteId': '451466'}, 'mediaTypes': {'banner': {'sizes': [[300, 250]]}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '8bd7c9f2-0fe6-4ac5-8f2a-7f4a88af1b71', 'sizes': [[300, 250]], 'bidId': '3dced609066035', 'bidderRequestId': '16f0746ff657b5', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'src': 'client', 'bidRequestsCount': 3, 'bidderRequestsCount': 2, 'bidderWinsCount': 0}], 'auctionStart': 1584563605739, 'timeout': 3000, 'start': 1584563605743}, {'bidderCode': 'medianet', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'bidderRequestId': '4b45d1de1fa8fe', 'bids': [{'bidder': 'medianet', 'params': {'cid': 'TEST_CID', 'crid': '451466393'}, 'mediaTypes': {'banner': {'sizes': [[300, 250], [300, 100]]}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '215c038e-3b6a-465b-8937-d32e2ad8de45', 'sizes': [[300, 250], [300, 100]], 'bidId': '58d34adcb09c99', 'bidderRequestId': '4b45d1de1fa8fe', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'src': 'client', 'bidRequestsCount': 3, 'bidderRequestsCount': 1, 'bidderWinsCount': 0}], 'auctionStart': 1584563605739, 'timeout': 3000, 'start': 1584563605743}], BID_RESPONSE: {'bidderCode': 'medianet', 'width': 300, 'height': 250, 'adId': '3e6e4bce5c8fb3', 'requestId': '28248b0e6aece2', 'mediaType': 'banner', 'source': 'client', 'ext': {'pvid': 123, 'crid': '321'}, 'no_bid': false, 'cpm': 2.299, 'ad': 'AD_CODE', 'ttl': 180, 'creativeId': 'Test1', 'netRevenue': true, 'currency': 'USD', 'dfp_id': 'div-gpt-ad-1460505748561-0', 'originalCpm': 1.1495, 'originalCurrency': 'USD', 'floorData': {'floorValue': 1.10, 'floorRule': 'banner'}, 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'responseTimestamp': 1584563606009, 'requestTimestamp': 1584563605743, 'bidder': 'medianet', 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'timeToRespond': 266, 'pbLg': '2.00', 'pbMg': '2.20', 'pbHg': '2.29', 'pbAg': '2.25', 'pbDg': '2.29', 'pbCg': '2.00', 'size': '300x250', 'adserverTargeting': {'hb_bidder': 'medianet', 'hb_adid': '3e6e4bce5c8fb3', 'hb_pb': '2.00', 'hb_size': '300x250', 'hb_source': 'client', 'hb_format': 'banner', 'prebid_test': 1}, 'status': 'rendered', 'params': [{'cid': 'test123', 'crid': '451466393'}]}, AUCTION_END: {'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'auctionEnd': 1584563605739}, SET_TARGETING: {'div-gpt-ad-1460505748561-0': {'prebid_test': '1', 'hb_format': 'banner', 'hb_source': 'client', 'hb_size': '300x250', 'hb_pb': '2.00', 'hb_adid': '3e6e4bce5c8fb3', 'hb_bidder': 'medianet', 'hb_format_medianet': 'banner', 'hb_source_medianet': 'client', 'hb_size_medianet': '300x250', 'hb_pb_medianet': '2.00', 'hb_adid_medianet': '3e6e4bce5c8fb3', 'hb_bidder_medianet': 'medianet'}}, NO_BID_SET_TARGETING: {'div-gpt-ad-1460505748561-0': {}}, BID_WON: {'bidderCode': 'medianet', 'width': 300, 'height': 250, 'statusMessage': 'Bid available', 'adId': '3e6e4bce5c8fb3', 'requestId': '28248b0e6aece2', 'mediaType': 'banner', 'source': 'client', 'no_bid': false, 'cpm': 2.299, 'ad': 'AD_CODE', 'ttl': 180, 'creativeId': 'Test1', 'netRevenue': true, 'currency': 'USD', 'dfp_id': 'div-gpt-ad-1460505748561-0', 'originalCpm': 1.1495, 'originalCurrency': 'USD', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'responseTimestamp': 1584563606009, 'requestTimestamp': 1584563605743, 'bidder': 'medianet', 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'timeToRespond': 266, 'pbLg': '2.00', 'pbMg': '2.20', 'pbHg': '2.29', 'pbAg': '2.25', 'pbDg': '2.29', 'pbCg': '2.00', 'size': '300x250', 'adserverTargeting': {'hb_bidder': 'medianet', 'hb_adid': '3e6e4bce5c8fb3', 'hb_pb': '2.00', 'hb_size': '300x250', 'hb_source': 'client', 'hb_format': 'banner', 'prebid_test': 1}, 'status': 'rendered', 'params': [{'cid': 'test123', 'crid': '451466393'}]}, NO_BID: {'bidder': 'medianet', 'params': {'cid': 'test123', 'crid': '451466393', 'site': {}}, 'mediaTypes': {'banner': {'sizes': [[300, 250]], 'ext': ['asdads']}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '303fa0c6-682f-4aea-8e4a-dc68f0d5c7d5', 'sizes': [[300, 250], [300, 600]], 'bidId': '28248b0e6aece2', 'bidderRequestId': '13fccf3809fe43', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'src': 'client'}, - BID_TIMEOUT: [{'bidId': '28248b0e6aece2', 'bidder': 'medianet', 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'params': [{'cid': 'test123', 'crid': '451466393', 'site': {}}, {'cid': '8CUX0H51P', 'crid': '451466393', 'site': {}}], 'timeout': 6}], - BIDS_SAME_REQ_DIFF_CPM: [{'bidderCode': 'medianet', 'width': 300, 'height': 250, 'adId': '3e6e4bce5c8fgg', 'requestId': '28248b0e6aece2', 'mediaType': 'banner', 'source': 'client', 'ext': {'pvid': 123, 'crid': '321'}, 'no_bid': false, 'cpm': 2.299, 'ad': 'AD_CODE', 'ttl': 180, 'creativeId': 'Test1', 'netRevenue': true, 'currency': 'USD', 'dfp_id': 'div-gpt-ad-1460505748561-0', 'originalCpm': 1.1495, 'originalCurrency': 'USD', 'floorData': {'floorValue': 1.10, 'floorRule': 'banner'}, 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'responseTimestamp': 1584563606009, 'requestTimestamp': 1584563605743, 'bidder': 'medianet', 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'timeToRespond': 266, 'pbLg': '2.00', 'pbMg': '2.20', 'pbHg': '2.29', 'pbAg': '2.25', 'pbDg': '2.29', 'pbCg': '2.00', 'size': '300x250', 'adserverTargeting': {'hb_bidder': 'medianet', 'hb_adid': '3e6e4bce5c8fb3', 'hb_pb': '2.00', 'hb_size': '300x250', 'hb_source': 'client', 'hb_format': 'banner', 'prebid_test': 1}, 'status': 'rendered', 'params': [{'cid': 'test123', 'crid': '451466393'}]}, {'bidderCode': 'medianet', 'width': 300, 'height': 250, 'adId': '3e6e4bce5c8fb4', 'requestId': '28248b0e6aece2', 'mediaType': 'banner', 'source': 'client', 'ext': {'pvid': 123, 'crid': '321'}, 'no_bid': false, 'cpm': 1.299, 'ad': 'AD_CODE', 'ttl': 180, 'creativeId': 'Test1', 'netRevenue': true, 'currency': 'USD', 'dfp_id': 'div-gpt-ad-1460505748561-0', 'originalCpm': 1.1495, 'originalCurrency': 'USD', 'floorData': {'floorValue': 1.10, 'floorRule': 'banner'}, 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'responseTimestamp': 1584563606009, 'requestTimestamp': 1584563605743, 'bidder': 'medianet', 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'timeToRespond': 278, 'pbLg': '1.00', 'pbMg': '1.20', 'pbHg': '1.29', 'pbAg': '1.25', 'pbDg': '1.29', 'pbCg': '1.00', 'size': '300x250', 'adserverTargeting': {'hb_bidder': 'medianet', 'hb_adid': '3e6e4bce5c8fb3', 'hb_pb': '1.00', 'hb_size': '300x250', 'hb_source': 'client', 'hb_format': 'banner', 'prebid_test': 1}, 'status': 'rendered', 'params': [{'cid': 'test123', 'crid': '451466393'}]}], - BIDS_SAME_REQ_EQUAL_CPM: [{'bidderCode': 'medianet', 'width': 300, 'height': 250, 'adId': '3e6e4bce5c8fgg', 'requestId': '28248b0e6aece2', 'mediaType': 'banner', 'source': 'client', 'ext': {'pvid': 123, 'crid': '321'}, 'no_bid': false, 'cpm': 2.299, 'ad': 'AD_CODE', 'ttl': 180, 'creativeId': 'Test1', 'netRevenue': true, 'currency': 'USD', 'dfp_id': 'div-gpt-ad-1460505748561-0', 'originalCpm': 1.1495, 'originalCurrency': 'USD', 'floorData': {'floorValue': 1.1, 'floorRule': 'banner'}, 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'responseTimestamp': 1584563606009, 'requestTimestamp': 1584563605743, 'bidder': 'medianet', 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'timeToRespond': 266, 'pbLg': '2.00', 'pbMg': '2.20', 'pbHg': '2.29', 'pbAg': '2.25', 'pbDg': '2.29', 'pbCg': '2.00', 'size': '300x250', 'adserverTargeting': {'hb_bidder': 'medianet', 'hb_adid': '3e6e4bce5c8fb3', 'hb_pb': '2.00', 'hb_size': '300x250', 'hb_source': 'client', 'hb_format': 'banner', 'prebid_test': 1}, 'status': 'rendered', 'params': [{'cid': 'test123', 'crid': '451466393'}]}, {'bidderCode': 'medianet', 'width': 300, 'height': 250, 'adId': '3e6e4bce5c8fb4', 'requestId': '28248b0e6aece2', 'mediaType': 'banner', 'source': 'client', 'ext': {'pvid': 123, 'crid': '321'}, 'no_bid': false, 'cpm': 2.299, 'ad': 'AD_CODE', 'ttl': 180, 'creativeId': 'Test1', 'netRevenue': true, 'currency': 'USD', 'dfp_id': 'div-gpt-ad-1460505748561-0', 'originalCpm': 1.1495, 'originalCurrency': 'USD', 'floorData': {'floorValue': 1.1, 'floorRule': 'banner'}, 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'responseTimestamp': 1584563606009, 'requestTimestamp': 1584563605743, 'bidder': 'medianet', 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'timeToRespond': 286, 'pbLg': '2.00', 'pbMg': '2.20', 'pbHg': '2.29', 'pbAg': '2.25', 'pbDg': '2.29', 'pbCg': '2.00', 'size': '300x250', 'adserverTargeting': {'hb_bidder': 'medianet', 'hb_adid': '3e6e4bce5c8fb3', 'hb_pb': '2.00', 'hb_size': '300x250', 'hb_source': 'client', 'hb_format': 'banner', 'prebid_test': 1}, 'status': 'rendered', 'params': [{'cid': 'test123', 'crid': '451466393'}]}] + BID_TIMEOUT: [{'bidId': '28248b0e6aece2', 'bidder': 'medianet', 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'auctionId': '8e0d5245-deb3-406c-96ca-9b609e077ff7', 'params': [{'cid': 'test123', 'crid': '451466393', 'site': {}}, {'cid': '8CUX0H51P', 'crid': '451466393', 'site': {}}], 'timeout': 6}] } function performAuctionWithFloorConfig() { - events.emit(AUCTION_INIT, Object.assign({}, MOCK.AUCTION_INIT_WITH_FLOOR, {adUnits: MOCK.Ad_Units})); + events.emit(AUCTION_INIT, {...MOCK.AUCTION_INIT_WITH_FLOOR, adUnits: MOCK.Ad_Units}); events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); events.emit(BID_RESPONSE, MOCK.BID_RESPONSE); events.emit(AUCTION_END, MOCK.AUCTION_END); @@ -38,7 +34,7 @@ function performAuctionWithFloorConfig() { } function performStandardAuctionWithWinner() { - events.emit(AUCTION_INIT, Object.assign({}, MOCK.AUCTION_INIT, {adUnits: MOCK.Ad_Units})); + events.emit(AUCTION_INIT, {...MOCK.AUCTION_INIT, adUnits: MOCK.Ad_Units}); events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); events.emit(BID_RESPONSE, MOCK.BID_RESPONSE); events.emit(AUCTION_END, MOCK.AUCTION_END); @@ -47,23 +43,15 @@ function performStandardAuctionWithWinner() { } function performMultiFormatAuctionWithNoBid() { - events.emit(AUCTION_INIT, Object.assign({}, MOCK.AUCTION_INIT, {adUnits: MOCK.MULTI_FORMAT_TWIN_AD_UNITS})); + events.emit(AUCTION_INIT, {...MOCK.AUCTION_INIT, adUnits: MOCK.MULTI_FORMAT_TWIN_AD_UNITS}); events.emit(BID_REQUESTED, MOCK.MULTI_FORMAT_BID_REQUESTED); events.emit(NO_BID, MOCK.NO_BID); events.emit(AUCTION_END, MOCK.AUCTION_END); events.emit(SET_TARGETING, MOCK.NO_BID_SET_TARGETING); } -function performTwinAdUnitAuctionWithNoBid() { - events.emit(AUCTION_INIT, Object.assign({}, MOCK.AUCTION_INIT, {adUnits: MOCK.TWIN_AD_UNITS})); - MOCK.TWIN_AD_UNITS_BID_REQUESTED.forEach(bidRequested => events.emit(BID_REQUESTED, bidRequested)); - MOCK.TWIN_AD_UNITS_BID_REQUESTED.forEach(bidRequested => bidRequested.bids.forEach(noBid => events.emit(NO_BID, noBid))); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.NO_BID_SET_TARGETING); -} - function performStandardAuctionWithNoBid() { - events.emit(AUCTION_INIT, Object.assign({}, MOCK.AUCTION_INIT, {adUnits: MOCK.Ad_Units})); + events.emit(AUCTION_INIT, {...MOCK.AUCTION_INIT, adUnits: MOCK.Ad_Units}); events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); events.emit(NO_BID, MOCK.NO_BID); events.emit(AUCTION_END, MOCK.AUCTION_END); @@ -71,29 +59,17 @@ function performStandardAuctionWithNoBid() { } function performStandardAuctionWithTimeout() { - events.emit(AUCTION_INIT, Object.assign({}, MOCK.AUCTION_INIT, {adUnits: MOCK.Ad_Units})); + events.emit(AUCTION_INIT, {...MOCK.AUCTION_INIT, adUnits: MOCK.Ad_Units}); events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); events.emit(BID_TIMEOUT, MOCK.BID_TIMEOUT); events.emit(AUCTION_END, MOCK.AUCTION_END); events.emit(SET_TARGETING, MOCK.NO_BID_SET_TARGETING); } -function performStandardAuctionMultiBidWithSameRequestId(bidRespArray) { - events.emit(AUCTION_INIT, Object.assign({}, MOCK.AUCTION_INIT, {adUnits: MOCK.Ad_Units})); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - bidRespArray.forEach(bidResp => events.emit(BID_RESPONSE, bidResp)); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON); -} - -function getQueryData(url, decode = false) { +function getQueryData(url) { const queryArgs = url.split('?')[1].split('&'); return queryArgs.reduce((data, arg) => { - let [key, val] = arg.split('='); - if (decode) { - val = decodeURIComponent(val); - } + const [key, val] = arg.split('='); if (data[key] !== undefined) { if (!Array.isArray(data[key])) { data[key] = [data[key]]; @@ -173,25 +149,6 @@ describe('Media.net Analytics Adapter', function() { expect(noBidLog.vplcmtt).to.equal('instream'); }); - it('twin ad units should have correct sizes', function() { - performTwinAdUnitAuctionWithNoBid(); - const noBidLog = medianetAnalytics.getlogsQueue().map((log) => getQueryData(log, true))[0]; - const banner = 'banner'; - expect(noBidLog.pvnm).to.have.ordered.members(['-2', 'bidder1', 'bidder1', 'medianet']); - expect(noBidLog.mtype).to.have.ordered.members([banner, banner, banner, banner]); - expect(noBidLog.status).to.have.ordered.members(['1', '2', '2', '2']); - expect(noBidLog.size).to.have.ordered.members(['', '', '', '']); - expect(noBidLog.szs).to.have.ordered.members(['300x100|300x250', '300x100', '300x250', '300x250|300x100']); - }); - - it('AP log should fire only once', function() { - performStandardAuctionWithNoBid(); - events.emit(SET_TARGETING, MOCK.NO_BID_SET_TARGETING); - const logs = medianetAnalytics.getlogsQueue().map((log) => getQueryData(log, true)); - expect(logs.length).to.equal(1); - expect(logs[0].lgtp).to.equal('APPR'); - }); - it('should have winner log in standard auction', function() { medianetAnalytics.clearlogsQueue(); performStandardAuctionWithWinner(); @@ -276,29 +233,5 @@ describe('Media.net Analytics Adapter', function() { expect(timeoutLog.mpvid).to.have.ordered.members(['', '']); expect(timeoutLog.crid).to.have.ordered.members(['', '451466393']); }); - - it('should pick winning bid if multibids with same request id', function() { - performStandardAuctionMultiBidWithSameRequestId(MOCK.BIDS_SAME_REQ_DIFF_CPM); - let winningBid = medianetAnalytics.getlogsQueue().map((log) => getQueryData(log)).filter(log => log.winner)[0]; - expect(winningBid.adid).equals('3e6e4bce5c8fgg'); - medianetAnalytics.clearlogsQueue(); - - const reversedResponseArray = [].concat(MOCK.BIDS_SAME_REQ_DIFF_CPM).reverse(); - performStandardAuctionMultiBidWithSameRequestId(reversedResponseArray); - winningBid = medianetAnalytics.getlogsQueue().map((log) => getQueryData(log)).filter(log => log.winner)[0]; - expect(winningBid.adid).equals('3e6e4bce5c8fgg'); - }); - - it('should pick winning bid if multibids with same request id and equal cpm', function() { - performStandardAuctionMultiBidWithSameRequestId(MOCK.BIDS_SAME_REQ_EQUAL_CPM); - let winningBid = medianetAnalytics.getlogsQueue().map((log) => getQueryData(log)).filter(log => log.winner)[0]; - expect(winningBid.adid).equals('3e6e4bce5c8fgg'); - medianetAnalytics.clearlogsQueue(); - - const reversedResponseArray = [].concat(MOCK.BIDS_SAME_REQ_EQUAL_CPM).reverse(); - performStandardAuctionMultiBidWithSameRequestId(reversedResponseArray); - winningBid = medianetAnalytics.getlogsQueue().map((log) => getQueryData(log)).filter(log => log.winner)[0]; - expect(winningBid.adid).equals('3e6e4bce5c8fgg'); - }); }); }); diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index 8589c3b404f..adb9663ba7c 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -1,4 +1,4 @@ -import {expect, assert} from 'chai'; +import {expect} from 'chai'; import {spec} from 'modules/medianetBidAdapter.js'; import { makeSlot } from '../integration/faker/googletag.js'; import { config } from 'src/config.js'; @@ -99,56 +99,6 @@ let VALID_BID_REQUEST = [{ 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'bidRequestsCount': 1 }], - VALID_BID_REQUEST_WITH_ORTB2 = [{ - 'bidder': 'medianet', - 'params': { - 'crid': 'crid', - 'cid': 'customer_id', - 'site': { - 'page': 'http://media.net/prebidtest', - 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest', - 'isTop': true - } - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250]], - } - }, - 'bidId': '28f8f8130a583e', - 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', - 'ortb2Imp': { 'ext': { 'data': { 'pbadslot': '/12345/my-gpt-tag-0' } } }, - 'bidRequestsCount': 1 - }, { - 'bidder': 'medianet', - 'params': { - 'crid': 'crid', - 'cid': 'customer_id', - 'site': { - 'page': 'http://media.net/prebidtest', - 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest', - 'isTop': true - } - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-123', - 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 251]], - } - }, - 'sizes': [[300, 251]], - 'bidId': '3f97ca71b1e5c2', - 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', - 'ortb2Imp': { 'ext': { 'data': { 'pbadslot': '/12345/my-gpt-tag-0' } } }, - 'bidRequestsCount': 1 - }], VALID_BID_REQUEST_WITH_USERID = [{ 'bidder': 'medianet', 'params': { @@ -1297,17 +1247,6 @@ describe('Media.net bid adapter', function () { expect(JSON.parse(bidreq.data)).to.deep.equal(VALID_PAYLOAD_WITH_CRID); }); - it('should have valid ortb2Imp param present in bid request', function() { - let bidreq = spec.buildRequests(VALID_BID_REQUEST_WITH_ORTB2, VALID_AUCTIONDATA); - let actual = JSON.parse(bidreq.data).imp[0].ortb2Imp; - const expected = VALID_BID_REQUEST_WITH_ORTB2[0].ortb2Imp - assert.equal(JSON.stringify(actual), JSON.stringify(expected)) - - bidreq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); - actual = JSON.parse(bidreq.data).imp[0].ortb2Imp; - assert.equal(actual, undefined) - }); - it('should have userid in bid request', function () { let bidReq = spec.buildRequests(VALID_BID_REQUEST_WITH_USERID, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_WITH_USERID); diff --git a/test/spec/modules/mediasniperBidAdapter_spec.js b/test/spec/modules/mediasniperBidAdapter_spec.js deleted file mode 100644 index 21ce5297c8f..00000000000 --- a/test/spec/modules/mediasniperBidAdapter_spec.js +++ /dev/null @@ -1,506 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/mediasniperBidAdapter.js'; -import { newBidder } from 'src/adapters/bidderFactory.js'; -import * as utils from 'src/utils.js'; -import { BANNER } from '../../../src/mediaTypes.js'; - -const DEFAULT_CURRENCY = 'RUB'; -const DEFAULT_BID_TTL = 360; - -describe('mediasniperBidAdapter', function () { - const adapter = newBidder(spec); - let utilsMock; - let sandbox; - - const bid = { - bidder: 'mediasniper', - params: { siteid: 'testSiteID', placementId: '12345' }, - mediaTypes: { - banner: { - sizes: [ - [300, 250], - [300, 600], - ], - }, - }, - adUnitCode: 'div-gpt-ad-1460505748561-0', - transactionId: '47789656-9e5c-4250-b7e0-2ce4cbe71a55', - sizes: [ - [300, 250], - [300, 600], - ], - bidId: '299320f4de980d', - bidderRequestId: '1c1b642f803242', - auctionId: '84212956-c377-40e8-b000-9885a06dc692', - src: 'client', - bidRequestsCount: 1, - bidderRequestsCount: 1, - bidderWinsCount: 0, - }; - - const bidderRequest = { - bidderCode: 'mediasniper', - auctionId: '84212956-c377-40e8-b000-9885a06dc692', - bidderRequestId: '1c1b642f803242', - bids: [bid], - auctionStart: 1620973766319, - timeout: 1000, - refererInfo: { - referer: - 'https://local.url/integrationExamples/gpt/hello_world.html?pbjs_debug=true', - reachedTop: true, - isAmp: false, - numIframes: 0, - stack: [ - 'https://local.url/integrationExamples/gpt/hello_world.html?pbjs_debug=true', - ], - canonicalUrl: null, - }, - start: 1620973766325, - }; - - beforeEach(function () { - utilsMock = sinon.mock(utils); - sandbox = sinon.createSandbox(); - }); - - afterEach(function () { - utilsMock.restore(); - sandbox.restore(); - }); - - describe('isBidRequestValid', function () { - it('should returns true when bid is provided with params', function () { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should returns false when bid is provided with empty params', function () { - const noParamsBid = { - bidder: 'mediasniper', - params: {}, - mediaTypes: { - banner: { - sizes: [ - [300, 250], - [300, 600], - ], - }, - }, - adUnitCode: 'div-gpt-ad-1460505748561-0', - transactionId: '47789656-9e5c-4250-b7e0-2ce4cbe71a55', - sizes: [ - [300, 250], - [300, 600], - ], - bidId: '299320f4de980d', - }; - - expect(spec.isBidRequestValid(noParamsBid)).to.equal(false); - }); - - it('should returns false when bid is falsy or empty', function () { - const emptyBid = {}; - expect(spec.isBidRequestValid()).to.equal(false); - expect(spec.isBidRequestValid(false)).to.equal(false); - expect(spec.isBidRequestValid(emptyBid)).to.equal(false); - }); - - it('should return false when no sizes', function () { - const bannerNoSizeBid = { - bidder: 'mediasniper', - params: { placementId: '123' }, - mediaTypes: { - banner: {}, - }, - }; - - expect(spec.isBidRequestValid(bannerNoSizeBid)).to.equal(false); - }); - - it('should return false when empty sizes', function () { - const bannerEmptySizeBid = { - bidder: 'mediasniper', - params: { placementId: '123' }, - mediaTypes: { - banner: { sizes: [] }, - }, - }; - - expect(spec.isBidRequestValid(bannerEmptySizeBid)).to.equal(false); - }); - - it('should return false when mediaType is not supported', function () { - const bannerVideoBid = { - bidder: 'mediasniper', - params: { placementId: '123' }, - mediaTypes: { - video: {}, - }, - }; - - expect(spec.isBidRequestValid(bannerVideoBid)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - it('should create imp for supported mediaType only', function () { - const bidRequests = [utils.deepClone(bid)]; - const bidderRequestCopy = utils.deepClone(bidderRequest); - - bidderRequestCopy.bids = bidRequests[0]; - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = JSON.parse(request.data); - - expect(data.imp.length).to.equal(1); - expect(data.imp[0].banner).to.exist; - }); - - it('should fill pmp only if dealid exists', function () { - const bidRequests = [utils.deepClone(bid)]; - const bidderRequestCopy = utils.deepClone(bidderRequest); - - bidRequests[0].params.dealid = '123'; - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = JSON.parse(request.data); - - expect(data.imp.length).to.equal(1); - expect(data.imp[0].pmp).to.exist; - expect(data.imp[0].pmp.deals).to.exist; - expect(data.imp[0].pmp.deals.length).to.equal(1); - expect(data.imp[0].pmp.deals[0].id).to.equal( - bidRequests[0].params.dealid - ); - }); - - it('should fill site only if referer exists', function () { - const bidRequests = [utils.deepClone(bid)]; - const bidderRequestCopy = utils.deepClone(bidderRequest); - - bidderRequestCopy.refererInfo = {}; - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = JSON.parse(request.data); - - expect(data.site.domain).to.not.exist; - expect(data.site.page).to.not.exist; - expect(data.site.ref).to.not.exist; - }); - - it('should fill site only if referer exists', function () { - const bidRequests = [utils.deepClone(bid)]; - const bidderRequestCopy = utils.deepClone(bidderRequest); - - bidderRequestCopy.refererInfo = null; - - const request = spec.buildRequests(bidRequests, bidderRequestCopy); - const data = JSON.parse(request.data); - - expect(data.site.domain).to.not.exist; - expect(data.site.page).to.not.exist; - expect(data.site.ref).to.not.exist; - }); - - it('should get expected properties with default values (no params set)', function () { - const bidRequests = [utils.deepClone(bid)]; - const request = spec.buildRequests(bidRequests, bidderRequest); - const data = JSON.parse(request.data); - - // openRTB 2.5 - expect(data.cur[0]).to.equal(DEFAULT_CURRENCY); - expect(data.id).to.equal(bidderRequest.auctionId); - - expect(data.imp.length).to.equal(1); - expect(data.imp[0].id).to.equal(bidRequests[0].bidId); - expect(data.imp[0].banner.w).to.equal(300); - expect(data.imp[0].banner.h).to.equal(250); - expect(data.imp[0].banner.format[0].w).to.equal(300); - expect(data.imp[0].banner.format[0].h).to.equal(250); - expect(data.imp[0].banner.format[1].w).to.equal(300); - expect(data.imp[0].banner.format[1].h).to.equal(600); - expect(data.imp[0].banner.topframe).to.equal(0); - expect(data.imp[0].banner.pos).to.equal(0); - }); - - it('should get expected properties with values from params', function () { - const bidRequests = [utils.deepClone(bid)]; - bidRequests[0].params = { - pos: 2, - }; - const request = spec.buildRequests(bidRequests, bidderRequest); - const data = JSON.parse(request.data); - expect(data.imp[0].banner.pos).to.equal(2); - }); - - describe('PriceFloors module support', function () { - it('should not set `imp[]bidfloor` property when priceFloors module is not available', function () { - const bidRequests = [bid]; - const request = spec.buildRequests(bidRequests, bidderRequest); - const data = JSON.parse(request.data); - expect(data.imp[0].banner).to.exist; - expect(data.imp[0].bidfloor).to.not.exist; - }); - - it('should not set `imp[]bidfloor` property when priceFloors module returns false', function () { - const bidWithPriceFloors = utils.deepClone(bid); - - bidWithPriceFloors.getFloor = () => { - return false; - }; - - const bidRequests = [bidWithPriceFloors]; - const request = spec.buildRequests(bidRequests, bidderRequest); - const data = JSON.parse(request.data); - - expect(data.imp[0].banner).to.exist; - expect(data.imp[0].bidfloor).to.not.exist; - }); - - it('should get the highest floorPrice found when bid have several mediaTypes', function () { - const getFloorTest = (options) => { - switch (options.mediaType) { - case BANNER: - return { floor: 1, currency: DEFAULT_CURRENCY }; - default: - return false; - } - }; - - const bidWithPriceFloors = utils.deepClone(bid); - - bidWithPriceFloors.mediaTypes.video = { - playerSize: [600, 480], - }; - - bidWithPriceFloors.getFloor = getFloorTest; - - const bidRequests = [bidWithPriceFloors]; - const request = spec.buildRequests(bidRequests, bidderRequest); - const data = JSON.parse(request.data); - - expect(data.imp[0].banner).to.exist; - expect(data.imp[0].bidfloor).to.equal(1); - }); - }); - }); - - describe('intrepretResponse', function () { - const rawServerResponse = { - body: { - id: '60839f99-d5f2-3ab3-b6ac-736b4fe9d0ae', - seatbid: [ - { - bid: [ - { - id: '60839f99-d5f2-3ab3-b6ac-736b4fe9d0ae_0_0', - impid: '1', - price: 58.01, - adid: 'string-id', - cid: 'string-id', - crid: 'string-id', - nurl: 'https://local.url/notif?index=ab-cd-ef&price=${AUCTION_PRICE}', - w: 300, - h: 250, - adomain: ['domain.io'], - adm: '', - }, - ], - seat: '', - }, - ], - cur: DEFAULT_CURRENCY, - ext: { protocol: '5.3' }, - }, - }; - - it('Returns empty array if no bid', function () { - const request = ''; - const response01 = spec.interpretResponse( - { body: { seatbid: [{ bid: [] }] } }, - request - ); - const response02 = spec.interpretResponse( - { body: { seatbid: [] } }, - request - ); - const response03 = spec.interpretResponse( - { body: { seatbid: null } }, - request - ); - const response04 = spec.interpretResponse( - { body: { seatbid: null } }, - request - ); - const response05 = spec.interpretResponse({ body: {} }, request); - const response06 = spec.interpretResponse({}, request); - - expect(response01.length).to.equal(0); - expect(response02.length).to.equal(0); - expect(response03.length).to.equal(0); - expect(response04.length).to.equal(0); - expect(response05.length).to.equal(0); - expect(response06.length).to.equal(0); - }); - - it('Log an error', function () { - const request = ''; - sinon.stub(utils, 'isArray').throws(); - utilsMock.expects('logError').once(); - spec.interpretResponse(rawServerResponse, request); - utils.isArray.restore(); - }); - - describe('Build banner response', function () { - it('Retrurn successful response', function () { - const request = ''; - const response = spec.interpretResponse(rawServerResponse, request); - - expect(response.length).to.equal(1); - expect(response[0].requestId).to.equal( - rawServerResponse.body.seatbid[0].bid[0].impid - ); - expect(response[0].cpm).to.equal( - rawServerResponse.body.seatbid[0].bid[0].price - ); - expect(response[0].width).to.equal( - rawServerResponse.body.seatbid[0].bid[0].w - ); - expect(response[0].height).to.equal( - rawServerResponse.body.seatbid[0].bid[0].h - ); - expect(response[0].creativeId).to.equal( - rawServerResponse.body.seatbid[0].bid[0].crid - ); - expect(response[0].dealId).to.equal(null); - expect(response[0].currency).to.equal(rawServerResponse.body.cur); - expect(response[0].netRevenue).to.equal(true); - expect(response[0].ttl).to.equal(DEFAULT_BID_TTL); - expect(response[0].ad).to.equal( - rawServerResponse.body.seatbid[0].bid[0].adm - ); - expect(response[0].mediaType).to.equal(BANNER); - expect(response[0].burl).to.equal( - rawServerResponse.body.seatbid[0].bid[0].nurl - ); - expect(response[0].meta).to.deep.equal({ - advertiserDomains: rawServerResponse.body.seatbid[0].bid[0].adomain, - mediaType: BANNER, - }); - }); - - it('shoud use adid if no crid', function () { - const raw = { - body: { - seatbid: [ - { - bid: [ - { - adid: 'string-id', - }, - ], - }, - ], - }, - }; - const response = spec.interpretResponse(raw, ''); - - expect(response[0].creativeId).to.equal( - raw.body.seatbid[0].bid[0].adid - ); - }); - - it('shoud use id if no crid or adid', function () { - const raw = { - body: { - seatbid: [ - { - bid: [ - { - id: '60839f99-d5f2-3ab3-b6ac-736b4fe9d0ae_0_0', - }, - ], - }, - ], - }, - }; - const response = spec.interpretResponse(raw, ''); - - expect(response[0].creativeId).to.equal(raw.body.seatbid[0].bid[0].id); - }); - - it('shoud use 0 if no cpm', function () { - const raw = { - body: { - seatbid: [ - { - bid: [{}], - }, - ], - }, - }; - const response = spec.interpretResponse(raw, ''); - - expect(response[0].cpm).to.equal(0); - }); - - it('shoud use dealid if exists', function () { - const raw = { - body: { - seatbid: [ - { - bid: [{ dealid: '123' }], - }, - ], - }, - }; - const response = spec.interpretResponse(raw, ''); - - expect(response[0].dealId).to.equal(raw.body.seatbid[0].bid[0].dealid); - }); - - it('shoud use DEFAUL_CURRENCY if no cur', function () { - const raw = { - body: { - seatbid: [ - { - bid: [{}], - }, - ], - }, - }; - const response = spec.interpretResponse(raw, ''); - - expect(response[0].currency).to.equal(DEFAULT_CURRENCY); - }); - }); - }); - - describe('onBidWon', function () { - beforeEach(function () { - sinon.stub(utils, 'triggerPixel'); - }); - - afterEach(function () { - utils.triggerPixel.restore(); - }); - - it('Should not trigger pixel if bid does not contain burl', function () { - const result = spec.onBidWon({}); - expect(result).to.be.undefined; - expect(utils.triggerPixel.callCount).to.equal(0); - }); - - it('Should trigger pixel if bid.burl exists', function () { - const result = spec.onBidWon({ - cpm: 4.2, - burl: 'https://example.com/p=${AUCTION_PRICE}&foo=bar', - }); - - expect(utils.triggerPixel.callCount).to.equal(1); - expect(utils.triggerPixel.firstCall.args[0]).to.be.equal( - 'https://example.com/p=4.2&foo=bar' - ); - }); - }); -}); diff --git a/test/spec/modules/mediasquareBidAdapter_spec.js b/test/spec/modules/mediasquareBidAdapter_spec.js index 40d0c44e4f9..f3f09a8ddf8 100644 --- a/test/spec/modules/mediasquareBidAdapter_spec.js +++ b/test/spec/modules/mediasquareBidAdapter_spec.js @@ -61,25 +61,7 @@ describe('MediaSquare bid adapter tests', function () { code: 'publishername_atf_desktop_rg_pave' }, }]; - var FLOORS_PARAMS = [{ - adUnitCode: 'banner-div', - bidId: 'aaaa1234', - auctionId: 'bbbb1234', - transactionId: 'cccc1234', - mediaTypes: { - banner: { - sizes: [ - [300, 250] - ] - } - }, - bidder: 'mediasquare', - params: { - owner: 'test', - code: 'publishername_atf_desktop_rg_pave' - }, - getFloor: function (a) { return { currency: 'EUR', floor: 1.0 }; }, - }]; + var BID_RESPONSE = {'body': { 'responses': [{ 'transaction_id': 'cccc1234', @@ -135,12 +117,6 @@ describe('MediaSquare bid adapter tests', function () { expect(requestContent.codes[0]).to.have.property('auctionId').and.to.equal('bbbb1234'); expect(requestContent.codes[0]).to.have.property('transactionId').and.to.equal('cccc1234'); expect(requestContent.codes[0]).to.have.property('mediatypes').exist; - expect(requestContent.codes[0]).to.have.property('floor').exist; - expect(requestContent.codes[0].floor).to.deep.equal({}); - const requestfloor = spec.buildRequests(FLOORS_PARAMS, DEFAULT_OPTIONS); - const responsefloor = JSON.parse(requestfloor.data); - expect(responsefloor.codes[0]).to.have.property('floor').exist; - expect(responsefloor.codes[0].floor).to.have.property('floor').and.to.equal(1.0); }); it('Verify parse response', function () { @@ -172,14 +148,6 @@ describe('MediaSquare bid adapter tests', function () { expect(bid.mediasquare.match).to.exist; expect(bid.mediasquare.match).to.equal(true); }); - it('Verifies hasConsent', function () { - const request = spec.buildRequests(DEFAULT_PARAMS, DEFAULT_OPTIONS); - BID_RESPONSE.body.responses[0].hasConsent = true; - const response = spec.interpretResponse(BID_RESPONSE, request); - const bid = response[0]; - expect(bid.mediasquare.hasConsent).to.exist; - expect(bid.mediasquare.hasConsent).to.equal(true); - }); it('Verifies bidder code', function () { expect(spec.code).to.equal('mediasquare'); }); @@ -193,15 +161,13 @@ describe('MediaSquare bid adapter tests', function () { }); it('Verifies bid won', function () { const request = spec.buildRequests(DEFAULT_PARAMS, DEFAULT_OPTIONS); - BID_RESPONSE.body.responses[0].match = true - BID_RESPONSE.body.responses[0].hasConsent = true; const response = spec.interpretResponse(BID_RESPONSE, request); const won = spec.onBidWon(response[0]); expect(won).to.equal(true); }); it('Verifies user sync without cookie in bid response', function () { var syncs = spec.getUserSyncs({}, [BID_RESPONSE], DEFAULT_OPTIONS.gdprConsent, DEFAULT_OPTIONS.uspConsent); - expect(syncs).to.have.lengthOf(0); + expect(syncs).to.have.property('type').and.to.equal('iframe'); }); it('Verifies user sync with cookies in bid response', function () { BID_RESPONSE.body.cookies = [{'type': 'image', 'url': 'http://www.cookie.sync.org/'}]; @@ -212,13 +178,13 @@ describe('MediaSquare bid adapter tests', function () { }); it('Verifies user sync with no bid response', function() { var syncs = spec.getUserSyncs({}, null, DEFAULT_OPTIONS.gdprConsent, DEFAULT_OPTIONS.uspConsent); - expect(syncs).to.have.lengthOf(0); + expect(syncs).to.have.property('type').and.to.equal('iframe'); }); it('Verifies user sync with no bid body response', function() { var syncs = spec.getUserSyncs({}, [], DEFAULT_OPTIONS.gdprConsent, DEFAULT_OPTIONS.uspConsent); - expect(syncs).to.have.lengthOf(0); + expect(syncs).to.have.property('type').and.to.equal('iframe'); var syncs = spec.getUserSyncs({}, [{}], DEFAULT_OPTIONS.gdprConsent, DEFAULT_OPTIONS.uspConsent); - expect(syncs).to.have.lengthOf(0); + expect(syncs).to.have.property('type').and.to.equal('iframe'); }); it('Verifies native in bid response', function () { const request = spec.buildRequests(NATIVE_PARAMS, DEFAULT_OPTIONS); diff --git a/test/spec/modules/merkleIdSystem_spec.js b/test/spec/modules/merkleIdSystem_spec.js deleted file mode 100644 index 63a2791ba3c..00000000000 --- a/test/spec/modules/merkleIdSystem_spec.js +++ /dev/null @@ -1,230 +0,0 @@ -import * as ajaxLib from 'src/ajax.js'; -import * as utils from 'src/utils.js'; -import {merkleIdSubmodule} from 'modules/merkleIdSystem.js'; - -import sinon from 'sinon'; - -let expect = require('chai').expect; - -const CONFIG_PARAMS = { - endpoint: 'https://test/id', - vendor: 'idsv2', - sv_cid: '5344_04531', - sv_pubid: '11314', - sv_domain: 'www.testDomain.com', - sv_session: 'testsession' -}; - -const STORAGE_PARAMS = { - type: 'cookie', - name: 'merkle', - expires: 10, - refreshInSeconds: 10 -}; - -const MOCK_RESPONSE = { - c: { - name: '_svsid', - value: '123876327647627364236478' - } -}; - -function mockResponse( - responseText, - response = (url, successCallback) => successCallback(responseText)) { - return function() { - return response; - } -} - -describe('Merkle System', function () { - describe('Merkle System getId()', function () { - const callbackSpy = sinon.spy(); - let sandbox; - let ajaxStub; - - beforeEach(function () { - sandbox = sinon.sandbox.create(); - sinon.stub(utils, 'logInfo'); - sinon.stub(utils, 'logWarn'); - sinon.stub(utils, 'logError'); - callbackSpy.resetHistory(); - ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockResponse(JSON.stringify(MOCK_RESPONSE))); - }); - - afterEach(function () { - utils.logInfo.restore(); - utils.logWarn.restore(); - utils.logError.restore(); - ajaxStub.restore(); - }); - - it('getId() should fail on missing vendor', function () { - let config = { - params: { - ...CONFIG_PARAMS, - vendor: undefined - }, - storage: STORAGE_PARAMS - }; - - let submoduleCallback = merkleIdSubmodule.getId(config, undefined); - expect(submoduleCallback).to.be.undefined; - expect(utils.logError.args[0][0]).to.exist.and.to.equal('User ID - merkleId submodule requires a valid vendor to be defined'); - }); - - it('getId() should fail on missing vendor', function () { - let config = { - params: { - ...CONFIG_PARAMS, - vendor: undefined - }, - storage: STORAGE_PARAMS - }; - - let submoduleCallback = merkleIdSubmodule.getId(config, undefined); - expect(submoduleCallback).to.be.undefined; - expect(utils.logError.args[0][0]).to.exist.and.to.equal('User ID - merkleId submodule requires a valid vendor to be defined'); - }); - - it('getId() should fail on missing sv_cid', function () { - let config = { - params: { - ...CONFIG_PARAMS, - sv_cid: undefined - }, - storage: STORAGE_PARAMS - }; - - let submoduleCallback = merkleIdSubmodule.getId(config, undefined); - expect(submoduleCallback).to.be.undefined; - expect(utils.logError.args[0][0]).to.exist.and.to.equal('User ID - merkleId submodule requires a valid sv_cid string to be defined'); - }); - - it('getId() should fail on missing sv_pubid', function () { - let config = { - params: { - ...CONFIG_PARAMS, - sv_pubid: undefined - }, - storage: STORAGE_PARAMS - }; - - let submoduleCallback = merkleIdSubmodule.getId(config, undefined); - expect(submoduleCallback).to.be.undefined; - expect(utils.logError.args[0][0]).to.exist.and.to.equal('User ID - merkleId submodule requires a valid sv_pubid string to be defined'); - }); - - it('getId() should warn on missing endpoint', function () { - let config = { - params: { - ...CONFIG_PARAMS, - endpoint: undefined - }, - storage: STORAGE_PARAMS - }; - - let submoduleCallback = merkleIdSubmodule.getId(config, undefined).callback; - submoduleCallback(callbackSpy); - expect(callbackSpy.calledOnce).to.be.true; - expect(utils.logWarn.args[0][0]).to.exist.and.to.equal('User ID - merkleId submodule endpoint string is not defined'); - }); - - it('getId() should handle callback with valid configuration', function () { - let config = { - params: CONFIG_PARAMS, - storage: STORAGE_PARAMS - }; - - let submoduleCallback = merkleIdSubmodule.getId(config, undefined).callback; - submoduleCallback(callbackSpy); - expect(callbackSpy.calledOnce).to.be.true; - }); - }); - - describe('Merkle System extendId()', function () { - const callbackSpy = sinon.spy(); - let sandbox; - let ajaxStub; - - beforeEach(function () { - sandbox = sinon.sandbox.create(); - sinon.stub(utils, 'logInfo'); - sinon.stub(utils, 'logWarn'); - sinon.stub(utils, 'logError'); - callbackSpy.resetHistory(); - ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockResponse(JSON.stringify(MOCK_RESPONSE))); - }); - - afterEach(function () { - utils.logInfo.restore(); - utils.logWarn.restore(); - utils.logError.restore(); - ajaxStub.restore(); - }); - - it('extendId() get storedid', function () { - let config = { - params: { - ...CONFIG_PARAMS, - }, - storage: STORAGE_PARAMS - }; - - let id = merkleIdSubmodule.extendId(config, undefined, 'Merkle_Stored_ID'); - expect(id.id).to.exist.and.to.equal('Merkle_Stored_ID'); - }); - - it('extendId() get storedId on configured storageParam.refreshInSeconds', function () { - let config = { - params: { - ...CONFIG_PARAMS, - refreshInSeconds: 1000 - }, - storage: STORAGE_PARAMS - }; - - let yesterday = new Date(Date.now() - 86400000).toUTCString(); - let storedId = {value: 'Merkle_Stored_ID', date: yesterday}; - - let id = merkleIdSubmodule.extendId(config, undefined, - storedId); - - expect(id.id).to.exist.and.to.equal(storedId); - }); - it('extendId() should warn on missing endpoint', function () { - let config = { - params: { - ...CONFIG_PARAMS, - endpoint: undefined - }, - storage: STORAGE_PARAMS - }; - - let yesterday = new Date(Date.now() - 86400000).toUTCString(); - let storedId = {value: 'Merkle_Stored_ID', date: yesterday}; - - let submoduleCallback = merkleIdSubmodule.extendId(config, undefined, - storedId).callback; - submoduleCallback(callbackSpy); - expect(callbackSpy.calledOnce).to.be.true; - expect(utils.logWarn.args[0][0]).to.exist.and.to.equal('User ID - merkleId submodule endpoint string is not defined'); - }); - - it('extendId() callback on configured storageParam.refreshInSeconds', function () { - let config = { - params: { - ...CONFIG_PARAMS, - refreshInSeconds: 1 - } - }; - - let yesterday = new Date(Date.now() - 86400000).toUTCString(); - let storedId = {value: 'Merkle_Stored_ID', date: yesterday}; - - let submoduleCallback = merkleIdSubmodule.extendId(config, undefined, storedId).callback; - submoduleCallback(callbackSpy); - expect(callbackSpy.calledOnce).to.be.true; - }); - }); -}); diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js deleted file mode 100644 index 34ad29b3e92..00000000000 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ /dev/null @@ -1,826 +0,0 @@ -import {assert, expect} from 'chai'; -import { spec, storage } from 'modules/mgidBidAdapter.js'; -import { version } from 'package.json'; -import * as utils from '../../../src/utils.js'; - -describe('Mgid bid adapter', function () { - let sandbox; - let logErrorSpy; - let logWarnSpy; - beforeEach(function () { - sandbox = sinon.sandbox.create(); - logErrorSpy = sinon.spy(utils, 'logError'); - logWarnSpy = sinon.spy(utils, 'logWarn'); - }); - - afterEach(function () { - sandbox.restore(); - utils.logError.restore(); - utils.logWarn.restore(); - }); - const ua = navigator.userAgent; - const screenHeight = screen.height; - const screenWidth = screen.width; - const dnt = (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0; - const language = navigator.language ? 'language' : 'userLanguage'; - let lang = navigator[language].split('-')[0]; - if (lang.length != 2 && lang.length != 3) { - lang = ''; - } - const secure = window.location.protocol === 'https:' ? 1 : 0; - const mgid_ver = spec.VERSION; - const utcOffset = (new Date()).getTimezoneOffset().toString(); - - describe('isBidRequestValid', function () { - let bid = { - 'adUnitCode': 'div', - 'bidder': 'mgid', - 'params': { - 'property': '10433394', - 'zone': 'zone' - }, - }; - - it('should not accept bid without required params', function () { - let isValid = spec.isBidRequestValid(bid); - expect(isValid).to.equal(false); - }); - - it('should return false when params are not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {}; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when valid params are not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {accountId: '', placementId: ''}; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when valid params are not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.adUnitCode = ''; - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - bid.params = {accountId: 2, placementId: 1}; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when adUnitCode not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.adUnitCode = ''; - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - bid.params = {accountId: 2, placementId: 1}; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return true when valid params are passed as nums', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.adUnitCode = 'div'; - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - bid.params = {accountId: 2, placementId: 1}; - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when valid params are not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.mediaTypes = { - native: { - sizes: [[300, 250]] - } - }; - bid.params = {accountId: '0', placementId: '00'}; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when valid mediaTypes are not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when valid mediaTypes.banner are not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; - bid.mediaTypes = { - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when valid mediaTypes.banner.sizes are not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; - bid.mediaTypes = { - sizes: [] - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when valid mediaTypes.banner.sizes are not valid', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; - bid.mediaTypes = { - sizes: [300, 250] - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return true when valid params are passed as strings', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.adUnitCode = 'div'; - bid.params = {accountId: '1', placementId: '1'}; - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when valid mediaTypes.native is not object', function () { - let bid = Object.assign({}, bid); - bid.params = {accountId: '1', placementId: '1'}; - bid.mediaTypes = { - native: [] - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when mediaTypes.native is empty object', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; - bid.mediaTypes = { - native: {} - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when mediaTypes.native is invalid object', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; - bid.mediaTypes = { - native: { - image: { - sizes: [80, 80] - }, - } - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when mediaTypes.native has unsupported required asset', function () { - let bid = Object.assign({}, bid); - bid.params = {accountId: '2', placementId: '1'}; - bid.mediaTypes = { - native: { - title: {required: true}, - image: {required: false, sizes: [80, 80]}, - sponsored: {required: false}, - }, - }; - bid.nativeParams = { - title: {required: true}, - image: {required: false, sizes: [80, 80]}, - sponsored: {required: false}, - unsupported: {required: true}, - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return true when mediaTypes.native all assets needed', function () { - let bid = Object.assign({}, bid); - bid.adUnitCode = 'div'; - bid.params = {accountId: '2', placementId: '1'}; - bid.mediaTypes = { - native: { - title: {required: true}, - image: {required: false, sizes: [80, 80]}, - sponsored: {required: false}, - }, - }; - bid.nativeParams = { - title: {required: true}, - image: {required: false, sizes: [80, 80]}, - sponsored: {required: false}, - }; - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - }); - - describe('override defaults', function () { - let bid = { - bidder: 'mgid', - params: { - accountId: '1', - placementId: '2', - }, - }; - it('should return object', function () { - let bid = Object.assign({}, bid); - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - let bidRequests = [bid]; - const request = spec.buildRequests(bidRequests); - expect(request).to.exist.and.to.be.a('object'); - }); - - it('should return overwrite default bidurl', function () { - let bid = Object.assign({}, bid); - bid.params = { - bidUrl: 'https://newbidurl.com/', - accountId: '1', - placementId: '2', - }; - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - let bidRequests = [bid]; - const request = spec.buildRequests(bidRequests); - expect(request.url).to.include('https://newbidurl.com/1'); - }); - it('should return overwrite default bidFloor', function () { - let bid = Object.assign({}, bid); - bid.params = { - bidFloor: 1.1, - accountId: '1', - placementId: '2', - }; - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - let bidRequests = [bid]; - const request = spec.buildRequests(bidRequests); - expect(request.data).to.be.a('string'); - const data = JSON.parse(request.data); - expect(data).to.be.a('object'); - expect(data.imp).to.be.a('array'); - expect(data.imp).to.have.lengthOf(1); - expect(data.imp[0].bidfloor).to.deep.equal(1.1); - }); - it('should return overwrite default currency', function () { - let bid = Object.assign({}, bid); - bid.params = { - cur: 'GBP', - accountId: '1', - placementId: '2', - }; - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - let bidRequests = [bid]; - const request = spec.buildRequests(bidRequests); - expect(request.data).to.be.a('string'); - const data = JSON.parse(request.data); - expect(data).to.be.a('object'); - expect(data.cur).to.deep.equal(['GBP']); - }); - }); - - describe('buildRequests', function () { - let abid = { - adUnitCode: 'div', - bidder: 'mgid', - params: { - accountId: '1', - placementId: '2', - }, - }; - - it('should return undefined if no validBidRequests passed', function () { - expect(spec.buildRequests([])).to.be.undefined; - }); - it('should return request url with muid', function () { - let getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); - getDataFromLocalStorageStub.withArgs('mgMuidn').returns('xxx'); - - let bid = Object.assign({}, abid); - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - let bidRequests = [bid]; - const request = spec.buildRequests(bidRequests); - expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1?muid=xxx'); - - getDataFromLocalStorageStub.restore(); - }); - it('should proper handle gdpr', function () { - let bid = Object.assign({}, abid); - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - let bidRequests = [bid]; - const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'gdpr', gdprApplies: true}}); - expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); - expect(request.method).deep.equal('POST'); - const data = JSON.parse(request.data); - expect(data.user).deep.equal({ext: {consent: 'gdpr'}}); - expect(data.regs).deep.equal({ext: {gdpr: 1}}); - }); - it('should return proper banner imp', function () { - let bid = Object.assign({}, abid); - bid.mediaTypes = { - banner: { - sizes: [[300, 250]] - } - }; - let bidRequests = [bid]; - const page = top.location.href; - const domain = utils.parseUrl(page).hostname; - const request = spec.buildRequests(bidRequests); - expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); - expect(request.method).deep.equal('POST'); - const data = JSON.parse(request.data); - expect(data.site.domain).to.deep.equal(domain); - expect(data.site.page).to.deep.equal(page); - expect(data.cur).to.deep.equal(['USD']); - expect(data.device.ua).to.deep.equal(ua); - expect(data.device.dnt).equal(dnt); - expect(data.device.h).equal(screenHeight); - expect(data.device.w).equal(screenWidth); - expect(data.device.language).to.deep.equal(lang); - expect(data.imp[0].tagid).to.deep.equal('2/div'); - expect(data.imp[0].banner).to.deep.equal({w: 300, h: 250}); - expect(data.imp[0].secure).to.deep.equal(secure); - expect(request).to.deep.equal({ - 'method': 'POST', - 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{"site":{"domain":"' + domain + '","page":"' + page + '"},"cur":["USD"],"geo":{"utcoffset":' + utcOffset + '},"device":{"ua":"' + ua + '","js":1,"dnt":' + dnt + ',"h":' + screenHeight + ',"w":' + screenWidth + ',"language":"' + lang + '"},"ext":{"mgid_ver":"' + mgid_ver + '","prebid_ver":"' + version + '"},"imp":[{"tagid":"2/div","secure":' + secure + ',"banner":{"w":300,"h":250}}]}', - }); - }); - it('should not return native imp if minimum asset list not requested', function () { - let bid = Object.assign({}, abid); - bid.mediaTypes = { - native: '', - }; - bid.nativeParams = { - title: {required: true}, - image: {sizes: [80, 80]}, - }; - let bidRequests = [bid]; - const request = spec.buildRequests(bidRequests); - expect(request).to.be.undefined; - }); - it('should return proper native imp', function () { - let bid = Object.assign({}, abid); - bid.mediaTypes = { - native: '', - }; - bid.nativeParams = { - title: {required: true}, - image: {sizes: [80, 80]}, - sponsored: { }, - }; - - let bidRequests = [bid]; - const page = top.location.href; - const domain = utils.parseUrl(page).hostname; - const request = spec.buildRequests(bidRequests); - expect(request).to.be.a('object'); - expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); - expect(request.method).deep.equal('POST'); - const data = JSON.parse(request.data); - expect(data.site.domain).to.deep.equal(domain); - expect(data.site.page).to.deep.equal(page); - expect(data.cur).to.deep.equal(['USD']); - expect(data.device.ua).to.deep.equal(ua); - expect(data.device.dnt).equal(dnt); - expect(data.device.h).equal(screenHeight); - expect(data.device.w).equal(screenWidth); - expect(data.device.language).to.deep.equal(lang); - expect(data.imp[0].tagid).to.deep.equal('2/div'); - expect(data.imp[0].native).is.a('object').and.to.deep.equal({'request': {'assets': [{'id': 1, 'required': 1, 'title': {'len': 80}}, {'id': 2, 'img': {'h': 80, 'type': 3, 'w': 80}, 'required': 0}, {'data': {'type': 1}, 'id': 11, 'required': 0}], 'plcmtcnt': 1}}); - expect(data.imp[0].secure).to.deep.equal(secure); - expect(request).to.deep.equal({ - 'method': 'POST', - 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{"site":{"domain":"' + domain + '","page":"' + page + '"},"cur":["USD"],"geo":{"utcoffset":' + utcOffset + '},"device":{"ua":"' + ua + '","js":1,"dnt":' + dnt + ',"h":' + screenHeight + ',"w":' + screenWidth + ',"language":"' + lang + '"},"ext":{"mgid_ver":"' + mgid_ver + '","prebid_ver":"' + version + '"},"imp":[{"tagid":"2/div","secure":' + secure + ',"native":{"request":{"plcmtcnt":1,"assets":[{"id":1,"required":1,"title":{"len":80}},{"id":2,"required":0,"img":{"type":3,"w":80,"h":80}},{"id":11,"required":0,"data":{"type":1}}]}}}]}', - }); - }); - it('should return proper native imp with image altered', function () { - let bid = Object.assign({}, abid); - bid.mediaTypes = { - native: '', - }; - bid.nativeParams = { - title: {required: true}, - image: {wmin: 50, hmin: 50, required: true}, - icon: {}, - sponsored: { }, - }; - - let bidRequests = [bid]; - const page = top.location.href; - const domain = utils.parseUrl(page).hostname; - const request = spec.buildRequests(bidRequests); - expect(request).to.be.a('object'); - expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); - expect(request.method).deep.equal('POST'); - const data = JSON.parse(request.data); - expect(data.site.domain).to.deep.equal(domain); - expect(data.site.page).to.deep.equal(page); - expect(data.cur).to.deep.equal(['USD']); - expect(data.device.ua).to.deep.equal(ua); - expect(data.device.dnt).equal(dnt); - expect(data.device.h).equal(screenHeight); - expect(data.device.w).equal(screenWidth); - expect(data.device.language).to.deep.equal(lang); - expect(data.imp[0].tagid).to.deep.equal('2/div'); - expect(data.imp[0].native).is.a('object').and.to.deep.equal({'request': {'assets': [{'id': 1, 'required': 1, 'title': {'len': 80}}, {'id': 2, 'img': {'h': 328, hmin: 50, 'type': 3, 'w': 492, wmin: 50}, 'required': 1}, {'id': 3, 'img': {'h': 50, 'type': 1, 'w': 50}, 'required': 0}, {'data': {'type': 1}, 'id': 11, 'required': 0}], 'plcmtcnt': 1}}); - expect(data.imp[0].secure).to.deep.equal(secure); - expect(request).to.deep.equal({ - 'method': 'POST', - 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{"site":{"domain":"' + domain + '","page":"' + page + '"},"cur":["USD"],"geo":{"utcoffset":' + utcOffset + '},"device":{"ua":"' + ua + '","js":1,"dnt":' + dnt + ',"h":' + screenHeight + ',"w":' + screenWidth + ',"language":"' + lang + '"},"ext":{"mgid_ver":"' + mgid_ver + '","prebid_ver":"' + version + '"},"imp":[{"tagid":"2/div","secure":' + secure + ',"native":{"request":{"plcmtcnt":1,"assets":[{"id":1,"required":1,"title":{"len":80}},{"id":2,"required":1,"img":{"type":3,"w":492,"h":328,"wmin":50,"hmin":50}},{"id":3,"required":0,"img":{"type":1,"w":50,"h":50}},{"id":11,"required":0,"data":{"type":1}}]}}}]}', - }); - }); - it('should return proper native imp with sponsoredBy', function () { - let bid = Object.assign({}, abid); - bid.mediaTypes = { - native: '', - }; - bid.nativeParams = { - title: {required: true}, - image: {sizes: [80, 80]}, - sponsoredBy: { }, - }; - - let bidRequests = [bid]; - const page = top.location.href; - const domain = utils.parseUrl(page).hostname; - const request = spec.buildRequests(bidRequests); - expect(request).to.be.a('object'); - expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); - expect(request.method).deep.equal('POST'); - const data = JSON.parse(request.data); - expect(data.site.domain).to.deep.equal(domain); - expect(data.site.page).to.deep.equal(page); - expect(data.cur).to.deep.equal(['USD']); - expect(data.device.ua).to.deep.equal(ua); - expect(data.device.dnt).equal(dnt); - expect(data.device.h).equal(screenHeight); - expect(data.device.w).equal(screenWidth); - expect(data.device.language).to.deep.equal(lang); - expect(data.imp[0].tagid).to.deep.equal('2/div'); - expect(data.imp[0].native).is.a('object').and.to.deep.equal({'request': {'assets': [{'id': 1, 'required': 1, 'title': {'len': 80}}, {'id': 2, 'img': {'h': 80, 'type': 3, 'w': 80}, 'required': 0}, {'data': {'type': 1}, 'id': 4, 'required': 0}], 'plcmtcnt': 1}}); - expect(data.imp[0].secure).to.deep.equal(secure); - expect(request).to.deep.equal({ - 'method': 'POST', - 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{"site":{"domain":"' + domain + '","page":"' + page + '"},"cur":["USD"],"geo":{"utcoffset":' + utcOffset + '},"device":{"ua":"' + ua + '","js":1,"dnt":' + dnt + ',"h":' + screenHeight + ',"w":' + screenWidth + ',"language":"' + lang + '"},"ext":{"mgid_ver":"' + mgid_ver + '","prebid_ver":"' + version + '"},"imp":[{"tagid":"2/div","secure":' + secure + ',"native":{"request":{"plcmtcnt":1,"assets":[{"id":1,"required":1,"title":{"len":80}},{"id":2,"required":0,"img":{"type":3,"w":80,"h":80}},{"id":4,"required":0,"data":{"type":1}}]}}}]}', - }); - }); - it('should return proper banner request', function () { - let bid = Object.assign({}, abid); - bid.mediaTypes = { - banner: { - sizes: [[300, 600], [300, 250]], - pos: 1, - }, - }; - let bidRequests = [bid]; - const request = spec.buildRequests(bidRequests); - - const page = top.location.href; - const domain = utils.parseUrl(page).hostname; - expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); - expect(request.method).deep.equal('POST'); - const data = JSON.parse(request.data); - expect(data.site.domain).to.deep.equal(domain); - expect(data.site.page).to.deep.equal(page); - expect(data.cur).to.deep.equal(['USD']); - expect(data.device.ua).to.deep.equal(ua); - expect(data.device.dnt).equal(dnt); - expect(data.device.h).equal(screenHeight); - expect(data.device.w).equal(screenWidth); - expect(data.device.language).to.deep.equal(lang); - expect(data.imp[0].tagid).to.deep.equal('2/div'); - expect(data.imp[0].banner).to.deep.equal({w: 300, h: 600, format: [{w: 300, h: 600}, {w: 300, h: 250}], pos: 1}); - expect(data.imp[0].secure).to.deep.equal(secure); - - expect(request).to.deep.equal({ - 'method': 'POST', - 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{"site":{"domain":"' + domain + '","page":"' + page + '"},"cur":["USD"],"geo":{"utcoffset":' + utcOffset + '},"device":{"ua":"' + ua + '","js":1,"dnt":' + dnt + ',"h":' + screenHeight + ',"w":' + screenWidth + ',"language":"' + lang + '"},"ext":{"mgid_ver":"' + mgid_ver + '","prebid_ver":"' + version + '"},"imp":[{"tagid":"2/div","secure":' + secure + ',"banner":{"w":300,"h":600,"format":[{"w":300,"h":600},{"w":300,"h":250}],"pos":1}}]}', - }); - }); - }); - - describe('interpretResponse', function () { - it('should not push proper native bid response if adm is missing', function () { - let resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': {'place': 0, 'crtype': 'native'}, 'adomain': ['test.com']}], 'seat': '44082'}]} - }; - let bids = spec.interpretResponse(resp); - expect(bids).to.deep.equal([]) - }); - it('should not push proper native bid response if assets is empty', function () { - let resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[],"imptrackers":["imptrackers1"]}}', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': {'place': 0, 'crtype': 'native'}, 'adomain': ['test.com']}], 'seat': '44082'}]} - }; - let bids = spec.interpretResponse(resp); - expect(bids).to.deep.equal([]) - }); - it('should push proper native bid response, assets1', function () { - let resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[{"id":1,"required":0,"title":{"text":"title1"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"image_src"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"icon_src"}},{"id":4,"required":0,"data":{"type":4,"value":"sponsored"}},{"id":5,"required":0,"data":{"type":6,"value":"price1"}},{"id":6,"required":0,"data":{"type":7,"value":"price2"}}],"imptrackers":["imptrackers1"]}}', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': {'place': 0, 'crtype': 'native'}, 'adomain': ['test.com']}], 'seat': '44082'}], ext: {'muidn': 'userid'}} - }; - let bids = spec.interpretResponse(resp); - expect(bids).to.deep.equal([{ - 'ad': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[{"id":1,"required":0,"title":{"text":"title1"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"image_src"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"icon_src"}},{"id":4,"required":0,"data":{"type":4,"value":"sponsored"}},{"id":5,"required":0,"data":{"type":6,"value":"price1"}},{"id":6,"required":0,"data":{"type":7,"value":"price2"}}],"imptrackers":["imptrackers1"]}}', - 'burl': 'https burl', - 'cpm': 1.5, - 'creativeId': '2898532/2419121/2592854/2499195', - 'currency': 'GBP', - 'dealId': '', - 'height': 0, - 'isBurl': true, - 'mediaType': 'native', - 'meta': {'advertiserDomains': ['test.com']}, - 'native': { - 'clickTrackers': [], - 'clickUrl': 'link_url', - 'data': 'price1', - 'icon': { - 'height': 50, - 'url': 'icon_src', - 'width': 50 - }, - 'image': { - 'height': 80, - 'url': 'image_src', - 'width': 80 - }, - 'impressionTrackers': [ - 'imptrackers1' - ], - 'jstracker': [], - 'sponsoredBy': 'sponsored', - 'title': 'title1' - }, - 'netRevenue': true, - 'nurl': 'https nurl', - 'requestId': '61e40632c53fc2', - 'ttl': 300, - 'width': 0 - }]) - }); - it('should push proper native bid response, assets2', function () { - let resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[{"id":1,"required":0,"title":{"text":"title1"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"image_src"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"icon_src"}}],"imptrackers":["imptrackers1"]}}', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': {'place': 0, 'crtype': 'native'}, 'adomain': ['test.com']}], 'seat': '44082'}]} - }; - let bids = spec.interpretResponse(resp); - expect(bids).to.deep.equal([ - { - 'ad': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[{"id":1,"required":0,"title":{"text":"title1"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"image_src"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"icon_src"}}],"imptrackers":["imptrackers1"]}}', - 'cpm': 1.5, - 'creativeId': '2898532/2419121/2592854/2499195', - 'currency': 'GBP', - 'dealId': '', - 'height': 0, - 'isBurl': true, - 'mediaType': 'native', - 'meta': {'advertiserDomains': ['test.com']}, - 'netRevenue': true, - 'nurl': 'https nurl', - 'burl': 'https burl', - 'requestId': '61e40632c53fc2', - 'ttl': 300, - 'width': 0, - 'native': { - clickTrackers: [], - title: 'title1', - image: { - url: 'image_src', - width: 80, - height: 80, - }, - icon: { - url: 'icon_src', - width: 50, - height: 50, - }, - impressionTrackers: ['imptrackers1'], - jstracker: [], - clickUrl: 'link_url', - } - } - ]); - }); - - it('should not push bid response', function () { - let bids = spec.interpretResponse(); - expect(bids).to.be.undefined; - }); - it('should push proper banner bid response', function () { - let resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': '', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': 'html: adm', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'adomain': ['test.com']}], 'seat': '44082'}]} - }; - let bids = spec.interpretResponse(resp); - expect(bids).to.deep.equal([ - { - 'ad': 'html: adm', - 'cpm': 1.5, - 'creativeId': '2898532/2419121/2592854/2499195', - 'currency': 'USD', - 'dealId': '', - 'height': 600, - 'isBurl': true, - 'mediaType': 'banner', - 'meta': {'advertiserDomains': ['test.com']}, - 'netRevenue': true, - 'nurl': 'https nurl', - 'burl': 'https burl', - 'requestId': '61e40632c53fc2', - 'ttl': 300, - 'width': 300, - } - ]); - }); - }); - - describe('getUserSyncs', function () { - it('should do nothing on getUserSyncs', function () { - spec.getUserSyncs() - }); - }); - - describe('on bidWon', function () { - beforeEach(function() { - sinon.stub(utils, 'triggerPixel'); - }); - afterEach(function() { - utils.triggerPixel.restore(); - }); - it('should replace nurl and burl for native', function () { - const burl = 'burl&s=${' + 'AUCTION_PRICE}'; - const nurl = 'nurl&s=${' + 'AUCTION_PRICE}'; - const bid = {'bidderCode': 'mgid', 'width': 0, 'height': 0, 'statusMessage': 'Bid available', 'adId': '3d0b6ff1dda89', 'requestId': '2a423489e058a1', 'mediaType': 'native', 'source': 'client', 'ad': '{"native":{"ver":"1.1","link":{"url":"LinkURL"},"assets":[{"id":1,"required":0,"title":{"text":"TITLE"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"ImageURL"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"IconURL"}},{"id":11,"required":0,"data":{"type":1,"value":"sponsored"}}],"imptrackers":["ImpTrackerURL"]}}', 'cpm': 0.66, 'creativeId': '353538_591471', 'currency': 'USD', 'dealId': '', 'netRevenue': true, 'ttl': 300, 'nurl': nurl, 'burl': burl, 'isBurl': true, 'native': {'title': 'TITLE', 'image': {'url': 'ImageURL', 'height': 80, 'width': 80}, 'icon': {'url': 'IconURL', 'height': 50, 'width': 50}, 'sponsored': 'sponsored', 'clickUrl': 'LinkURL', 'clickTrackers': [], 'impressionTrackers': ['ImpTrackerURL'], 'jstracker': []}, 'auctionId': 'a92bffce-14d2-4f8f-a78a-7b9b5e4d28fa', 'responseTimestamp': 1556867386065, 'requestTimestamp': 1556867385916, 'bidder': 'mgid', 'adUnitCode': 'div-gpt-ad-1555415275793-0', 'timeToRespond': 149, 'pbLg': '0.50', 'pbMg': '0.60', 'pbHg': '0.66', 'pbAg': '0.65', 'pbDg': '0.66', 'pbCg': '', 'size': '0x0', 'adserverTargeting': {'hb_bidder': 'mgid', 'hb_adid': '3d0b6ff1dda89', 'hb_pb': '0.66', 'hb_size': '0x0', 'hb_source': 'client', 'hb_format': 'native', 'hb_native_title': 'TITLE', 'hb_native_image': 'hb_native_image:3d0b6ff1dda89', 'hb_native_icon': 'IconURL', 'hb_native_linkurl': 'hb_native_linkurl:3d0b6ff1dda89'}, 'status': 'targetingSet', 'params': [{'accountId': '184', 'placementId': '353538'}]}; - spec.onBidWon(bid); - expect(bid.nurl).to.deep.equal('nurl&s=0.66'); - expect(bid.burl).to.deep.equal('burl&s=0.66'); - }); - it('should replace nurl and burl for banner', function () { - const burl = 'burl&s=${' + 'AUCTION_PRICE}'; - const nurl = 'nurl&s=${' + 'AUCTION_PRICE}'; - const bid = {'bidderCode': 'mgid', 'width': 0, 'height': 0, 'statusMessage': 'Bid available', 'adId': '3d0b6ff1dda89', 'requestId': '2a423489e058a1', 'mediaType': 'banner', 'source': 'client', 'ad': burl, 'cpm': 0.66, 'creativeId': '353538_591471', 'currency': 'USD', 'dealId': '', 'netRevenue': true, 'ttl': 300, 'nurl': nurl, 'burl': burl, 'isBurl': true, 'auctionId': 'a92bffce-14d2-4f8f-a78a-7b9b5e4d28fa', 'responseTimestamp': 1556867386065, 'requestTimestamp': 1556867385916, 'bidder': 'mgid', 'adUnitCode': 'div-gpt-ad-1555415275793-0', 'timeToRespond': 149, 'pbLg': '0.50', 'pbMg': '0.60', 'pbHg': '0.66', 'pbAg': '0.65', 'pbDg': '0.66', 'pbCg': '', 'size': '0x0', 'adserverTargeting': {'hb_bidder': 'mgid', 'hb_adid': '3d0b6ff1dda89', 'hb_pb': '0.66', 'hb_size': '0x0', 'hb_source': 'client', 'hb_format': 'banner', 'hb_banner_title': 'TITLE', 'hb_banner_image': 'hb_banner_image:3d0b6ff1dda89', 'hb_banner_icon': 'IconURL', 'hb_banner_linkurl': 'hb_banner_linkurl:3d0b6ff1dda89'}, 'status': 'targetingSet', 'params': [{'accountId': '184', 'placementId': '353538'}]}; - spec.onBidWon(bid); - expect(bid.nurl).to.deep.equal('nurl&s=0.66'); - expect(bid.burl).to.deep.equal(burl); - expect(bid.ad).to.deep.equal('burl&s=0.66'); - }); - }); - - describe('price floor module', function() { - let bidRequest; - let bidRequests0 = { - adUnitCode: 'div', - bidder: 'mgid', - params: { - accountId: '1', - placementId: '2', - }, - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - sizes: [[300, 250]], - } - beforeEach(function() { - bidRequest = [utils.deepClone(bidRequests0)]; - }); - - it('obtain floor from getFloor', function() { - bidRequest[0].getFloor = () => { - return { - currency: 'USD', - floor: 1.23 - }; - }; - - const payload = JSON.parse(spec.buildRequests(bidRequest).data); - expect(payload.imp[0]).to.have.property('bidfloor', 1.23); - expect(payload.imp[0]).to.not.have.property('bidfloorcur'); - }); - it('obtain floor from params', function() { - bidRequest[0].getFloor = () => { - return { - currency: 'USD', - floor: 1.23 - }; - }; - bidRequest[0].params.bidfloor = 0.1; - - const payload = JSON.parse(spec.buildRequests(bidRequest).data); - expect(payload.imp[0]).to.have.property('bidfloor', 0.1); - expect(payload.imp[0]).to.not.have.property('bidfloorcur'); - }); - - it('undefined currency -> USD', function() { - bidRequest[0].params.currency = 'EUR' - bidRequest[0].getFloor = () => { - return { - floor: 1.23 - }; - }; - - const payload = JSON.parse(spec.buildRequests(bidRequest).data); - expect(payload.imp[0]).to.have.property('bidfloor', 1.23); - expect(payload.imp[0]).to.have.property('bidfloorcur', 'USD'); - }); - it('altered currency', function() { - bidRequest[0].getFloor = () => { - return { - currency: 'EUR', - floor: 1.23 - }; - }; - - const payload = JSON.parse(spec.buildRequests(bidRequest).data); - expect(payload.imp[0]).to.have.property('bidfloor', 1.23); - expect(payload.imp[0]).to.have.property('bidfloorcur', 'EUR'); - }); - it('altered currency, same as in request', function() { - bidRequest[0].params.cur = 'EUR' - bidRequest[0].getFloor = () => { - return { - currency: 'EUR', - floor: 1.23 - }; - }; - - const payload = JSON.parse(spec.buildRequests(bidRequest).data); - expect(payload.imp[0]).to.have.property('bidfloor', 1.23); - expect(payload.imp[0]).to.not.have.property('bidfloorcur'); - }); - - it('bad floor value', function() { - bidRequest[0].getFloor = () => { - return { - currency: 'USD', - floor: 'test' - }; - }; - - const payload = JSON.parse(spec.buildRequests(bidRequest).data); - expect(payload.imp[0]).to.not.have.property('bidfloor'); - expect(payload.imp[0]).to.not.have.property('bidfloorcur'); - }); - - it('empty floor object', function() { - bidRequest[0].getFloor = () => { - return {}; - }; - - const payload = JSON.parse(spec.buildRequests(bidRequest).data); - expect(payload.imp[0]).to.not.have.property('bidfloor'); - expect(payload.imp[0]).to.not.have.property('bidfloorcur'); - }); - - it('undefined floor result', function() { - bidRequest[0].getFloor = () => {}; - - const payload = JSON.parse(spec.buildRequests(bidRequest).data); - expect(payload.imp[0]).to.not.have.property('bidfloor'); - expect(payload.imp[0]).to.not.have.property('bidfloorcur'); - }); - }); -}); diff --git a/test/spec/modules/minutemediaBidAdapter_spec.js b/test/spec/modules/minutemediaBidAdapter_spec.js deleted file mode 100644 index cce08e615a3..00000000000 --- a/test/spec/modules/minutemediaBidAdapter_spec.js +++ /dev/null @@ -1,479 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/minutemediaBidAdapter.js'; -import { newBidder } from 'src/adapters/bidderFactory.js'; -import { config } from 'src/config.js'; -import { BANNER, VIDEO } from '../../../src/mediaTypes.js'; -import * as utils from 'src/utils.js'; - -const ENDPOINT = 'https://hb.minutemedia-prebid.com/hb-mm-multi'; -const TEST_ENDPOINT = 'https://hb.minutemedia-prebid.com/hb-multi-mm-test'; -const TTL = 360; -/* eslint no-console: ["error", { allow: ["log", "warn", "error"] }] */ - -describe('minutemediaAdapter', function () { - const adapter = newBidder(spec); - - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', function () { - const bid = { - 'bidder': spec.code, - 'adUnitCode': 'adunit-code', - 'sizes': [['640', '480']], - 'params': { - 'org': 'jdye8weeyirk00000001' - } - }; - - it('should return true when required params are passed', function () { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when required params are not found', function () { - const newBid = Object.assign({}, bid); - delete newBid.params; - newBid.params = { - 'org': null - }; - expect(spec.isBidRequestValid(newBid)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - const bidRequests = [ - { - 'bidder': spec.code, - 'adUnitCode': 'adunit-code', - 'sizes': [[640, 480]], - 'params': { - 'org': 'jdye8weeyirk00000001' - }, - 'bidId': '299ffc8cca0b87', - 'bidderRequestId': '1144f487e563f9', - 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d', - 'mediaTypes': { - 'video': { - 'playerSize': [[640, 480]], - 'context': 'instream' - } - }, - 'vastXml': '"..."' - }, - { - 'bidder': spec.code, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250]], - 'params': { - 'org': 'jdye8weeyirk00000001' - }, - 'bidId': '299ffc8cca0b87', - 'bidderRequestId': '1144f487e563f9', - 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d', - 'mediaTypes': { - 'banner': { - } - }, - 'ad': '""' - } - ]; - - const testModeBidRequests = [ - { - 'bidder': spec.code, - 'adUnitCode': 'adunit-code', - 'sizes': [[640, 480]], - 'params': { - 'org': 'jdye8weeyirk00000001', - 'testMode': true - }, - 'bidId': '299ffc8cca0b87', - 'bidderRequestId': '1144f487e563f9', - 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d', - } - ]; - - const bidderRequest = { - bidderCode: 'minutemedia', - } - const placementId = '12345678'; - - it('sends the placementId to ENDPOINT via POST', function () { - bidRequests[0].params.placementId = placementId; - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[0].placementId).to.equal(placementId); - }); - - it('sends bid request to ENDPOINT via POST', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.equal(ENDPOINT); - expect(request.method).to.equal('POST'); - }); - - it('sends bid request to TEST ENDPOINT via POST', function () { - const request = spec.buildRequests(testModeBidRequests, bidderRequest); - expect(request.url).to.equal(TEST_ENDPOINT); - expect(request.method).to.equal('POST'); - }); - - it('should send the correct bid Id', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[0].bidId).to.equal('299ffc8cca0b87'); - }); - - it('should send the correct sizes array', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[0].sizes).to.be.an('array'); - expect(request.data.bids[0].sizes).to.equal(bidRequests[0].sizes) - expect(request.data.bids[1].sizes).to.be.an('array'); - expect(request.data.bids[1].sizes).to.equal(bidRequests[1].sizes) - }); - - it('should send the correct media type', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[0].mediaType).to.equal(VIDEO) - expect(request.data.bids[1].mediaType).to.equal(BANNER) - }); - - it('should respect syncEnabled option', function() { - config.setConfig({ - userSync: { - syncEnabled: false, - filterSettings: { - all: { - bidders: '*', - filter: 'include' - } - } - } - }); - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.not.have.property('cs_method'); - }); - - it('should respect "iframe" filter settings', function () { - config.setConfig({ - userSync: { - syncEnabled: true, - filterSettings: { - iframe: { - bidders: [spec.code], - filter: 'include' - } - } - } - }); - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('cs_method', 'iframe'); - }); - - it('should respect "all" filter settings', function () { - config.setConfig({ - userSync: { - syncEnabled: true, - filterSettings: { - all: { - bidders: [spec.code], - filter: 'include' - } - } - } - }); - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('cs_method', 'iframe'); - }); - - it('should send the pixel user sync param if userSync is enabled and no "iframe" or "all" configs are present', function () { - config.resetConfig(); - config.setConfig({ - userSync: { - syncEnabled: true, - } - }); - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('cs_method', 'pixel'); - }); - - it('should respect total exclusion', function() { - config.setConfig({ - userSync: { - syncEnabled: true, - filterSettings: { - image: { - bidders: [spec.code], - filter: 'exclude' - }, - iframe: { - bidders: [spec.code], - filter: 'exclude' - } - } - } - }); - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.not.have.property('cs_method'); - }); - - it('should have us_privacy param if usPrivacy is available in the bidRequest', function () { - const bidderRequestWithUSP = Object.assign({uspConsent: '1YNN'}, bidderRequest); - const request = spec.buildRequests(bidRequests, bidderRequestWithUSP); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('us_privacy', '1YNN'); - }); - - it('should have an empty us_privacy param if usPrivacy is missing in the bidRequest', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.not.have.property('us_privacy'); - }); - - it('should not send the gdpr param if gdprApplies is false in the bidRequest', function () { - const bidderRequestWithGDPR = Object.assign({gdprConsent: {gdprApplies: false}}, bidderRequest); - const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.not.have.property('gdpr'); - expect(request.data.params).to.not.have.property('gdpr_consent'); - }); - - it('should send the gdpr param if gdprApplies is true in the bidRequest', function () { - const bidderRequestWithGDPR = Object.assign({gdprConsent: {gdprApplies: true, consentString: 'test-consent-string'}}, bidderRequest); - const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('gdpr', true); - expect(request.data.params).to.have.property('gdpr_consent', 'test-consent-string'); - }); - - it('should have schain param if it is available in the bidRequest', () => { - const schain = { - ver: '1.0', - complete: 1, - nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], - }; - bidRequests[0].schain = schain; - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('schain', '1.0,1!indirectseller.com,00001,1,,,'); - }); - - it('should set flooPrice to getFloor.floor value if it is greater than params.floorPrice', function() { - const bid = utils.deepClone(bidRequests[0]); - bid.getFloor = () => { - return { - currency: 'USD', - floor: 3.32 - } - } - bid.params.floorPrice = 0.64; - const request = spec.buildRequests([bid], bidderRequest); - expect(request.data.bids[0]).to.be.an('object'); - expect(request.data.bids[0]).to.have.property('floorPrice', 3.32); - }); - - it('should set floorPrice to params.floorPrice value if it is greater than getFloor.floor', function() { - const bid = utils.deepClone(bidRequests[0]); - bid.getFloor = () => { - return { - currency: 'USD', - floor: 0.8 - } - } - bid.params.floorPrice = 1.5; - const request = spec.buildRequests([bid], bidderRequest); - expect(request.data.bids[0]).to.be.an('object'); - expect(request.data.bids[0]).to.have.property('floorPrice', 1.5); - }); - }); - - describe('interpretResponse', function () { - const response = { - params: { - currency: 'USD', - netRevenue: true, - }, - bids: [{ - cpm: 12.5, - vastXml: '', - width: 640, - height: 480, - requestId: '21e12606d47ba7', - adomain: ['abc.com'], - mediaType: VIDEO - }, - { - cpm: 12.5, - ad: '""', - width: 300, - height: 250, - requestId: '21e12606d47ba7', - adomain: ['abc.com'], - mediaType: BANNER - }] - }; - - const expectedVideoResponse = { - requestId: '21e12606d47ba7', - cpm: 12.5, - currency: 'USD', - width: 640, - height: 480, - ttl: TTL, - creativeId: '21e12606d47ba7', - netRevenue: true, - nurl: 'http://example.com/win/1234', - mediaType: VIDEO, - meta: { - mediaType: VIDEO, - advertiserDomains: ['abc.com'] - }, - vastXml: '', - }; - - const expectedBannerResponse = { - requestId: '21e12606d47ba7', - cpm: 12.5, - currency: 'USD', - width: 640, - height: 480, - ttl: TTL, - creativeId: '21e12606d47ba7', - netRevenue: true, - nurl: 'http://example.com/win/1234', - mediaType: BANNER, - meta: { - mediaType: BANNER, - advertiserDomains: ['abc.com'] - }, - ad: '""' - }; - - it('should get correct bid response', function () { - const result = spec.interpretResponse({ body: response }); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedVideoResponse)); - expect(Object.keys(result[1])).to.deep.equal(Object.keys(expectedBannerResponse)); - }); - - it('video type should have vastXml key', function () { - const result = spec.interpretResponse({ body: response }); - expect(result[0].vastXml).to.equal(expectedVideoResponse.vastXml) - }); - - it('banner type should have ad key', function () { - const result = spec.interpretResponse({ body: response }); - expect(result[1].ad).to.equal(expectedBannerResponse.ad) - }); - }) - - describe('getUserSyncs', function() { - const imageSyncResponse = { - body: { - params: { - userSyncPixels: [ - 'https://image-sync-url.test/1', - 'https://image-sync-url.test/2', - 'https://image-sync-url.test/3' - ] - } - } - }; - - const iframeSyncResponse = { - body: { - params: { - userSyncURL: 'https://iframe-sync-url.test' - } - } - }; - - it('should register all img urls from the response', function() { - const syncs = spec.getUserSyncs({ pixelEnabled: true }, [imageSyncResponse]); - expect(syncs).to.deep.equal([ - { - type: 'image', - url: 'https://image-sync-url.test/1' - }, - { - type: 'image', - url: 'https://image-sync-url.test/2' - }, - { - type: 'image', - url: 'https://image-sync-url.test/3' - } - ]); - }); - - it('should register the iframe url from the response', function() { - const syncs = spec.getUserSyncs({ iframeEnabled: true }, [iframeSyncResponse]); - expect(syncs).to.deep.equal([ - { - type: 'iframe', - url: 'https://iframe-sync-url.test' - } - ]); - }); - - it('should register both image and iframe urls from the responses', function() { - const syncs = spec.getUserSyncs({ pixelEnabled: true, iframeEnabled: true }, [iframeSyncResponse, imageSyncResponse]); - expect(syncs).to.deep.equal([ - { - type: 'iframe', - url: 'https://iframe-sync-url.test' - }, - { - type: 'image', - url: 'https://image-sync-url.test/1' - }, - { - type: 'image', - url: 'https://image-sync-url.test/2' - }, - { - type: 'image', - url: 'https://image-sync-url.test/3' - } - ]); - }); - - it('should handle an empty response', function() { - const syncs = spec.getUserSyncs({ iframeEnabled: true }, []); - expect(syncs).to.deep.equal([]); - }); - - it('should handle when user syncs are disabled', function() { - const syncs = spec.getUserSyncs({ pixelEnabled: false }, [imageSyncResponse]); - expect(syncs).to.deep.equal([]); - }); - }) - - describe('onBidWon', function() { - beforeEach(function() { - sinon.stub(utils, 'triggerPixel'); - }); - afterEach(function() { - utils.triggerPixel.restore(); - }); - - it('Should trigger pixel if bid nurl', function() { - const bid = { - 'bidder': spec.code, - 'adUnitCode': 'adunit-code', - 'sizes': [['640', '480']], - 'nurl': 'http://example.com/win/1234', - 'params': { - 'org': 'jdye8weeyirk00000001' - } - }; - - spec.onBidWon(bid); - expect(utils.triggerPixel.callCount).to.equal(1) - }) - }) -}); diff --git a/test/spec/modules/missenaBidAdapter_spec.js b/test/spec/modules/missenaBidAdapter_spec.js deleted file mode 100644 index 86b967cca5b..00000000000 --- a/test/spec/modules/missenaBidAdapter_spec.js +++ /dev/null @@ -1,134 +0,0 @@ -import { expect } from 'chai'; -import { spec, _getPlatform } from 'modules/missenaBidAdapter.js'; -import { newBidder } from 'src/adapters/bidderFactory.js'; - -describe('Missena Adapter', function () { - const adapter = newBidder(spec); - - const bidId = 'abc'; - - const bid = { - bidder: 'missena', - bidId: bidId, - sizes: [[1, 1]], - params: { - apiKey: 'PA-34745704', - }, - }; - - describe('codes', function () { - it('should return a bidder code of missena', function () { - expect(spec.code).to.equal('missena'); - }); - }); - - describe('isBidRequestValid', function () { - it('should return true if the apiKey param is present', function () { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false if the apiKey is missing', function () { - expect( - spec.isBidRequestValid(Object.assign(bid, { params: {} })) - ).to.equal(false); - }); - - it('should return false if the apiKey is an empty string', function () { - expect( - spec.isBidRequestValid(Object.assign(bid, { params: { apiKey: '' } })) - ).to.equal(false); - }); - }); - - describe('buildRequests', function () { - const consentString = 'AAAAAAAAA=='; - - const bidderRequest = { - gdprConsent: { - consentString: consentString, - gdprApplies: true, - }, - refererInfo: { - referer: 'https://referer', - canonicalUrl: 'https://canonical', - }, - }; - - const requests = spec.buildRequests([bid, bid], bidderRequest); - const request = requests[0]; - const payload = JSON.parse(request.data); - - it('should return as many server requests as bidder requests', function () { - expect(requests.length).to.equal(2); - }); - - it('should have a post method', function () { - expect(request.method).to.equal('POST'); - }); - - it('should send the bidder id', function () { - expect(payload.request_id).to.equal(bidId); - }); - - it('should send referer information to the request', function () { - expect(payload.referer).to.equal('https://referer'); - expect(payload.referer_canonical).to.equal('https://canonical'); - }); - - it('should send gdpr consent information to the request', function () { - expect(payload.consent_string).to.equal(consentString); - expect(payload.consent_required).to.equal(true); - }); - }); - - describe('interpretResponse', function () { - const serverResponse = { - requestId: bidId, - cpm: 0.5, - currency: 'USD', - ad: '', - meta: { - advertiserDomains: ['missena.com'] - }, - }; - - const serverTimeoutResponse = { - requestId: bidId, - timeout: true, - ad: '', - }; - - const serverEmptyAdResponse = { - requestId: bidId, - cpm: 0.5, - currency: 'USD', - ad: '', - }; - - it('should return a proper bid response', function () { - const result = spec.interpretResponse({ body: serverResponse }, bid); - - expect(result.length).to.equal(1); - - expect(Object.keys(result[0])).to.have.members( - Object.keys(serverResponse) - ); - }); - - it('should return an empty response when the server answers with a timeout', function () { - const result = spec.interpretResponse( - { body: serverTimeoutResponse }, - bid - ); - expect(result).to.deep.equal([]); - }); - - it('should return an empty response when the server answers with an empty ad', function () { - const result = spec.interpretResponse( - { body: serverEmptyAdResponse }, - bid - ); - expect(result).to.deep.equal([]); - }); - }); -}); diff --git a/test/spec/modules/mobfoxpbBidAdapter_spec.js b/test/spec/modules/mobfoxpbBidAdapter_spec.js deleted file mode 100644 index 766f8d1a848..00000000000 --- a/test/spec/modules/mobfoxpbBidAdapter_spec.js +++ /dev/null @@ -1,307 +0,0 @@ -import {expect} from 'chai'; -import {spec} from '../../../modules/mobfoxpbBidAdapter.js'; -import { BANNER, VIDEO, NATIVE } from '../../../src/mediaTypes.js'; - -describe('MobfoxHBBidAdapter', function () { - const bid = { - bidId: '23fhj33i987f', - bidder: 'mobfoxpb', - mediaTypes: { - [BANNER]: { - sizes: [[300, 250]] - } - }, - params: { - placementId: 783, - traffic: BANNER - } - }; - - const bidderRequest = { - refererInfo: { - referer: 'test.com' - } - }; - - describe('isBidRequestValid', function () { - it('Should return true if there are bidId, params and key parameters present', function () { - expect(spec.isBidRequestValid(bid)).to.be.true; - }); - it('Should return false if at least one of parameters is not present', function () { - delete bid.params.placementId; - expect(spec.isBidRequestValid(bid)).to.be.false; - }); - }); - - describe('buildRequests', function () { - let serverRequest = spec.buildRequests([bid], bidderRequest); - it('Creates a ServerRequest object with method, URL and data', function () { - expect(serverRequest).to.exist; - expect(serverRequest.method).to.exist; - expect(serverRequest.url).to.exist; - expect(serverRequest.data).to.exist; - }); - it('Returns POST method', function () { - expect(serverRequest.method).to.equal('POST'); - }); - it('Returns valid URL', function () { - expect(serverRequest.url).to.equal('https://bes.mobfox.com/pbjs'); - }); - it('Returns valid data if array of bids is valid', function () { - let data = serverRequest.data; - expect(data).to.be.an('object'); - expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements'); - expect(data.deviceWidth).to.be.a('number'); - expect(data.deviceHeight).to.be.a('number'); - expect(data.language).to.be.a('string'); - expect(data.secure).to.be.within(0, 1); - expect(data.host).to.be.a('string'); - expect(data.page).to.be.a('string'); - expect(data.gdpr).to.not.exist; - expect(data.ccpa).to.not.exist; - let placement = data['placements'][0]; - expect(placement).to.have.keys('placementId', 'bidId', 'traffic', 'sizes', 'schain', 'bidfloor'); - expect(placement.placementId).to.equal(783); - expect(placement.bidId).to.equal('23fhj33i987f'); - expect(placement.traffic).to.equal(BANNER); - expect(placement.schain).to.be.an('object'); - expect(placement.sizes).to.be.an('array'); - expect(placement.bidfloor).to.equal(0); - }); - - it('Returns valid data for mediatype video', function () { - const playerSize = [300, 300]; - bid.mediaTypes = {}; - bid.params.traffic = VIDEO; - bid.mediaTypes[VIDEO] = { - playerSize - }; - serverRequest = spec.buildRequests([bid], bidderRequest); - let data = serverRequest.data; - expect(data).to.be.an('object'); - let placement = data['placements'][0]; - expect(placement).to.be.an('object'); - expect(placement).to.have.keys('placementId', 'bidId', 'traffic', 'playerSize', 'wPlayer', 'hPlayer', 'schain', 'bidfloor', - 'minduration', 'maxduration', 'mimes', 'protocols', 'startdelay', 'placement', - 'skip', 'skipafter', 'minbitrate', 'maxbitrate', 'delivery', 'playbackmethod', 'api', 'linearity'); - expect(placement.traffic).to.equal(VIDEO); - expect(placement.wPlayer).to.equal(playerSize[0]); - expect(placement.hPlayer).to.equal(playerSize[1]); - }); - - it('Returns valid data for mediatype native', function () { - const native = { - title: { - required: true - }, - body: { - required: true - }, - icon: { - required: true, - size: [64, 64] - } - }; - - bid.mediaTypes = {}; - bid.params.traffic = NATIVE; - bid.mediaTypes[NATIVE] = native; - serverRequest = spec.buildRequests([bid], bidderRequest); - let data = serverRequest.data; - expect(data).to.be.an('object'); - let placement = data['placements'][0]; - expect(placement).to.be.an('object'); - expect(placement).to.have.keys('placementId', 'bidId', 'traffic', 'native', 'schain', 'bidfloor'); - expect(placement.traffic).to.equal(NATIVE); - expect(placement.native).to.equal(native); - }); - - it('Returns data with gdprConsent and without uspConsent', function () { - bidderRequest.gdprConsent = 'test'; - serverRequest = spec.buildRequests([bid], bidderRequest); - let data = serverRequest.data; - expect(data.gdpr).to.exist; - expect(data.gdpr).to.be.a('string'); - expect(data.gdpr).to.equal(bidderRequest.gdprConsent); - expect(data.ccpa).to.not.exist; - delete bidderRequest.gdprConsent; - }); - - it('Returns data with uspConsent and without gdprConsent', function () { - bidderRequest.uspConsent = 'test'; - serverRequest = spec.buildRequests([bid], bidderRequest); - let data = serverRequest.data; - expect(data.ccpa).to.exist; - expect(data.ccpa).to.be.a('string'); - expect(data.ccpa).to.equal(bidderRequest.uspConsent); - expect(data.gdpr).to.not.exist; - }); - - it('Returns empty data if no valid requests are passed', function () { - serverRequest = spec.buildRequests([]); - let data = serverRequest.data; - expect(data.placements).to.be.an('array').that.is.empty; - }); - }); - describe('interpretResponse', function () { - it('Should interpret banner response', function () { - const banner = { - body: [{ - mediaType: 'banner', - width: 300, - height: 250, - cpm: 0.4, - ad: 'Test', - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - let bannerResponses = spec.interpretResponse(banner); - expect(bannerResponses).to.be.an('array').that.is.not.empty; - let dataItem = bannerResponses[0]; - expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', - 'netRevenue', 'currency', 'dealId', 'mediaType', 'meta'); - expect(dataItem.requestId).to.equal('23fhj33i987f'); - expect(dataItem.cpm).to.equal(0.4); - expect(dataItem.width).to.equal(300); - expect(dataItem.height).to.equal(250); - expect(dataItem.ad).to.equal('Test'); - expect(dataItem.ttl).to.equal(120); - expect(dataItem.creativeId).to.equal('2'); - expect(dataItem.netRevenue).to.be.true; - expect(dataItem.currency).to.equal('USD'); - }); - it('Should interpret video response', function () { - const video = { - body: [{ - vastUrl: 'test.com', - mediaType: 'video', - cpm: 0.5, - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - let videoResponses = spec.interpretResponse(video); - expect(videoResponses).to.be.an('array').that.is.not.empty; - - let dataItem = videoResponses[0]; - expect(dataItem).to.have.all.keys('requestId', 'cpm', 'vastUrl', 'ttl', 'creativeId', - 'netRevenue', 'currency', 'dealId', 'mediaType', 'meta'); - expect(dataItem.requestId).to.equal('23fhj33i987f'); - expect(dataItem.cpm).to.equal(0.5); - expect(dataItem.vastUrl).to.equal('test.com'); - expect(dataItem.ttl).to.equal(120); - expect(dataItem.creativeId).to.equal('2'); - expect(dataItem.netRevenue).to.be.true; - expect(dataItem.currency).to.equal('USD'); - }); - it('Should interpret native response', function () { - const native = { - body: [{ - mediaType: 'native', - native: { - clickUrl: 'test.com', - title: 'Test', - image: 'test.com', - impressionTrackers: ['test.com'], - }, - ttl: 120, - cpm: 0.4, - requestId: '23fhj33i987f', - creativeId: '2', - netRevenue: true, - currency: 'USD', - }] - }; - let nativeResponses = spec.interpretResponse(native); - expect(nativeResponses).to.be.an('array').that.is.not.empty; - - let dataItem = nativeResponses[0]; - expect(dataItem).to.have.keys('requestId', 'cpm', 'ttl', 'creativeId', 'netRevenue', 'currency', 'mediaType', 'native', 'meta'); - expect(dataItem.native).to.have.keys('clickUrl', 'impressionTrackers', 'title', 'image') - expect(dataItem.requestId).to.equal('23fhj33i987f'); - expect(dataItem.cpm).to.equal(0.4); - expect(dataItem.native.clickUrl).to.equal('test.com'); - expect(dataItem.native.title).to.equal('Test'); - expect(dataItem.native.image).to.equal('test.com'); - expect(dataItem.native.impressionTrackers).to.be.an('array').that.is.not.empty; - expect(dataItem.native.impressionTrackers[0]).to.equal('test.com'); - expect(dataItem.ttl).to.equal(120); - expect(dataItem.creativeId).to.equal('2'); - expect(dataItem.netRevenue).to.be.true; - expect(dataItem.currency).to.equal('USD'); - }); - it('Should return an empty array if invalid banner response is passed', function () { - const invBanner = { - body: [{ - width: 300, - cpm: 0.4, - ad: 'Test', - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - - let serverResponses = spec.interpretResponse(invBanner); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - it('Should return an empty array if invalid video response is passed', function () { - const invVideo = { - body: [{ - mediaType: 'video', - cpm: 0.5, - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - let serverResponses = spec.interpretResponse(invVideo); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - it('Should return an empty array if invalid native response is passed', function () { - const invNative = { - body: [{ - mediaType: 'native', - clickUrl: 'test.com', - title: 'Test', - impressionTrackers: ['test.com'], - ttl: 120, - requestId: '23fhj33i987f', - creativeId: '2', - netRevenue: true, - currency: 'USD', - }] - }; - let serverResponses = spec.interpretResponse(invNative); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - it('Should return an empty array if invalid response is passed', function () { - const invalid = { - body: [{ - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - let serverResponses = spec.interpretResponse(invalid); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - }); -}); diff --git a/test/spec/modules/multibid_spec.js b/test/spec/modules/multibid_spec.js index eaf8fa33a66..e849392ee4b 100644 --- a/test/spec/modules/multibid_spec.js +++ b/test/spec/modules/multibid_spec.js @@ -11,6 +11,7 @@ import { import {parse as parseQuery} from 'querystring'; import {config} from 'src/config.js'; import * as utils from 'src/utils.js'; +import find from 'core-js-pure/features/array/find.js'; describe('multibid adapter', function () { let bidArray = [{ @@ -81,7 +82,7 @@ describe('multibid adapter', function () { 'sizes': [[300, 250]] } }, - 'adUnitCode': 'test.div', + 'adUnitCode': 'test-div', 'transactionId': 'c153f3da-84f0-4be8-95cb-0647c458bc60', 'sizes': [[300, 250]], 'bidId': '2408ef83b84c9d', @@ -105,7 +106,7 @@ describe('multibid adapter', function () { 'sizes': [[300, 250]] } }, - 'adUnitCode': 'test.div', + 'adUnitCode': 'test-div', 'transactionId': 'c153f3da-84f0-4be8-95cb-0647c458bc60', 'sizes': [[300, 250]], 'bidId': '2408ef83b84c9d', @@ -196,14 +197,14 @@ describe('multibid adapter', function () { }); it('adds original bids and does not modify', function () { - let adUnitCode = 'test.div'; + let adUnitCode = 'test-div'; let bids = [{...bidArray[0]}, {...bidArray[1]}]; addBidResponseHook(callbackFn, adUnitCode, {...bids[0]}); expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[0]); @@ -213,13 +214,13 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[1]); }); it('modifies and adds both bids based on multibid configuration', function () { - let adUnitCode = 'test.div'; + let adUnitCode = 'test-div'; let bids = [{...bidArray[0]}, {...bidArray[1]}]; config.setConfig({multibid: [{bidder: 'bidderA', maxBids: 2, targetBiddercodePrefix: 'bidA'}]}); @@ -231,7 +232,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[0]); @@ -249,13 +250,13 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[1]); }); it('only modifies bids defined in the multibid configuration', function () { - let adUnitCode = 'test.div'; + let adUnitCode = 'test-div'; let bids = [{...bidArray[0]}, {...bidArray[1]}]; bids.push({ @@ -275,7 +276,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[0]); @@ -291,7 +292,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[1]); @@ -301,13 +302,13 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[2]); }); it('only modifies and returns bids under limit for a specifc bidder in the multibid configuration', function () { - let adUnitCode = 'test.div'; + let adUnitCode = 'test-div'; let bids = [{...bidArray[0]}, {...bidArray[1]}]; bids.push({ @@ -327,7 +328,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[0]); @@ -343,7 +344,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[1]); @@ -355,7 +356,7 @@ describe('multibid adapter', function () { }); it('if no prefix in multibid configuration, modifies and returns bids under limit without preifx property', function () { - let adUnitCode = 'test.div'; + let adUnitCode = 'test-div'; let bids = [{...bidArray[0]}, {...bidArray[1]}]; bids.push({ @@ -374,7 +375,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[0]); @@ -388,7 +389,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid).to.deep.equal(bids[1]); @@ -400,7 +401,7 @@ describe('multibid adapter', function () { }); it('does not include extra bids if cpm is less than floor value', function () { - let adUnitCode = 'test.div'; + let adUnitCode = 'test-div'; let bids = [{...bidArrayAlt[1]}, {...bidArrayAlt[0]}, {...bidArrayAlt[2]}, {...bidArrayAlt[3]}]; bids.map(bid => { @@ -417,7 +418,7 @@ describe('multibid adapter', function () { floorRuleValue: 65, floorValue: 65, matchedFields: { - gptSlot: 'test.div', + gptSlot: 'test-div', mediaType: 'banner' } } @@ -434,7 +435,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid.bidder).to.equal('bidderA'); expect(result.bid.targetingBidder).to.equal(undefined); @@ -451,7 +452,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid.bidder).to.equal('bidderB'); expect(result.bid.targetingBidder).to.equal(undefined); @@ -462,14 +463,14 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid.bidder).to.equal('bidderC'); expect(result.bid.targetingBidder).to.equal(undefined); }); it('does include extra bids if cpm is not less than floor value', function () { - let adUnitCode = 'test.div'; + let adUnitCode = 'test-div'; let bids = [{...bidArrayAlt[1]}, {...bidArrayAlt[0]}]; bids.map(bid => { @@ -486,7 +487,7 @@ describe('multibid adapter', function () { floorRuleValue: 25, floorValue: 25, matchedFields: { - gptSlot: 'test.div', + gptSlot: 'test-div', mediaType: 'banner' } } @@ -503,7 +504,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid.bidder).to.equal('bidderA'); expect(result.bid.targetingBidder).to.equal(undefined); @@ -517,7 +518,7 @@ describe('multibid adapter', function () { expect(result).to.not.equal(null); expect(result.adUnitCode).to.not.equal(null); - expect(result.adUnitCode).to.equal('test.div'); + expect(result.adUnitCode).to.equal('test-div'); expect(result.bid).to.not.equal(null); expect(result.bid.bidder).to.equal('bidderA'); expect(result.bid.targetingBidder).to.equal('bidA2'); @@ -577,7 +578,7 @@ describe('multibid adapter', function () { it('it sorts and creates dynamic alias on bidsReceived if multibid configuration found with prefix', function () { let modifiedBids = [{...bidArray[1]}, {...bidArray[0]}].map(bid => { - addBidResponseHook(bidResponseCallback, 'test.div', {...bid}); + addBidResponseHook(bidResponseCallback, 'test-div', {...bid}); return bidResult; }); @@ -602,7 +603,7 @@ describe('multibid adapter', function () { it('it sorts by cpm treating dynamic alias as unique bid when no bid limit defined', function () { let modifiedBids = [{...bidArrayAlt[0]}, {...bidArrayAlt[2]}, {...bidArrayAlt[3]}, {...bidArrayAlt[1]}].map(bid => { - addBidResponseHook(bidResponseCallback, 'test.div', {...bid}); + addBidResponseHook(bidResponseCallback, 'test-div', {...bid}); return bidResult; }); @@ -635,7 +636,7 @@ describe('multibid adapter', function () { it('it should filter out dynamic bid when bid limit is less than unique bid pool', function () { let modifiedBids = [{...bidArrayAlt[0]}, {...bidArrayAlt[2]}, {...bidArrayAlt[3]}, {...bidArrayAlt[1]}].map(bid => { - addBidResponseHook(bidResponseCallback, 'test.div', {...bid}); + addBidResponseHook(bidResponseCallback, 'test-div', {...bid}); return bidResult; }); @@ -661,7 +662,7 @@ describe('multibid adapter', function () { config.setConfig({ multibid: [{bidder: 'bidderA', maxBids: 2, targetBiddercodePrefix: 'bidA'}] }); let modifiedBids = [{...bidArrayAlt[0]}, {...bidArrayAlt[2]}, {...bidArrayAlt[3]}, {...bidArrayAlt[1]}].map(bid => { - addBidResponseHook(bidResponseCallback, 'test.div', {...bid}); + addBidResponseHook(bidResponseCallback, 'test-div', {...bid}); return bidResult; }); diff --git a/test/spec/modules/mytargetBidAdapter_spec.js b/test/spec/modules/mytargetBidAdapter_spec.js deleted file mode 100644 index 62d139bb926..00000000000 --- a/test/spec/modules/mytargetBidAdapter_spec.js +++ /dev/null @@ -1,199 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/mytargetBidAdapter'; - -describe('MyTarget Adapter', function() { - describe('isBidRequestValid', function () { - it('should return true when required params found', function () { - let validBid = { - bidder: 'mytarget', - params: { - placementId: '1' - } - }; - - expect(spec.isBidRequestValid(validBid)).to.equal(true); - }); - - it('should return false for when required params are not passed', function () { - let invalidBid = { - bidder: 'mytarget', - params: {} - }; - - expect(spec.isBidRequestValid(invalidBid)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - let bidRequests = [ - { - bidId: 'bid1', - bidder: 'mytarget', - params: { - placementId: '1' - } - }, - { - bidId: 'bid2', - bidder: 'mytarget', - params: { - placementId: '2', - position: 1, - response: 1, - bidfloor: 10000 - } - } - ]; - let bidderRequest = { - refererInfo: { - referer: 'https://example.com?param=value' - } - }; - - let bidRequest = spec.buildRequests(bidRequests, bidderRequest); - - it('should build single POST request for multiple bids', function() { - expect(bidRequest.method).to.equal('POST'); - expect(bidRequest.url).to.equal('//ad.mail.ru/hbid_prebid/'); - expect(bidRequest.data).to.be.an('object'); - expect(bidRequest.data.places).to.be.an('array'); - expect(bidRequest.data.places).to.have.lengthOf(2); - }); - - it('should pass bid parameters', function() { - let place1 = bidRequest.data.places[0]; - let place2 = bidRequest.data.places[1]; - - expect(place1.placementId).to.equal('1'); - expect(place2.placementId).to.equal('2'); - expect(place1.id).to.equal('bid1'); - expect(place2.id).to.equal('bid2'); - }); - - it('should pass default position and response type', function() { - let place = bidRequest.data.places[0]; - - expect(place.position).to.equal(0); - expect(place.response).to.equal(0); - }); - - it('should pass provided position and response type', function() { - let place = bidRequest.data.places[1]; - - expect(place.position).to.equal(1); - expect(place.response).to.equal(1); - }); - - it('should not pass default bidfloor', function() { - let place = bidRequest.data.places[0]; - - expect(place.bidfloor).not.to.exist; - }); - - it('should not pass provided bidfloor', function() { - let place = bidRequest.data.places[1]; - - expect(place.bidfloor).to.exist; - expect(place.bidfloor).to.equal(10000); - }); - - it('should pass site parameters', function() { - let site = bidRequest.data.site; - - expect(site).to.be.an('object'); - expect(site.sitename).to.equal('example.com'); - expect(site.page).to.equal('https://example.com?param=value'); - }); - - it('should pass settings', function() { - let settings = bidRequest.data.settings; - - expect(settings).to.be.an('object'); - expect(settings.currency).to.equal('RUB'); - expect(settings.windowSize).to.be.an('object'); - expect(settings.windowSize.width).to.equal(window.screen.width); - expect(settings.windowSize.height).to.equal(window.screen.height); - }); - }); - - describe('interpretResponse', function () { - let serverResponse = { - body: { - 'bidder_status': - [ - { - 'bidder': 'mail.ru', - 'response_time_ms': 100, - 'num_bids': 2 - } - ], - 'bids': - [ - { - 'displayUrl': 'https://ad.mail.ru/hbid_imp/12345', - 'size': - { - 'height': '400', - 'width': '240' - }, - 'id': '1', - 'currency': 'RUB', - 'price': 100, - 'ttl': 360, - 'creativeId': '123456' - }, - { - 'adm': '

Ad

', - 'size': - { - 'height': '250', - 'width': '300' - }, - 'id': '2', - 'price': 200 - } - ] - } - }; - - let bids = spec.interpretResponse(serverResponse); - - it('should return empty array for response with no bids', function() { - let emptyBids = spec.interpretResponse({ body: {} }); - - expect(emptyBids).to.have.lengthOf(0); - }); - - it('should parse all bids from response', function() { - expect(bids).to.have.lengthOf(2); - }); - - it('should parse bid with ad url', function() { - expect(bids[0].requestId).to.equal('1'); - expect(bids[0].cpm).to.equal(100); - expect(bids[0].width).to.equal('240'); - expect(bids[0].height).to.equal('400'); - expect(bids[0].ttl).to.equal(360); - expect(bids[0].currency).to.equal('RUB'); - expect(bids[0]).to.have.property('creativeId'); - expect(bids[0].creativeId).to.equal('123456'); - expect(bids[0].netRevenue).to.equal(true); - expect(bids[0].adUrl).to.equal('https://ad.mail.ru/hbid_imp/12345'); - expect(bids[0]).to.not.have.property('ad'); - }); - - it('should parse bid with ad markup', function() { - expect(bids[1].requestId).to.equal('2'); - expect(bids[1].cpm).to.equal(200); - expect(bids[1].width).to.equal('300'); - expect(bids[1].height).to.equal('250'); - expect(bids[1].ttl).to.equal(180); - expect(bids[1].currency).to.equal('RUB'); - expect(bids[1]).to.have.property('creativeId'); - expect(bids[1].creativeId).not.to.equal('123456'); - expect(bids[1].netRevenue).to.equal(true); - expect(bids[1].ad).to.equal('

Ad

'); - expect(bids[1]).to.not.have.property('adUrl'); - }); - }); -}); diff --git a/test/spec/modules/nativoBidAdapter_spec.js b/test/spec/modules/nativoBidAdapter_spec.js index c552090cf6e..4202b7c6f91 100644 --- a/test/spec/modules/nativoBidAdapter_spec.js +++ b/test/spec/modules/nativoBidAdapter_spec.js @@ -1,49 +1,36 @@ import { expect } from 'chai' import { spec } from 'modules/nativoBidAdapter.js' +// import { newBidder } from 'src/adapters/bidderFactory.js' +// import * as bidderFactory from 'src/adapters/bidderFactory.js' +// import { deepClone } from 'src/utils.js' +// import { config } from 'src/config.js' describe('nativoBidAdapterTests', function () { describe('isBidRequestValid', function () { let bid = { bidder: 'nativo', - } - - it('should return true if no params found', function () { - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) - - it('should return true for valid placementId value', function () { - bid.params = { + params: { placementId: '10433394', - } - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) - - it('should return true for valid placementId value', function () { - bid.params = { - placementId: 10433394, - } - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) - - it('should return false for invalid placementId value', function () { - bid.params = { - placementId: true, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) + }, + adUnitCode: 'adunit-code', + sizes: [ + [300, 250], + [300, 600], + ], + bidId: '27b02036ccfa6e', + bidderRequestId: '1372cd8bd8d6a8', + auctionId: 'cfc467e4-2707-48da-becb-bcaab0b2c114', + } - it('should return true for valid placementId value', function () { - bid.params = { - url: 'www.test.com', - } + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true) }) - it('should return false for invalid placementId value', function () { - bid.params = { - url: 4567890, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) + it('should return false when required params are not passed', function () { + let bid2 = Object.assign({}, bid) + delete bid2.params + bid2.params = {} + expect(spec.isBidRequestValid(bid2)).to.equal(false) }) }) @@ -142,12 +129,7 @@ describe('interpretResponse', function () { } // mock - spec.getAdUnitData = () => { - return { - bidId: 123456, - sizes: [300, 250], - } - } + spec.getRequestId = () => 123456 let result = spec.interpretResponse({ body: response }, { bidderRequest }) expect(Object.keys(result[0])).to.have.deep.members( @@ -250,192 +232,3 @@ describe('getUserSyncs', function () { ) }) }) - -describe('getAdUnitData', () => { - afterEach(() => { - if (window.bidRequestMap) delete window.bidRequestMap - }) - - it('Matches placementId value', () => { - const adUnitData = { - bidId: 123456, - sizes: [300, 250], - } - - window.bidRequestMap = { - 9876543: { - 12345: adUnitData, - }, - } - - const data = spec.getAdUnitData(9876543, { impid: 12345 }) - expect(Object.keys(data)).to.have.deep.members(Object.keys(adUnitData)) - }) - - it('Falls back to ad unit code value', () => { - const adUnitData = { - bidId: 123456, - sizes: [300, 250], - } - - window.bidRequestMap = { - 9876543: { - '#test-code': adUnitData, - }, - } - - const data = spec.getAdUnitData(9876543, { - impid: 12345, - ext: { ad_unit_code: '#test-code' }, - }) - expect(Object.keys(data)).to.have.deep.members(Object.keys(adUnitData)) - }) -}) - -describe('Response to Request Filter Flow', () => { - let bidRequests = [ - { - bidder: 'nativo', - params: { - placementId: '10433394', - }, - adUnitCode: 'adunit-code', - sizes: [ - [300, 250], - [300, 600], - ], - bidId: '27b02036ccfa6e', - bidderRequestId: '1372cd8bd8d6a8', - auctionId: 'cfc467e4-2707-48da-becb-bcaab0b2c114', - transactionId: '3b36e7e0-0c3e-4006-a279-a741239154ff', - }, - ] - - let response - - beforeEach(() => { - response = { - id: '126456', - seatbid: [ - { - seat: 'seat_0', - bid: [ - { - id: 'f70362ac-f3cf-4225-82a5-948b690927a6', - impid: '1', - price: 3.569, - adm: '', - h: 300, - w: 250, - cat: [], - adomain: ['test.com'], - crid: '1060_72_6760217', - }, - ], - }, - ], - cur: 'USD', - } - }) - - let bidderRequest = { - id: 123456, - bids: [ - { - params: { - placementId: 1, - }, - }, - ], - } - - // mock - spec.getAdUnitData = () => { - return { - bidId: 123456, - size: [300, 250], - } - } - - it('Appends NO filter based on previous response', () => { - // Getting the mock response - let result = spec.interpretResponse({ body: response }, { bidderRequest }) - - // Winning the bid - spec.onBidWon(result[0]) - - // Making another request - const request = spec.buildRequests(bidRequests, { - bidderRequestId: 123456, - refererInfo: { - referer: 'https://www.test.com', - }, - }) - expect(request.url).to.not.include('ntv_aft') - expect(request.url).to.not.include('ntv_avtf') - expect(request.url).to.not.include('ntv_ctf') - }) - - it('Appends Ads filter based on previous response', () => { - response.seatbid[0].bid[0].ext = { adsToFilter: ['12345'] } - - // Getting the mock response - let result = spec.interpretResponse({ body: response }, { bidderRequest }) - - // Winning the bid - spec.onBidWon(result[0]) - - // Making another request - const request = spec.buildRequests(bidRequests, { - bidderRequestId: 123456, - refererInfo: { - referer: 'https://www.test.com', - }, - }) - expect(request.url).to.include(`ntv_atf=12345`) - expect(request.url).to.not.include('ntv_avtf') - expect(request.url).to.not.include('ntv_ctf') - }) - - it('Appends Advertiser filter based on previous response', () => { - response.seatbid[0].bid[0].ext = { advertisersToFilter: ['1'] } - - // Getting the mock response - let result = spec.interpretResponse({ body: response }, { bidderRequest }) - - // Winning the bid - spec.onBidWon(result[0]) - - // Making another request - const request = spec.buildRequests(bidRequests, { - bidderRequestId: 123456, - refererInfo: { - referer: 'https://www.test.com', - }, - }) - expect(request.url).to.include(`ntv_atf=12345`) - expect(request.url).to.include('ntv_avtf=1') - expect(request.url).to.not.include('ntv_ctf') - }) - - it('Appends Campaign filter based on previous response', () => { - response.seatbid[0].bid[0].ext = { campaignsToFilter: ['234'] } - - // Getting the mock response - let result = spec.interpretResponse({ body: response }, { bidderRequest }) - - // Winning the bid - spec.onBidWon(result[0]) - - // Making another request - const request = spec.buildRequests(bidRequests, { - bidderRequestId: 123456, - refererInfo: { - referer: 'https://www.test.com', - }, - }) - expect(request.url).to.include(`ntv_atf=12345`) - expect(request.url).to.include('ntv_avtf=1') - expect(request.url).to.include('ntv_ctf=234') - }) -}) diff --git a/test/spec/modules/naveggIdSystem_spec.js b/test/spec/modules/naveggIdSystem_spec.js deleted file mode 100644 index c0973a05372..00000000000 --- a/test/spec/modules/naveggIdSystem_spec.js +++ /dev/null @@ -1,21 +0,0 @@ -import { naveggIdSubmodule, storage } from 'modules/naveggIdSystem.js'; - -describe('naveggId', function () { - it('should NOT find navegg id', function () { - let id = naveggIdSubmodule.getId(); - - expect(id).to.be.undefined; - }); - - it('getId() should return "test-nid" id from cookie OLD_NAVEGG_ID', function() { - sinon.stub(storage, 'getCookie').withArgs('nid').returns('test-nid'); - let id = naveggIdSubmodule.getId(); - expect(id).to.be.deep.equal({id: 'test-nid'}) - }) - - it('getId() should return "test-nvggid" id from local storage NAVEGG_ID', function() { - sinon.stub(storage, 'getDataFromLocalStorage').withArgs('nvggid').returns('test-ninvggidd'); - let id = naveggIdSubmodule.getId(); - expect(id).to.be.deep.equal({id: 'test-ninvggidd'}) - }) -}); diff --git a/test/spec/modules/nextMillenniumBidAdapter_spec.js b/test/spec/modules/nextMillenniumBidAdapter_spec.js index a8aa62f24d1..15256d6c382 100644 --- a/test/spec/modules/nextMillenniumBidAdapter_spec.js +++ b/test/spec/modules/nextMillenniumBidAdapter_spec.js @@ -4,108 +4,20 @@ import { spec } from 'modules/nextMillenniumBidAdapter.js'; describe('nextMillenniumBidAdapterTests', function() { const bidRequestData = [ { - adUnitCode: 'test-div', bidId: 'bid1234', auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', bidder: 'nextMillennium', params: { placement_id: '-1' }, - sizes: [[300, 250]], - uspConsent: '1---', - gdprConsent: { - consentString: 'kjfdniwjnifwenrif3', - gdprApplies: true - } + sizes: [[300, 250]] } ]; - const bidRequestDataGI = [ - { - adUnitCode: 'test-banner-gi', - bidId: 'bid1234', - auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', - bidder: 'nextMillennium', - params: { group_id: '1234' }, - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - - sizes: [[300, 250]], - uspConsent: '1---', - gdprConsent: { - consentString: 'kjfdniwjnifwenrif3', - gdprApplies: true - } - }, - - { - adUnitCode: 'test-video-gi', - bidId: 'bid1234', - auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', - bidder: 'nextMillennium', - params: { group_id: '1234' }, - mediaTypes: { - video: { - playerSize: [640, 480], - } - }, - - uspConsent: '1---', - gdprConsent: { - consentString: 'kjfdniwjnifwenrif3', - gdprApplies: true - } - }, - ]; - - it('Request params check with GDPR and USP Consent', function () { - const request = spec.buildRequests(bidRequestData, bidRequestData[0]); - expect(JSON.parse(request[0].data).user.ext.consent).to.equal('kjfdniwjnifwenrif3'); - expect(JSON.parse(request[0].data).regs.ext.us_privacy).to.equal('1---'); - expect(JSON.parse(request[0].data).regs.ext.gdpr).to.equal(1); - }); - - it('Request params check without GDPR Consent', function () { - delete bidRequestData[0].gdprConsent - const request = spec.buildRequests(bidRequestData, bidRequestData[0]); - expect(JSON.parse(request[0].data).regs.ext.gdpr).to.be.undefined; - expect(JSON.parse(request[0].data).regs.ext.us_privacy).to.equal('1---'); - }); - it('validate_generated_params', function() { const request = spec.buildRequests(bidRequestData); expect(request[0].bidId).to.equal('bid1234'); expect(JSON.parse(request[0].data).id).to.equal('b06c5141-fe8f-4cdf-9d7d-54415490a917'); }); - it('use parameters group_id', function() { - for (let test of bidRequestDataGI) { - const request = spec.buildRequests([test]); - const requestData = JSON.parse(request[0].data); - const storeRequestId = requestData.ext.prebid.storedrequest.id; - const templateRE = /^g\d+;\d+x\d+;/; - expect(templateRE.test(storeRequestId)).to.be.true; - }; - }); - - it('Check if refresh_count param is incremented', function() { - const request = spec.buildRequests(bidRequestData); - expect(JSON.parse(request[0].data).ext.nextMillennium.refresh_count).to.equal(3); - }); - - it('Test getUserSyncs function', function () { - const syncOptions = { - 'iframeEnabled': true - } - const userSync = spec.getUserSyncs(syncOptions); - expect(userSync).to.be.an('array').with.lengthOf(1); - expect(userSync[0].type).to.exist; - expect(userSync[0].url).to.exist; - expect(userSync[0].type).to.be.equal('iframe'); - expect(userSync[0].url).to.be.equal('https://statics.nextmillmedia.com/load-cookie.html?v=4'); - }); - it('validate_response_params', function() { const serverResponse = { body: { diff --git a/test/spec/modules/nextrollBidAdapter_spec.js b/test/spec/modules/nextrollBidAdapter_spec.js deleted file mode 100644 index d4779120248..00000000000 --- a/test/spec/modules/nextrollBidAdapter_spec.js +++ /dev/null @@ -1,290 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/nextrollBidAdapter.js'; -import * as utils from 'src/utils.js'; -import { deepClone } from '../../../src/utils'; - -describe('nextrollBidAdapter', function() { - let utilsMock; - beforeEach(function () { - utilsMock = sinon.mock(utils); - }); - - afterEach(function() { - global.NextRoll = undefined; - utilsMock.restore(); - }); - - let validBid = { - bidder: 'nextroll', - adUnitCode: 'adunit-code', - bidId: 'bid_id', - sizes: [[300, 200]], - params: { - bidfloor: 1, - zoneId: 'zone1', - publisherId: 'publisher_id' - } - }; - let bidWithoutValidId = { id: '' }; - let bidWithoutId = { params: { zoneId: 'zone1' } }; - - describe('nativeBidRequest', () => { - it('validates native spec', () => { - let nativeAdUnit = [{ - bidder: 'nextroll', - adUnitCode: 'adunit-code', - bidId: 'bid_id', - mediaTypes: { - native: { - title: {required: true, len: 80}, - image: {required: true, sizes: [728, 90]}, - sponsoredBy: {required: false, len: 20}, - clickUrl: {required: true}, - body: {required: true, len: 25}, - icon: {required: true, sizes: [50, 50], aspect_ratios: [{ratio_height: 3, ratio_width: 4}]}, - someRandomAsset: {required: false, len: 100} // This should be ignored - } - }, - params: { - bidfloor: 1, - zoneId: 'zone1', - publisherId: 'publisher_id' - } - }]; - - let request = spec.buildRequests(nativeAdUnit) - let assets = request[0].data.imp.native.request.native.assets - - let excptedAssets = [ - {id: 1, required: 1, title: {len: 80}}, - {id: 2, required: 1, img: {w: 728, h: 90, wmin: 1, hmin: 1, type: 3}}, - {id: 3, required: 1, img: {w: 50, h: 50, wmin: 4, hmin: 3, type: 1}}, - {id: 5, required: 0, data: {len: 20, type: 1}}, - {id: 6, required: 1, data: {len: 25, type: 2}} - ] - expect(assets).to.be.deep.equal(excptedAssets) - }) - }) - - describe('isBidRequestValid', function() { - it('validates the bids correctly when the bid has an id', function() { - expect(spec.isBidRequestValid(validBid)).to.be.true; - }); - - it('validates the bids correcly when the bid does not have an id', function() { - expect(spec.isBidRequestValid(bidWithoutValidId)).to.be.false; - expect(spec.isBidRequestValid(bidWithoutId)).to.be.false; - }); - }); - - describe('buildRequests', function() { - it('builds the same amount of requests as valid requests it takes', function() { - expect(spec.buildRequests([validBid, validBid], {})).to.be.lengthOf(2); - }); - - it('doest not build a request when there is no valid requests', function () { - expect(spec.buildRequests([], {})).to.be.lengthOf(0); - }); - - it('builds a request with POST method', function () { - expect(spec.buildRequests([validBid], {})[0].method).to.equal('POST'); - }); - - it('builds a request with cookies method', function () { - expect(spec.buildRequests([validBid], {})[0].options.withCredentials).to.be.true; - }); - - it('builds a request with id, url and imp object', function () { - const request = spec.buildRequests([validBid], {})[0]; - expect(request.data.id).to.be.an('string').that.is.not.empty; - expect(request.url).to.equal('https://d.adroll.com/bid/prebid/'); - expect(request.data.imp).to.exist.and.to.be.a('object'); - }); - - it('builds a request with site and device information', function () { - const request = spec.buildRequests([validBid], {})[0]; - - expect(request.data.site).to.exist.and.to.be.a('object'); - expect(request.data.device).to.exist.and.to.be.a('object'); - }); - - it('builds a request with a complete imp object', function () { - const request = spec.buildRequests([validBid], {})[0]; - - expect(request.data.imp.id).to.equal('bid_id'); - expect(request.data.imp.bidfloor).to.be.equal(1); - expect(request.data.imp.banner).to.exist.and.to.be.a('object'); - expect(request.data.imp.ext.zone.id).to.be.equal('zone1'); - }); - - it('builds a request with the correct floor object', function () { - // bidfloor is defined, getFloor isn't - let bid = deepClone(validBid); - let request = spec.buildRequests([bid], {})[0]; - expect(request.data.imp.bidfloor).to.be.equal(1); - - // bidfloor not defined, getFloor not defined - bid = deepClone(validBid); - bid.params.bidfloor = null; - request = spec.buildRequests([bid], {})[0]; - expect(request.data.imp.bidfloor).to.not.exist; - - // bidfloor defined, getFloor defined, use getFloor - let getFloorResponse = { currency: 'USD', floor: 3 }; - bid = deepClone(validBid); - bid.getFloor = () => getFloorResponse; - request = spec.buildRequests([bid], {})[0]; - - expect(request.data.imp.bidfloor).to.exist.and.to.equal(3); - }); - - it('includes the sizes into the request correctly', function () { - const bannerObject = spec.buildRequests([validBid], {})[0].data.imp.banner; - - expect(bannerObject.format).to.exist; - expect(bannerObject.format).to.be.lengthOf(1); - expect(bannerObject.format[0].w).to.be.equal(300); - expect(bannerObject.format[0].h).to.be.equal(200); - }); - - it('sets the CCPA consent string', function () { - const us_privacy = '1YYY'; - const request = spec.buildRequests([validBid], {'uspConsent': us_privacy})[0]; - - expect(request.data.regs.ext.us_privacy).to.be.equal(us_privacy); - }); - }); - - describe('interpretResponse', function () { - let responseBody = { - id: 'bidresponse_id', - dealId: 'deal_id', - seatbid: [ - { - bid: [ - { - price: 1.2, - w: 300, - h: 200, - crid: 'crid1', - adm: 'adm1' - } - ] - }, - { - bid: [ - { - price: 2.1, - w: 250, - h: 300, - crid: 'crid2', - adm: 'adm2' - } - ] - } - ] - }; - - it('returns an empty list when there is no response body', function () { - expect(spec.interpretResponse({}, {})).to.be.eql([]); - }); - - it('builds the same amount of responses as server responses it receives', function () { - expect(spec.interpretResponse({body: responseBody}, {})).to.be.lengthOf(2); - }); - - it('builds a response with the expected fields', function () { - const response = spec.interpretResponse({body: responseBody}, {})[0]; - - expect(response.requestId).to.be.equal('bidresponse_id'); - expect(response.cpm).to.be.equal(1.2); - expect(response.width).to.be.equal(300); - expect(response.height).to.be.equal(200); - expect(response.creativeId).to.be.equal('crid1'); - expect(response.dealId).to.be.equal('deal_id'); - expect(response.currency).to.be.equal('USD'); - expect(response.netRevenue).to.be.equal(true); - expect(response.ttl).to.be.equal(300); - expect(response.ad).to.be.equal('adm1'); - }); - }); - - describe('interpret native response', () => { - let clickUrl = 'https://clickurl.com/with/some/path' - let titleText = 'Some title' - let imgW = 300 - let imgH = 250 - let imgUrl = 'https://clickurl.com/img.png' - let brandText = 'Some Brand' - let impUrl = 'https://clickurl.com/imptracker' - - let responseBody = { - body: { - id: 'bidresponse_id', - seatbid: [{ - bid: [{ - price: 1.2, - crid: 'crid1', - adm: { - link: {url: clickUrl}, - assets: [ - {id: 1, title: {text: titleText}}, - {id: 2, img: {w: imgW, h: imgH, url: imgUrl}}, - {id: 5, data: {value: brandText}} - ], - imptrackers: [impUrl] - } - }] - }] - } - }; - - it('Should interpret response', () => { - let response = spec.interpretResponse(utils.deepClone(responseBody)) - let expectedResponse = { - clickUrl: clickUrl, - impressionTrackers: [impUrl], - privacyLink: 'https://app.adroll.com/optout/personalized', - privacyIcon: 'https://s.adroll.com/j/ad-choices-small.png', - title: titleText, - image: {url: imgUrl, width: imgW, height: imgH}, - sponsoredBy: brandText, - clickTrackers: [], - jstracker: [] - } - - expect(response[0].native).to.be.deep.equal(expectedResponse) - }) - - it('Should interpret all assets', () => { - let allAssetsResponse = utils.deepClone(responseBody) - let iconUrl = imgUrl + '?icon=true', iconW = 10, iconH = 15 - let logoUrl = imgUrl + '?logo=true', logoW = 20, logoH = 25 - let bodyText = 'Some body text' - - allAssetsResponse.body.seatbid[0].bid[0].adm.assets.push(...[ - {id: 3, img: {w: iconW, h: iconH, url: iconUrl}}, - {id: 4, img: {w: logoW, h: logoH, url: logoUrl}}, - {id: 6, data: {value: bodyText}} - ]) - - let response = spec.interpretResponse(allAssetsResponse) - let expectedResponse = { - clickUrl: clickUrl, - impressionTrackers: [impUrl], - jstracker: [], - clickTrackers: [], - privacyLink: 'https://app.adroll.com/optout/personalized', - privacyIcon: 'https://s.adroll.com/j/ad-choices-small.png', - title: titleText, - image: {url: imgUrl, width: imgW, height: imgH}, - icon: {url: iconUrl, width: iconW, height: iconH}, - logo: {url: logoUrl, width: logoW, height: logoH}, - body: bodyText, - sponsoredBy: brandText - } - - expect(response[0].native).to.be.deep.equal(expectedResponse) - }) - }) -}); diff --git a/test/spec/modules/nexx360BidAdapter_spec.js b/test/spec/modules/nexx360BidAdapter_spec.js deleted file mode 100644 index 1a695e5f8b3..00000000000 --- a/test/spec/modules/nexx360BidAdapter_spec.js +++ /dev/null @@ -1,305 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/nexx360BidAdapter.js'; -import {newBidder} from 'src/adapters/bidderFactory.js'; -import {config} from 'src/config.js'; -import * as utils from 'src/utils.js'; -import { requestBidsHook } from 'modules/consentManagement.js'; - -describe('Nexx360 bid adapter tests', function () { - const DISPLAY_BID_REQUEST = [{ - 'bidder': 'nexx360', - 'params': { - 'account': '1067', - 'tagId': 'luvxjvgn' - }, - 'userId': { - 'id5id': { - 'uid': 'ID5*hQ5WobYI9Od4u52qpaXVKHhxUa4DsOWRAlvaFajm8gINfI1oVAe3UK59416dT4TqDX1pj4MBJ5TYwir6x3JgBw1-avYHSnmvQDdRMbxmC2sNf3ggIRTbyQBdI1RjvHyeDYCsistnTXF_iKF1nutYeQ2BZ4P5d5muZTG7C2PXVFgNg-18io9dCiSjzJXx93KPDYRiuIwtsGGsp51rojlpFw2Fp_dUkjXl4CAblk58DvwNhobwQ27bnBP8F2-Pcs88DYcvKn4r6dm3Vi7ILttxDQ2IgZ2X44ClgjoWh-vRf6ANis8Z7uL16vO8q0P5C21eDYuc4v_KaZqN-p9YWEeEZQ2OpkbRL7n5NieVJExHM6ANkAlLZhVf2T-1906TAIHKDZFm_xMCa1jJfpBqZB2agw2TjfbK6wMtJeHiZaipSuUNlM_CSH0HVXtfMj9yfzjzDZZnltZQ9lvc4JhXye5AwA2X1f9Dhk8VURTvVdfEUlU', - 'ext': { - 'linkType': 2 - } - } - }, - 'userIdAsEids': [ - { - 'source': 'id5-sync.com', - 'uids': [ - { - 'id': 'ID5*hQ5WobYI9Od4u52qpaXVKHhxUa4DsOWRAlvaFajm8gINfI1oVAe3UK59416dT4TqDX1pj4MBJ5TYwir6x3JgBw1-avYHSnmvQDdRMbxmC2sNf3ggIRTbyQBdI1RjvHyeDYCsistnTXF_iKF1nutYeQ2BZ4P5d5muZTG7C2PXVFgNg-18io9dCiSjzJXx93KPDYRiuIwtsGGsp51rojlpFw2Fp_dUkjXl4CAblk58DvwNhobwQ27bnBP8F2-Pcs88DYcvKn4r6dm3Vi7ILttxDQ2IgZ2X44ClgjoWh-vRf6ANis8Z7uL16vO8q0P5C21eDYuc4v_KaZqN-p9YWEeEZQ2OpkbRL7n5NieVJExHM6ANkAlLZhVf2T-1906TAIHKDZFm_xMCa1jJfpBqZB2agw2TjfbK6wMtJeHiZaipSuUNlM_CSH0HVXtfMj9yfzjzDZZnltZQ9lvc4JhXye5AwA2X1f9Dhk8VURTvVdfEUlU', - 'atype': 1, - 'ext': { - 'linkType': 2 - } - } - ] - } - ], - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250], [300, 600]] - } - }, - 'adUnitCode': 'banner-div', - 'transactionId': '9ad89d90-eb73-41b9-bf5f-7a8e2eecff27', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '4d9e29504f8af6', - 'bidderRequestId': '3423b6bd1a922c', - 'auctionId': '05e0a3a1-9f57-41f6-bbcb-2ba9c9e3d2d5', - 'src': 'client', - 'bidRequestsCount': 1, - 'bidderRequestsCount': 1, - 'bidderWinsCount': 0 - }]; - - const DISPLAY_BID_RESPONSE = {'body': { - 'responses': [ - { - 'bidId': '4d9e29504f8af6', - 'cpm': 0.437245, - 'width': 300, - 'height': 250, - 'creativeId': '98493581', - 'currency': 'EUR', - 'netRevenue': true, - 'type': 'banner', - 'ttl': 360, - 'uuid': 'ce6d1ee3-2a05-4d7c-b97a-9e62097798ec', - 'bidder': 'appnexus', - 'consent': 1, - 'tagId': 'luvxjvgn' - } - ], - }}; - - const VIDEO_BID_REQUEST = [ - { - 'bidder': 'nexx360', - 'params': { - 'account': '1067', - 'tagId': 'yqsc1tfj' - }, - 'mediaTypes': { - 'video': { - 'context': 'instream', - 'playerSize': [[640, 480]], - 'mimes': ['video/mp4'], - 'protocols': [1, 2, 3, 4, 5, 6], - 'playbackmethod': [2], - 'skip': 1 - } - }, - 'adUnitCode': 'video1', - 'transactionId': '5434c81c-7210-44ae-9014-67c75dee48d0', - 'sizes': [[640, 480]], - 'bidId': '22f90541e576a3', - 'bidderRequestId': '1d4549243f3bfd', - 'auctionId': 'ed21b528-bcab-47e2-8605-ec9b71000c89', - 'src': 'client', - 'bidRequestsCount': 1, - 'bidderRequestsCount': 1, - 'bidderWinsCount': 0 - } - ] - - const VIDEO_BID_RESPONSE = {'body': { - 'responses': [ - { - 'bidId': '2c129e8e01859a', - 'type': 'video', - 'uuid': 'b8e7b2f0-c378-479f-aa4f-4f55d5d7d1d5', - 'cpm': 4.5421, - 'width': 1, - 'height': 1, - 'creativeId': '97517771', - 'currency': 'EUR', - 'netRevenue': true, - 'ttl': 360, - 'bidder': 'appnexus', - 'consent': 1, - 'tagId': 'yqsc1tfj' - } - ] - }}; - - const DEFAULT_OPTIONS = { - gdprConsent: { - gdprApplies: true, - consentString: 'BOzZdA0OzZdA0AGABBENDJ-AAAAvh7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__79__3z3_9pxP78k89r7337Mw_v-_v-b7JCPN_Y3v-8Kg', - vendorData: {} - }, - refererInfo: { - referer: 'https://www.prebid.org', - canonicalUrl: 'https://www.prebid.org/the/link/to/the/page' - }, - uspConsent: '111222333', - userId: { 'id5id': { uid: '1111' } }, - schain: { - 'ver': '1.0', - 'complete': 1, - 'nodes': [{ - 'asi': 'exchange1.com', - 'sid': '1234', - 'hp': 1, - 'rid': 'bid-request-1', - 'name': 'publisher', - 'domain': 'publisher.com' - }] - }, - }; - - it('We verify isBidRequestValid with uncorrect bidfloorCurrency', function() { - const bid = { params: { - 'account': '1067', - 'tagId': 'luvxjvgn', - 'bidfloorCurrency': 'AAA', - }}; - expect(spec.isBidRequestValid(bid)).to.be.equal(false); - }); - - it('We verify isBidRequestValid with uncorrect bidfloor', function() { - const bid = { params: { - 'account': '1067', - 'tagId': 'luvxjvgn', - 'bidfloorCurrency': 'EUR', - 'bidfloor': 'EUR', - }}; - expect(spec.isBidRequestValid(bid)).to.be.equal(false); - }); - - it('We verify isBidRequestValid with uncorrect keywords', function() { - const bid = { params: { - 'account': '1067', - 'tagId': 'luvxjvgn', - 'bidfloorCurrency': 'EUR', - 'bidfloor': 0.8, - 'keywords': 'test', - }}; - expect(spec.isBidRequestValid(bid)).to.be.equal(false); - }); - - it('Verify banner build request', function () { - const request = spec.buildRequests(DISPLAY_BID_REQUEST, DEFAULT_OPTIONS); - expect(request).to.have.property('url').and.to.equal('https://fast.nexx360.io/prebid'); - expect(request).to.have.property('method').and.to.equal('POST'); - const requestContent = JSON.parse(request.data); - expect(requestContent.userEids.length).to.be.eql(1); - expect(requestContent.userEids[0]).to.have.property('source').and.to.equal('id5-sync.com'); - expect(requestContent.userEids[0]).to.have.property('uids'); - expect(requestContent.userEids[0].uids[0]).to.have.property('id').and.to.equal('ID5*hQ5WobYI9Od4u52qpaXVKHhxUa4DsOWRAlvaFajm8gINfI1oVAe3UK59416dT4TqDX1pj4MBJ5TYwir6x3JgBw1-avYHSnmvQDdRMbxmC2sNf3ggIRTbyQBdI1RjvHyeDYCsistnTXF_iKF1nutYeQ2BZ4P5d5muZTG7C2PXVFgNg-18io9dCiSjzJXx93KPDYRiuIwtsGGsp51rojlpFw2Fp_dUkjXl4CAblk58DvwNhobwQ27bnBP8F2-Pcs88DYcvKn4r6dm3Vi7ILttxDQ2IgZ2X44ClgjoWh-vRf6ANis8Z7uL16vO8q0P5C21eDYuc4v_KaZqN-p9YWEeEZQ2OpkbRL7n5NieVJExHM6ANkAlLZhVf2T-1906TAIHKDZFm_xMCa1jJfpBqZB2agw2TjfbK6wMtJeHiZaipSuUNlM_CSH0HVXtfMj9yfzjzDZZnltZQ9lvc4JhXye5AwA2X1f9Dhk8VURTvVdfEUlU'); - expect(requestContent.adUnits[0]).to.have.property('account').and.to.equal('1067'); - expect(requestContent.adUnits[0]).to.have.property('tagId').and.to.equal('luvxjvgn'); - expect(requestContent.adUnits[0]).to.have.property('label').and.to.equal('banner-div'); - expect(requestContent.adUnits[0]).to.have.property('bidId').and.to.equal('4d9e29504f8af6'); - expect(requestContent.adUnits[0]).to.have.property('auctionId').and.to.equal('05e0a3a1-9f57-41f6-bbcb-2ba9c9e3d2d5'); - expect(requestContent.adUnits[0]).to.have.property('mediatypes').exist; - expect(requestContent.adUnits[0].mediatypes).to.have.property('banner').exist; - expect(requestContent.adUnits[0]).to.have.property('bidfloor').and.to.equal(0); - expect(requestContent.adUnits[0]).to.have.property('bidfloorCurrency').and.to.equal('USD'); - expect(requestContent.adUnits[0]).to.have.property('keywords'); - expect(requestContent.adUnits[0].keywords.length).to.be.eql(0); - }); - - it('We add bidfloor and keywords', function() { - const DISPLAY_BID_REQUEST_2 = [ ...DISPLAY_BID_REQUEST ]; - DISPLAY_BID_REQUEST_2[0].params.keywords = { interest: 'cars' }; - DISPLAY_BID_REQUEST_2[0].params.bidfloor = 2.1; - const request = spec.buildRequests(DISPLAY_BID_REQUEST, DEFAULT_OPTIONS); - const requestContent = JSON.parse(request.data); - expect(requestContent.adUnits[0]).to.have.property('bidfloor').and.to.equal(2.1); - expect(requestContent.adUnits[0]).to.have.property('bidfloorCurrency').and.to.equal('USD'); - expect(requestContent.adUnits[0]).to.have.property('keywords'); - expect(requestContent.adUnits[0].keywords.length).to.be.eql(1); - expect(requestContent.adUnits[0].keywords[0].key).to.be.eql('interest'); - expect(requestContent.adUnits[0].keywords[0].value[0]).to.be.eql('cars'); - }); - - it('Verify banner parse response', function () { - const request = spec.buildRequests(DISPLAY_BID_REQUEST, DEFAULT_OPTIONS); - const response = spec.interpretResponse(DISPLAY_BID_RESPONSE, request); - expect(response).to.have.lengthOf(1); - const bid = response[0]; - expect(bid.cpm).to.equal(0.437245); - expect(bid.adUrl).to.equal('https://fast.nexx360.io/cache?uuid=ce6d1ee3-2a05-4d7c-b97a-9e62097798ec'); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - expect(bid.creativeId).to.equal('98493581'); - expect(bid.currency).to.equal('EUR'); - expect(bid.netRevenue).to.equal(true); - expect(bid.ttl).to.equal(360); - expect(bid.requestId).to.equal('4d9e29504f8af6'); - expect(bid.nexx360).to.exist; - expect(bid.nexx360.ssp).to.equal('appnexus'); - }); - - it('Verify video build request', function () { - const request = spec.buildRequests(VIDEO_BID_REQUEST, DEFAULT_OPTIONS); - expect(request).to.have.property('url').and.to.equal('https://fast.nexx360.io/prebid'); - expect(request).to.have.property('method').and.to.equal('POST'); - const requestContent = JSON.parse(request.data); - expect(requestContent.adUnits[0]).to.have.property('account').and.to.equal('1067'); - expect(requestContent.adUnits[0]).to.have.property('tagId').and.to.equal('yqsc1tfj'); - expect(requestContent.adUnits[0]).to.have.property('label').and.to.equal('video1'); - expect(requestContent.adUnits[0]).to.have.property('bidId').and.to.equal('22f90541e576a3'); - expect(requestContent.adUnits[0]).to.have.property('auctionId').and.to.equal('ed21b528-bcab-47e2-8605-ec9b71000c89'); - expect(requestContent.adUnits[0]).to.have.property('mediatypes').exist; - expect(requestContent.adUnits[0].mediatypes).to.have.property('video').exist; - }); - - it('Verify video parse response', function () { - const request = spec.buildRequests(VIDEO_BID_REQUEST, DEFAULT_OPTIONS); - const response = spec.interpretResponse(VIDEO_BID_RESPONSE, request); - expect(response).to.have.lengthOf(1); - const bid = response[0]; - expect(bid.cpm).to.equal(4.5421); - expect(bid.vastUrl).to.equal('https://fast.nexx360.io/cache?uuid=b8e7b2f0-c378-479f-aa4f-4f55d5d7d1d5'); - expect(bid.vastImpUrl).to.equal('https://fast.nexx360.io/track-imp?type=prebid&mediatype=video&ssp=appnexus&tag_id=yqsc1tfj&consent=1&price=4.5421'); - expect(bid.width).to.equal(1); - expect(bid.height).to.equal(1); - expect(bid.creativeId).to.equal('97517771'); - expect(bid.currency).to.equal('EUR'); - expect(bid.netRevenue).to.equal(true); - expect(bid.ttl).to.equal(360); - expect(bid.requestId).to.equal('2c129e8e01859a'); - expect(bid.nexx360).to.exist; - expect(bid.nexx360.ssp).to.equal('appnexus'); - }); - - it('Verifies bidder code', function () { - expect(spec.code).to.equal('nexx360'); - }); - - it('Verifies bidder aliases', function () { - expect(spec.aliases).to.have.lengthOf(1); - expect(spec.aliases[0]).to.equal('revenuemaker'); - }); - it('Verifies if bid request valid', function () { - expect(spec.isBidRequestValid(DISPLAY_BID_REQUEST[0])).to.equal(true); - }); - it('Verifies bid won', function () { - const request = spec.buildRequests(DISPLAY_BID_REQUEST, DEFAULT_OPTIONS); - const response = spec.interpretResponse(DISPLAY_BID_RESPONSE, request); - const won = spec.onBidWon(response[0]); - expect(won).to.equal(true); - }); - it('Verifies user sync without cookie in bid response', function () { - var syncs = spec.getUserSyncs({}, [DISPLAY_BID_RESPONSE], DEFAULT_OPTIONS.gdprConsent, DEFAULT_OPTIONS.uspConsent); - expect(syncs).to.have.lengthOf(0); - }); - it('Verifies user sync with cookies in bid response', function () { - DISPLAY_BID_RESPONSE.body.cookies = [{'type': 'image', 'url': 'http://www.cookie.sync.org/'}]; - var syncs = spec.getUserSyncs({}, [DISPLAY_BID_RESPONSE], DEFAULT_OPTIONS.gdprConsent); - expect(syncs).to.have.lengthOf(1); - expect(syncs[0]).to.have.property('type').and.to.equal('image'); - expect(syncs[0]).to.have.property('url').and.to.equal('http://www.cookie.sync.org/'); - }); - it('Verifies user sync with no bid response', function() { - var syncs = spec.getUserSyncs({}, null, DEFAULT_OPTIONS.gdprConsent, DEFAULT_OPTIONS.uspConsent); - expect(syncs).to.have.lengthOf(0); - }); - it('Verifies user sync with no bid body response', function() { - var syncs = spec.getUserSyncs({}, [], DEFAULT_OPTIONS.gdprConsent, DEFAULT_OPTIONS.uspConsent); - expect(syncs).to.have.lengthOf(0); - var syncs = spec.getUserSyncs({}, [{}], DEFAULT_OPTIONS.gdprConsent, DEFAULT_OPTIONS.uspConsent); - expect(syncs).to.have.lengthOf(0); - }); -}); diff --git a/test/spec/modules/nobidBidAdapter_spec.js b/test/spec/modules/nobidBidAdapter_spec.js index eccf0e84031..f775e439a80 100644 --- a/test/spec/modules/nobidBidAdapter_spec.js +++ b/test/spec/modules/nobidBidAdapter_spec.js @@ -2,7 +2,6 @@ import { expect } from 'chai'; import * as utils from 'src/utils.js'; import { spec } from 'modules/nobidBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; -import { config } from 'src/config.js'; import * as bidderFactory from 'src/adapters/bidderFactory.js'; describe('Nobid Adapter', function () { @@ -51,70 +50,6 @@ describe('Nobid Adapter', function () { }); }); - describe('Request with ORTB2', function () { - const SITE_ID = 2; - const REFERER = 'https://www.examplereferer.com'; - const BIDDER_CODE = 'duration'; - let bidRequests = [ - { - 'bidder': BIDDER_CODE, - 'params': { - 'siteId': SITE_ID - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - - let bidderRequest = { - refererInfo: {referer: REFERER}, bidderCode: BIDDER_CODE - } - - const siteName = 'example'; - const siteDomain = 'page.example.com'; - const sitePage = 'https://page.example.com/here.html'; - const siteRef = 'https://ref.example.com'; - const siteKeywords = 'power tools, drills'; - const siteSearch = 'drill'; - const siteCat = 'IAB2'; - const siteSectionCat = 'IAB2-2'; - const sitePageCat = 'IAB2-12'; - - it('ortb2 should exist', function () { - config.setConfig({ - ortb2: { - site: { - name: siteName, - domain: siteDomain, - cat: [ siteCat ], - sectioncat: [ siteSectionCat ], - pagecat: [ sitePageCat ], - page: sitePage, - ref: siteRef, - keywords: siteKeywords, - search: siteSearch - } - } - }); - const request = spec.buildRequests(bidRequests, bidderRequest); - let payload = JSON.parse(request.data); - payload = JSON.parse(JSON.stringify(payload)); - expect(payload.sid).to.equal(SITE_ID); - expect(payload.ortb2.site.name).to.equal(siteName); - expect(payload.ortb2.site.domain).to.equal(siteDomain); - expect(payload.ortb2.site.page).to.equal(sitePage); - expect(payload.ortb2.site.ref).to.equal(siteRef); - expect(payload.ortb2.site.keywords).to.equal(siteKeywords); - expect(payload.ortb2.site.search).to.equal(siteSearch); - expect(payload.ortb2.site.cat[0]).to.equal(siteCat); - expect(payload.ortb2.site.sectioncat[0]).to.equal(siteSectionCat); - expect(payload.ortb2.site.pagecat[0]).to.equal(sitePageCat); - }); - }); - describe('isDurationBidRequestValid', function () { const SITE_ID = 2; const REFERER = 'https://www.examplereferer.com'; @@ -320,6 +255,7 @@ describe('Nobid Adapter', function () { expect(payload.a).to.exist; expect(payload.t).to.exist; expect(payload.tz).to.exist; + expect(payload.r).to.exist.and.to.equal('100x100'); expect(payload.lang).to.exist; expect(payload.ref).to.exist; expect(payload.a[0].d).to.exist.and.to.equal('adunit-code'); diff --git a/test/spec/modules/novatiqIdSystem_spec.js b/test/spec/modules/novatiqIdSystem_spec.js index b92fb0d219a..60c82626450 100644 --- a/test/spec/modules/novatiqIdSystem_spec.js +++ b/test/spec/modules/novatiqIdSystem_spec.js @@ -3,41 +3,41 @@ import * as utils from 'src/utils.js'; import { server } from 'test/mocks/xhr.js'; describe('novatiqIdSystem', function () { - let urlParams = { - novatiqId: 'snowflake', - useStandardUuid: false, - useSspId: true, - useSspHost: true - } - describe('getSrcId', function() { it('getSrcId should set srcId value to 000 due to undefined parameter in config section', function() { const config = { params: { } }; const configParams = config.params || {}; - const response = novatiqIdSubmodule.getSrcId(configParams, urlParams); + const response = novatiqIdSubmodule.getSrcId(configParams); expect(response).to.eq('000'); }); it('getSrcId should set srcId value to 000 due to missing value in config section', function() { const config = { params: { sourceid: '' } }; const configParams = config.params || {}; - const response = novatiqIdSubmodule.getSrcId(configParams, urlParams); + const response = novatiqIdSubmodule.getSrcId(configParams); expect(response).to.eq('000'); }); it('getSrcId should set value to 000 due to null value in config section', function() { const config = { params: { sourceid: null } }; const configParams = config.params || {}; - const response = novatiqIdSubmodule.getSrcId(configParams, urlParams); + const response = novatiqIdSubmodule.getSrcId(configParams); expect(response).to.eq('000'); }); it('getSrcId should set value to 001 due to wrong length in config section max 3 chars', function() { const config = { params: { sourceid: '1234' } }; const configParams = config.params || {}; - const response = novatiqIdSubmodule.getSrcId(configParams, urlParams); + const response = novatiqIdSubmodule.getSrcId(configParams); expect(response).to.eq('001'); }); + + it('getSrcId should set value to 002 due to wrong format in config section', function() { + const config = { params: { sourceid: '1xc' } }; + const configParams = config.params || {}; + const response = novatiqIdSubmodule.getSrcId(configParams); + expect(response).to.eq('002'); + }); }); describe('getId', function() { @@ -52,89 +52,6 @@ describe('novatiqIdSystem', function () { const response = novatiqIdSubmodule.getId(config); expect(response.id).should.be.not.empty; }); - - it('should set sharedStatus if sharedID is configured but returned null', function() { - const config = { params: { sourceid: '123', useSharedId: true } }; - const response = novatiqIdSubmodule.getId(config); - expect(response.sharedStatus).to.equal('Not Found'); - }); - - it('should set sharedStatus if sharedID is configured and is valid', function() { - const config = { params: { sourceid: '123', useSharedId: true } }; - - let stub = sinon.stub(novatiqIdSubmodule, 'getSharedId').returns('fakeId'); - - const response = novatiqIdSubmodule.getId(config); - - stub.restore(); - - expect(response.sharedStatus).to.equal('Found'); - }); - - it('should set sharedStatus if sharedID is configured and is valid when making an async call', function() { - const config = { params: { sourceid: '123', useSharedId: true, useCallbacks: true } }; - - let stub = sinon.stub(novatiqIdSubmodule, 'getSharedId').returns('fakeId'); - - const response = novatiqIdSubmodule.getId(config); - - stub.restore(); - - expect(response.sharedStatus).to.equal('Found'); - }); - }); - - describe('getUrlParams', function() { - it('should return default url parameters when none set', function() { - const defaultUrlParams = { - novatiqId: 'snowflake', - useStandardUuid: false, - useSspId: true, - useSspHost: true - } - - const config = { params: { sourceid: '123' } }; - const response = novatiqIdSubmodule.getUrlParams(config); - - expect(response).to.deep.equal(defaultUrlParams); - }); - - it('should return custom url parameters when set', function() { - let customUrlParams = { - novatiqId: 'hyperid', - useStandardUuid: true, - useSspId: false, - useSspHost: false - } - - const config = { - sourceid: '123', - urlParams: { - novatiqId: 'hyperid', - useStandardUuid: true, - useSspId: false, - useSspHost: false - } - }; - const response = novatiqIdSubmodule.getUrlParams(config); - - expect(response).to.deep.equal(customUrlParams); - }); - }); - - describe('sendAsyncSyncRequest', function() { - it('should return an async function when called asynchronously', function() { - const defaultUrlParams = { - novatiqId: 'snowflake', - useStandardUuid: false, - useSspId: true, - useSspHost: true - } - - const url = novatiqIdSubmodule.getSyncUrl(false, '', defaultUrlParams); - const response = novatiqIdSubmodule.sendAsyncSyncRequest('testuuid', url); - expect(response.callback).should.not.be.empty; - }); }); describe('decode', function() { diff --git a/test/spec/modules/oguryBidAdapter_spec.js b/test/spec/modules/oguryBidAdapter_spec.js index acf62bf5a7b..0a57690db27 100644 --- a/test/spec/modules/oguryBidAdapter_spec.js +++ b/test/spec/modules/oguryBidAdapter_spec.js @@ -1,9 +1,8 @@ import { expect } from 'chai'; import { spec } from 'modules/oguryBidAdapter'; -import * as utils from 'src/utils.js'; +import { deepClone } from 'src/utils.js'; -const BID_URL = 'https://mweb-hb.presage.io/api/header-bidding-request'; -const TIMEOUT_URL = 'https://ms-ads-monitoring-events.presage.io/bid_timeout' +const BID_HOST = 'https://mweb-hb.presage.io/api/header-bidding-request'; describe('OguryBidAdapter', function () { let bidRequests; @@ -68,14 +67,14 @@ describe('OguryBidAdapter', function () { describe('isBidRequestValid', function () { it('should validate correct bid', () => { - let validBid = utils.deepClone(bidRequests[0]); + let validBid = deepClone(bidRequests[0]); let isValid = spec.isBidRequestValid(validBid); expect(isValid).to.equal(true); }); it('should not validate incorrect bid', () => { - let invalidBid = utils.deepClone(bidRequests[0]); + let invalidBid = deepClone(bidRequests[0]); delete invalidBid.sizes; delete invalidBid.mediaTypes; @@ -84,7 +83,7 @@ describe('OguryBidAdapter', function () { }); it('should not validate bid if adunit is not present', () => { - let invalidBid = utils.deepClone(bidRequests[0]); + let invalidBid = deepClone(bidRequests[0]); delete invalidBid.params.adUnitId; let isValid = spec.isBidRequestValid(invalidBid); @@ -92,7 +91,7 @@ describe('OguryBidAdapter', function () { }); it('should not validate bid if assetKet is not present', () => { - let invalidBid = utils.deepClone(bidRequests[0]); + let invalidBid = deepClone(bidRequests[0]); delete invalidBid.params.assetKey; let isValid = spec.isBidRequestValid(invalidBid); @@ -100,7 +99,7 @@ describe('OguryBidAdapter', function () { }); it('should validate bid if getFloor is not present', () => { - let invalidBid = utils.deepClone(bidRequests[1]); + let invalidBid = deepClone(bidRequests[1]); delete invalidBid.getFloor; let isValid = spec.isBidRequestValid(invalidBid); @@ -119,117 +118,35 @@ describe('OguryBidAdapter', function () { }; }); - it('should return syncs array with two elements of type image', () => { + it('should return syncs array with an element of type image', () => { const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent); - expect(userSyncs).to.have.lengthOf(2); + expect(userSyncs).to.have.lengthOf(1); expect(userSyncs[0].type).to.equal('image'); expect(userSyncs[0].url).to.contain('https://ms-cookie-sync.presage.io/v1/init-sync/bid-switch'); - expect(userSyncs[1].type).to.equal('image'); - expect(userSyncs[1].url).to.contain('https://ms-cookie-sync.presage.io/ttd/init-sync'); }); it('should set the source as query param', () => { const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent); expect(userSyncs[0].url).to.contain('source=prebid'); - expect(userSyncs[1].url).to.contain('source=prebid'); }); it('should set the tcString as query param', () => { const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent); expect(userSyncs[0].url).to.contain(`iab_string=${gdprConsent.consentString}`); - expect(userSyncs[1].url).to.contain(`iab_string=${gdprConsent.consentString}`); }); it('should return an empty array when pixel is disable', () => { syncOptions.pixelEnabled = false; expect(spec.getUserSyncs(syncOptions, [], gdprConsent)).to.have.lengthOf(0); }); - - it('should return syncs array with two elements of type image when consentString is undefined', () => { - gdprConsent = { - gdprApplies: true, - consentString: undefined - }; - - const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent); - expect(userSyncs).to.have.lengthOf(2); - expect(userSyncs[0].type).to.equal('image'); - expect(userSyncs[0].url).to.equal('https://ms-cookie-sync.presage.io/v1/init-sync/bid-switch?iab_string=&source=prebid') - expect(userSyncs[1].type).to.equal('image'); - expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid') - }); - - it('should return syncs array with two elements of type image when consentString is null', () => { - gdprConsent = { - gdprApplies: true, - consentString: null - }; - - const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent); - expect(userSyncs).to.have.lengthOf(2); - expect(userSyncs[0].type).to.equal('image'); - expect(userSyncs[0].url).to.equal('https://ms-cookie-sync.presage.io/v1/init-sync/bid-switch?iab_string=&source=prebid') - expect(userSyncs[1].type).to.equal('image'); - expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid') - }); - - it('should return syncs array with two elements of type image when gdprConsent is undefined', () => { - gdprConsent = undefined; - - const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent); - expect(userSyncs).to.have.lengthOf(2); - expect(userSyncs[0].type).to.equal('image'); - expect(userSyncs[0].url).to.equal('https://ms-cookie-sync.presage.io/v1/init-sync/bid-switch?iab_string=&source=prebid') - expect(userSyncs[1].type).to.equal('image'); - expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid') - }); - - it('should return syncs array with two elements of type image when gdprConsent is null', () => { - gdprConsent = null; - - const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent); - expect(userSyncs).to.have.lengthOf(2); - expect(userSyncs[0].type).to.equal('image'); - expect(userSyncs[0].url).to.equal('https://ms-cookie-sync.presage.io/v1/init-sync/bid-switch?iab_string=&source=prebid') - expect(userSyncs[1].type).to.equal('image'); - expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid') - }); - - it('should return syncs array with two elements of type image when gdprConsent is null and gdprApplies is false', () => { - gdprConsent = { - gdprApplies: false, - consentString: null - }; - - const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent); - expect(userSyncs).to.have.lengthOf(2); - expect(userSyncs[0].type).to.equal('image'); - expect(userSyncs[0].url).to.equal('https://ms-cookie-sync.presage.io/v1/init-sync/bid-switch?iab_string=&source=prebid') - expect(userSyncs[1].type).to.equal('image'); - expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid') - }); - - it('should return syncs array with two elements of type image when gdprConsent is empty string and gdprApplies is false', () => { - gdprConsent = { - gdprApplies: false, - consentString: '' - }; - - const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent); - expect(userSyncs).to.have.lengthOf(2); - expect(userSyncs[0].type).to.equal('image'); - expect(userSyncs[0].url).to.equal('https://ms-cookie-sync.presage.io/v1/init-sync/bid-switch?iab_string=&source=prebid') - expect(userSyncs[1].type).to.equal('image'); - expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid') - }); }); describe('buildRequests', function () { const defaultTimeout = 1000; const expectedRequestObject = { id: bidRequests[0].auctionId, - at: 1, + at: 2, tmax: defaultTimeout, imp: [{ id: bidRequests[0].bidId, @@ -240,8 +157,7 @@ describe('OguryBidAdapter', function () { w: 300, h: 250 }] - }, - ext: bidRequests[0].params + } }, { id: bidRequests[1].bidId, tagid: bidRequests[1].params.adUnitId, @@ -251,8 +167,7 @@ describe('OguryBidAdapter', function () { w: 600, h: 500 }] - }, - ext: bidRequests[1].params + } }], regs: { ext: { @@ -262,29 +177,24 @@ describe('OguryBidAdapter', function () { site: { id: bidRequests[0].params.assetKey, domain: window.location.hostname, - page: window.location.href }, user: { ext: { consent: bidderRequest.gdprConsent.consentString }, - }, - ext: { - prebidversion: '$prebid.version$', - adapterversion: '1.2.10' } }; it('sends bid request to ENDPOINT via POST', function () { - const validBidRequests = utils.deepClone(bidRequests) + const validBidRequests = deepClone(bidRequests) const request = spec.buildRequests(validBidRequests, bidderRequest); - expect(request.url).to.equal(BID_URL); + expect(request.url).to.equal(BID_HOST); expect(request.method).to.equal('POST'); }); it('bid request object should be conform', function () { - const validBidRequests = utils.deepClone(bidRequests) + const validBidRequests = deepClone(bidRequests) const request = spec.buildRequests(validBidRequests, bidderRequest); expect(request.data).to.deep.equal(expectedRequestObject); @@ -300,59 +210,7 @@ describe('OguryBidAdapter', function () { ...expectedRequestObject, regs: { ext: { - gdpr: 0 - }, - }, - user: { - ext: { - consent: '' - }, - } - }; - - const validBidRequests = bidRequests - - const request = spec.buildRequests(validBidRequests, bidderRequestWithoutGdpr); - expect(request.data).to.deep.equal(expectedRequestObjectWithoutGdpr); - expect(request.data.regs.ext.gdpr).to.be.a('number'); - }); - - it('should not add gdpr infos if gdprConsent is undefined', () => { - const bidderRequestWithoutGdpr = { - ...bidderRequest, - gdprConsent: undefined, - } - const expectedRequestObjectWithoutGdpr = { - ...expectedRequestObject, - regs: { - ext: { - gdpr: 0 - }, - }, - user: { - ext: { - consent: '' - }, - } - }; - - const validBidRequests = bidRequests - - const request = spec.buildRequests(validBidRequests, bidderRequestWithoutGdpr); - expect(request.data).to.deep.equal(expectedRequestObjectWithoutGdpr); - expect(request.data.regs.ext.gdpr).to.be.a('number'); - }); - - it('should not add tcString and turn off gdpr-applies if consentString and gdprApplies are undefined', () => { - const bidderRequestWithoutGdpr = { - ...bidderRequest, - gdprConsent: { consentString: undefined, gdprApplies: undefined }, - } - const expectedRequestObjectWithoutGdpr = { - ...expectedRequestObject, - regs: { - ext: { - gdpr: 0 + gdpr: 1 }, }, user: { @@ -374,7 +232,7 @@ describe('OguryBidAdapter', function () { ...expectedRequestObject }; - const validBidRequests = utils.deepClone(bidRequests); + const validBidRequests = deepClone(bidRequests); validBidRequests[1] = { ...validBidRequests[1], getFloor: undefined @@ -389,7 +247,7 @@ describe('OguryBidAdapter', function () { ...expectedRequestObject }; - let validBidRequests = utils.deepClone(bidRequests); + let validBidRequests = deepClone(bidRequests); validBidRequests[1] = { ...validBidRequests[1], getFloor: 'getFloor' @@ -400,9 +258,9 @@ describe('OguryBidAdapter', function () { }); it('should handle bidFloor when currency is not USD', () => { - const expectedRequestWithUnsupportedFloorCurrency = utils.deepClone(expectedRequestObject) + const expectedRequestWithUnsupportedFloorCurrency = deepClone(expectedRequestObject) expectedRequestWithUnsupportedFloorCurrency.imp[0].bidfloor = 0; - let validBidRequests = utils.deepClone(bidRequests); + let validBidRequests = deepClone(bidRequests); validBidRequests[0] = { ...validBidRequests[0], getFloor: ({ size, currency, mediaType }) => { @@ -481,9 +339,7 @@ describe('OguryBidAdapter', function () { meta: { advertiserDomains: openRtbBidResponse.body.seatbid[0].bid[0].adomain }, - nurl: openRtbBidResponse.body.seatbid[0].bid[0].nurl, - adapterVersion: '1.2.10', - prebidVersion: '$prebid.version$' + nurl: openRtbBidResponse.body.seatbid[0].bid[0].nurl }, { requestId: openRtbBidResponse.body.seatbid[0].bid[1].impid, cpm: openRtbBidResponse.body.seatbid[0].bid[1].price, @@ -498,9 +354,7 @@ describe('OguryBidAdapter', function () { meta: { advertiserDomains: openRtbBidResponse.body.seatbid[0].bid[1].adomain }, - nurl: openRtbBidResponse.body.seatbid[0].bid[1].nurl, - adapterVersion: '1.2.10', - prebidVersion: '$prebid.version$' + nurl: openRtbBidResponse.body.seatbid[0].bid[1].nurl }] let request = spec.buildRequests(bidRequests, bidderRequest); @@ -533,11 +387,11 @@ describe('OguryBidAdapter', function () { }) afterEach(function() { - xhr.restore() + xhr.restore(); }) it('Should not create nurl request if bid is undefined', function() { - spec.onBidWon() + spec.onBidWon(); expect(requests.length).to.equal(0); }) @@ -546,87 +400,11 @@ describe('OguryBidAdapter', function () { expect(requests.length).to.equal(0); }) - it('Should not create nurl request if bid contains undefined nurl', function() { - spec.onBidWon({ nurl: undefined }) - expect(requests.length).to.equal(0); - }) - it('Should create nurl request if bid nurl', function() { spec.onBidWon({ nurl }) expect(requests.length).to.equal(1); expect(requests[0].url).to.equal(nurl); expect(requests[0].method).to.equal('GET') }) - - it('Should trigger getWindowContext method', function() { - const bidSample = { - id: 'advertId', - impid: 'bidId', - price: 100, - nurl: 'url', - adm: `test creative
cookies
`, - adomain: ['renault.fr'], - ext: { - adcontent: 'sample_creative', - advertid: '1a278c48-b79a-4bbf-b69f-3824803e7d87', - campaignid: '31724', - mediatype: 'image', - userid: 'ab4aabed-5230-49d9-9f1a-f06280d28366', - usersync: true, - advertiserid: '1', - isomidcompliant: false - }, - w: 180, - h: 101 - } - spec.onBidWon(bidSample) - expect(window.top.OG_PREBID_BID_OBJECT).to.deep.equal(bidSample) - }) }) - - describe('getWindowContext', function() { - it('Should return top window if exist', function() { - const res = spec.getWindowContext() - expect(res).to.equal(window.top) - expect(res).to.not.be.undefined; - }) - - it('Should return self window if getting top window throw an error', function() { - const stub = sinon.stub(utils, 'getWindowTop') - stub.throws() - const res = spec.getWindowContext() - expect(res).to.equal(window.self) - utils.getWindowTop.restore() - }) - }) - - describe('onTimeout', function () { - let xhr; - let requests; - - beforeEach(function() { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (xhr) => { - requests.push(xhr); - }; - }) - - afterEach(function() { - xhr.restore() - }) - - it('should send on bid timeout notification', function() { - const bid = { - ad: 'cookies', - cpm: 3 - } - spec.onTimeout(bid); - expect(requests).to.not.be.undefined; - expect(requests.length).to.equal(1); - expect(requests[0].url).to.equal(TIMEOUT_URL); - expect(requests[0].method).to.equal('POST'); - expect(JSON.parse(requests[0].requestBody).location).to.equal(window.location.href); - }) - }); }); diff --git a/test/spec/modules/onetagBidAdapter_spec.js b/test/spec/modules/onetagBidAdapter_spec.js index f335f2ec62a..9fb73f7774b 100644 --- a/test/spec/modules/onetagBidAdapter_spec.js +++ b/test/spec/modules/onetagBidAdapter_spec.js @@ -1,6 +1,6 @@ import { spec, isValid, hasTypeVideo } from 'modules/onetagBidAdapter.js'; import { expect } from 'chai'; -import {find} from 'src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; import { BANNER, VIDEO } from 'src/mediaTypes.js'; import {INSTREAM, OUTSTREAM} from 'src/video.js'; @@ -191,8 +191,12 @@ describe('onetag', function () { 'pubId', 'transactionId', 'context', + 'mimes', 'playerSize', - 'mediaTypeInfo', + 'protocols', + 'maxDuration', + 'api', + 'playbackmethod', 'type' ); } else if (isValid(BANNER, bid)) { @@ -203,7 +207,6 @@ describe('onetag', function () { 'bidderRequestId', 'pubId', 'transactionId', - 'mediaTypeInfo', 'sizes', 'type' ); diff --git a/test/spec/modules/ooloAnalyticsAdapter_spec.js b/test/spec/modules/ooloAnalyticsAdapter_spec.js index a6030e972ce..f82f7856fb2 100644 --- a/test/spec/modules/ooloAnalyticsAdapter_spec.js +++ b/test/spec/modules/ooloAnalyticsAdapter_spec.js @@ -2,7 +2,7 @@ import ooloAnalytics, { PAGEVIEW_ID } from 'modules/ooloAnalyticsAdapter.js'; import {expect} from 'chai'; import {server} from 'test/mocks/xhr.js'; import constants from 'src/constants.json' -import * as events from 'src/events' +import events from 'src/events' import { config } from 'src/config'; import { buildAuctionData, generatePageViewId } from 'modules/ooloAnalyticsAdapter'; diff --git a/test/spec/modules/open8BidAdapter_spec.js b/test/spec/modules/open8BidAdapter_spec.js deleted file mode 100644 index 27e460bad9d..00000000000 --- a/test/spec/modules/open8BidAdapter_spec.js +++ /dev/null @@ -1,258 +0,0 @@ -import { spec } from 'modules/open8BidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; - -const ENDPOINT = 'https://as.vt.open8.com/v1/control/prebid'; - -describe('Open8Adapter', function() { - const adapter = newBidder(spec); - - describe('isBidRequestValid', function() { - let bid = { - 'bidder': 'open8', - 'params': { - 'slotKey': 'slotkey1234' - }, - 'adUnitCode': 'adunit', - 'sizes': [[300, 250]], - 'bidId': 'bidid1234', - 'bidderRequestId': 'requestid1234', - 'auctionId': 'auctionid1234', - }; - - it('should return true when required params found', function() { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when required params are not passed', function() { - bid.params = { - ' slotKey': 0 - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', function() { - let bidRequests = [ - { - 'bidder': 'open8', - 'params': { - 'slotKey': 'slotkey1234' - }, - 'adUnitCode': 'adunit', - 'sizes': [[300, 250]], - 'bidId': 'bidid1234', - 'bidderRequestId': 'requestid1234', - 'auctionId': 'auctionid1234', - } - ]; - - it('sends bid request to ENDPOINT via GET', function() { - const requests = spec.buildRequests(bidRequests); - expect(requests[0].url).to.equal(ENDPOINT); - expect(requests[0].method).to.equal('GET'); - }); - }); - describe('interpretResponse', function() { - const adomin = ['example.com'] - const bannerResponse = { - slotKey: 'slotkey1234', - userId: 'userid1234', - impId: 'impid1234', - media: 'TEST_MEDIA', - nurl: '//example/win', - isAdReturn: true, - syncPixels: ['//example/sync/pixel.gif'], - syncIFs: [], - ad: { - bidId: 'TEST_BID_ID', - price: 1234.56, - creativeId: 'creativeid1234', - dealId: 'TEST_DEAL_ID', - currency: 'JPY', - ds: 876, - spd: 1234, - fa: 5678, - pr: 'pr1234', - mr: 'mr1234', - nurl: '//example/win', - adType: 2, - banner: { - w: 300, - h: 250, - adm: '
', - imps: ['//example.com/imp'] - }, - adomain: adomin - } - }; - const videoResponse = { - slotKey: 'slotkey1234', - userId: 'userid1234', - impId: 'impid1234', - media: 'TEST_MEDIA', - isAdReturn: true, - syncPixels: ['//example/sync/pixel.gif'], - syncIFs: [], - ad: { - bidId: 'TEST_BID_ID', - price: 1234.56, - creativeId: 'creativeid1234', - dealId: 'TEST_DEAL_ID', - currency: 'JPY', - ds: 876, - spd: 1234, - fa: 5678, - pr: 'pr1234', - mr: 'mr1234', - nurl: '//example/win', - adType: 1, - video: { - purl: '//playerexample.js', - vastXml: '', - w: 320, - h: 180 - }, - adomain: adomin - } - }; - - it('should get correct banner bid response', function() { - let expectedResponse = [{ - 'slotKey': 'slotkey1234', - 'userId': 'userid1234', - 'impId': 'impid1234', - 'media': 'TEST_MEDIA', - 'ds': 876, - 'spd': 1234, - 'fa': 5678, - 'pr': 'pr1234', - 'mr': 'mr1234', - 'nurl': '//example/win', - 'requestId': 'requestid1234', - 'cpm': 1234.56, - 'creativeId': 'creativeid1234', - 'dealId': 'TEST_DEAL_ID', - 'width': 300, - 'height': 250, - 'ad': "
", - 'mediaType': 'banner', - 'currency': 'JPY', - 'ttl': 360, - 'netRevenue': true, - 'meta': { } - }]; - - let bidderRequest; - let result = spec.interpretResponse({ body: bannerResponse }, { bidderRequest }); - expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); - expect(result[0]).to.nested.contain.property('meta.advertiserDomains', adomin); - }); - - it('handles video responses', function() { - let expectedResponse = [{ - 'slotKey': 'slotkey1234', - 'userId': 'userid1234', - 'impId': 'impid1234', - 'media': 'TEST_MEDIA', - 'ds': 876, - 'spd': 1234, - 'fa': 5678, - 'pr': 'pr1234', - 'mr': 'mr1234', - 'nurl': '//example/win', - 'requestId': 'requestid1234', - 'cpm': 1234.56, - 'creativeId': 'creativeid1234', - 'dealId': 'TEST_DEAL_ID', - 'width': 320, - 'height': 180, - 'vastXml': '', - 'mediaType': 'video', - 'renderer': {}, - 'adResponse': {}, - 'currency': 'JPY', - 'ttl': 360, - 'netRevenue': true, - 'meta': { } - }]; - - let bidderRequest; - let result = spec.interpretResponse({ body: videoResponse }, { bidderRequest }); - expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); - expect(result[0]).to.nested.contain.property('meta.advertiserDomains', adomin); - }); - - it('handles nobid responses', function() { - let response = { - isAdReturn: false, - 'ad': {} - }; - - let bidderRequest; - let result = spec.interpretResponse({ body: response }, { bidderRequest }); - expect(result.length).to.equal(0); - }); - }); - - describe('getUserSyncs', function() { - const imgResponse1 = { - body: { - 'isAdReturn': true, - 'ad': { /* ad body */ }, - 'syncPixels': [ - 'https://example.test/1' - ] - } - }; - - const imgResponse2 = { - body: { - 'isAdReturn': true, - 'ad': { /* ad body */ }, - 'syncPixels': [ - 'https://example.test/2' - ] - } - }; - - const ifResponse = { - body: { - 'isAdReturn': true, - 'ad': { /* ad body */ }, - 'syncIFs': [ - 'https://example.test/3' - ] - } - }; - - it('should use a sync img url from first response', function() { - const syncs = spec.getUserSyncs({ pixelEnabled: true }, [imgResponse1, imgResponse2, ifResponse]); - expect(syncs).to.deep.equal([ - { - type: 'image', - url: 'https://example.test/1' - } - ]); - }); - - it('handle ifs response', function() { - const syncs = spec.getUserSyncs({ iframeEnabled: true }, [ifResponse]); - expect(syncs).to.deep.equal([ - { - type: 'iframe', - url: 'https://example.test/3' - } - ]); - }); - - it('handle empty response (e.g. timeout)', function() { - const syncs = spec.getUserSyncs({ pixelEnabled: true }, []); - expect(syncs).to.deep.equal([]); - }); - - it('returns empty syncs when not enabled', function() { - const syncs = spec.getUserSyncs({ pixelEnabled: false }, [imgResponse1]); - expect(syncs).to.deep.equal([]); - }); - }); -}); diff --git a/test/spec/modules/openxAnalyticsAdapter_spec.js b/test/spec/modules/openxAnalyticsAdapter_spec.js index 47663a41f47..d7d2d31669c 100644 --- a/test/spec/modules/openxAnalyticsAdapter_spec.js +++ b/test/spec/modules/openxAnalyticsAdapter_spec.js @@ -1,10 +1,10 @@ import { expect } from 'chai'; import openxAdapter, {AUCTION_STATES} from 'modules/openxAnalyticsAdapter.js'; -import * as events from 'src/events.js'; +import events from 'src/events.js'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils.js'; import { server } from 'test/mocks/xhr.js'; -import {find} from 'src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; const { EVENTS: { AUCTION_INIT, BID_REQUESTED, BID_RESPONSE, BID_TIMEOUT, BID_WON, AUCTION_END } diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 3bc53e30eb8..96e545d70fa 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1085,7 +1085,7 @@ describe('OpenxAdapter', function () { intentIqId: '1111-intentiqid', lipb: {lipbid: '1111-lipb'}, lotamePanoramaId: '1111-lotameid', - merkleId: {id: '1111-merkleid'}, + merkleId: '1111-merkleid', netId: 'fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg', parrableId: { eid: 'eidVersion.encryptionKeyReference.encryptedValue' }, pubcid: '1111-pubcid', @@ -1102,11 +1102,6 @@ describe('OpenxAdapter', function () { mwOpenLinkId: '1111-mwopenlinkid', dapId: '1111-dapId', amxId: '1111-amxid', - kpuid: '1111-kpuid', - publinkId: '1111-publinkid', - naveggId: '1111-naveggid', - imuid: '1111-imuid', - adtelligentId: '1111-adtelligentid' }; // generates the same set of tests for each id provider @@ -1144,9 +1139,6 @@ describe('OpenxAdapter', function () { let userIdValue; // handle cases where userId key refers to an object switch (userIdProviderKey) { - case 'merkleId': - userIdValue = EXAMPLE_DATA_BY_ATTR.merkleId.id; - break; case 'flocId': userIdValue = EXAMPLE_DATA_BY_ATTR.flocId.id; break; @@ -1553,7 +1545,7 @@ describe('OpenxAdapter', function () { describe('with segments', function () { const TESTS = [ { - name: 'should send proprietary segment data from ortb2.user.data', + name: 'should send proprietary segment data from first party config', config: { ortb2: { user: { @@ -1564,51 +1556,10 @@ describe('OpenxAdapter', function () { } } }, - expect: {sm: 'dmp1/4:foo|bar,dmp2:baz'}, + expect: 'dmp1/4:foo|bar,dmp2:baz', }, { - name: 'should send proprietary segment data from ortb2.site.content.data', - config: { - ortb2: { - site: { - content: { - data: [ - {name: 'dmp1', ext: {segtax: 4}, segment: [{id: 'foo'}, {id: 'bar'}]}, - {name: 'dmp2', segment: [{id: 'baz'}]}, - ] - } - } - } - }, - expect: {scsm: 'dmp1/4:foo|bar,dmp2:baz'}, - }, - { - name: 'should send proprietary segment data from both ortb2.site.content.data and ortb2.user.data', - config: { - ortb2: { - user: { - data: [ - {name: 'dmp1', ext: {segtax: 4}, segment: [{id: 'foo'}, {id: 'bar'}]}, - {name: 'dmp2', segment: [{id: 'baz'}]}, - ] - }, - site: { - content: { - data: [ - {name: 'dmp3', ext: {segtax: 5}, segment: [{id: 'foo2'}, {id: 'bar2'}]}, - {name: 'dmp4', segment: [{id: 'baz2'}]}, - ] - } - } - } - }, - expect: { - sm: 'dmp1/4:foo|bar,dmp2:baz', - scsm: 'dmp3/5:foo2|bar2,dmp4:baz2' - }, - }, - { - name: 'should combine same provider segment data from ortb2.user.data', + name: 'should combine same provider segment data from first party config', config: { ortb2: { user: { @@ -1619,23 +1570,7 @@ describe('OpenxAdapter', function () { } } }, - expect: {sm: 'dmp1/4:foo|bar,dmp1:baz'}, - }, - { - name: 'should combine same provider segment data from ortb2.site.content.data', - config: { - ortb2: { - site: { - content: { - data: [ - {name: 'dmp1', ext: {segtax: 4}, segment: [{id: 'foo'}, {id: 'bar'}]}, - {name: 'dmp1', ext: {}, segment: [{id: 'baz'}]}, - ] - } - } - } - }, - expect: {scsm: 'dmp1/4:foo|bar,dmp1:baz'}, + expect: 'dmp1/4:foo|bar,dmp1:baz', }, { name: 'should not send any segment data if first party config is incomplete', @@ -1660,14 +1595,6 @@ describe('OpenxAdapter', function () { {name: 'dmp1', segment: [{id: 'foo'}, {id: 'bar'}]}, {name: 'dmp2', segment: [{id: 'baz'}]}, ] - }, - site: { - content: { - data: [ - {name: 'dmp3', ext: {segtax: 5}, segment: [{id: 'foo2'}, {id: 'bar2'}]}, - {name: 'dmp4', segment: [{id: 'baz2'}]}, - ] - } } } }, @@ -1679,10 +1606,7 @@ describe('OpenxAdapter', function () { }, }, }, - expect: { - sm: 'dmp1:foo|bar,dmp2:baz,liveintent:l1|l2', - scsm: 'dmp3/5:foo2|bar2,dmp4:baz2' - }, + expect: 'dmp1:foo|bar,dmp2:baz,liveintent:l1|l2', }, { name: 'should send just liveintent segment from request if no first party config', @@ -1695,7 +1619,7 @@ describe('OpenxAdapter', function () { }, }, }, - expect: {sm: 'liveintent:l1|l2'}, + expect: 'liveintent:l1|l2', }, { name: 'should send nothing if lipb section does not contain segments', @@ -1712,11 +1636,13 @@ describe('OpenxAdapter', function () { utils._each(TESTS, (t) => { context('in ortb2.user.data', function () { let bidRequests; + let configStub; + beforeEach(function () { let fpdConfig = t.config - sinon + configStub = sinon .stub(config, 'getConfig') - .withArgs(sinon.match(/^ortb2\.user\.data$|^ortb2\.site\.content\.data$/)) + .withArgs('ortb2.user.data') .callsFake((key) => { return utils.deepAccess(fpdConfig, key); }); @@ -1732,13 +1658,10 @@ describe('OpenxAdapter', function () { const request = spec.buildRequests(bidRequests, mockBidderRequest) expect(request.length).to.equal(1); if (t.expect) { - for (const key in t.expect) { - expect(request[0].data[key]).to.exist; - expect(request[0].data[key]).to.equal(t.expect[key]); - } + expect(request[0].data.sm).to.exist; + expect(request[0].data.sm).to.equal(encodeURIComponent(t.expect)); } else { expect(request[0].data.sm).to.not.exist; - expect(request[0].data.scsm).to.not.exist; } }); }); diff --git a/test/spec/modules/operaadsBidAdapter_spec.js b/test/spec/modules/operaadsBidAdapter_spec.js index 849a3eada3f..92e51c5473d 100644 --- a/test/spec/modules/operaadsBidAdapter_spec.js +++ b/test/spec/modules/operaadsBidAdapter_spec.js @@ -266,7 +266,7 @@ describe('Opera Ads Bid Adapter', function () { } }); - it('test getBidFloor', function() { + it('currency in params should be used', function () { const bidRequests = [ { adUnitCode: 'test-div', @@ -276,13 +276,8 @@ describe('Opera Ads Bid Adapter', function () { params: { placementId: 's12345678', publisherId: 'pub12345678', - endpointId: 'ep12345678' - }, - getFloor: function() { - return { - currency: 'USD', - floor: 0.1 - } + endpointId: 'ep12345678', + currency: 'RMB' } } ]; @@ -297,9 +292,7 @@ describe('Opera Ads Bid Adapter', function () { requestData = JSON.parse(req.data); }).to.not.throw(); - expect(requestData.imp).to.be.an('array').that.have.lengthOf(1); - expect(requestData.imp[0].bidfloor).to.be.equal(0.1); - expect(requestData.imp[0].bidfloorcur).to.be.equal('USD'); + expect(requestData.cur).to.be.an('array').that.includes('RMB'); } }); @@ -369,7 +362,7 @@ describe('Opera Ads Bid Adapter', function () { requestData = JSON.parse(reqs[0].data); }).to.not.throw(); - expect(requestData.user.buyeruid).to.equal(bidRequests[0].userId.sharedid.id); + expect(requestData.user.id).to.equal(bidRequests[0].userId.sharedid.id); }); it('pubcid should be used when sharedid is empty', function () { @@ -406,7 +399,7 @@ describe('Opera Ads Bid Adapter', function () { requestData = JSON.parse(reqs[0].data); }).to.not.throw(); - expect(requestData.user.buyeruid).to.equal(bidRequests[0].userId.pubcid); + expect(requestData.user.id).to.equal(bidRequests[0].userId.pubcid); }); it('random uid will be generate when userId is empty', function () { @@ -433,7 +426,7 @@ describe('Opera Ads Bid Adapter', function () { requestData = JSON.parse(reqs[0].data); }).to.not.throw(); - expect(requestData.user.buyeruid).to.not.be.empty; + expect(requestData.user.id).to.not.be.empty; }) }); @@ -679,41 +672,9 @@ describe('Opera Ads Bid Adapter', function () { }); }); - describe('Test getUserSyncs with both iframe and pixel disabled', function () { - it('getUserSyncs should return an empty array', function () { - const syncOptions = {}; - expect(spec.getUserSyncs(syncOptions)).to.be.an('array').that.is.empty; - }); - }); - - describe('Test getUserSyncs with iframe enabled', function () { - it('getUserSyncs should return array', function () { - const syncOptions = { - iframeEnabled: true - } - const userSyncPixels = spec.getUserSyncs(syncOptions) - expect(userSyncPixels).to.have.lengthOf(1); - expect(userSyncPixels[0].url).to.equal('https://s.adx.opera.com/usersync/page') - }); - }); - - describe('Test getUserSyncs with pixel enabled', function () { - it('getUserSyncs should return array', function () { - const serverResponse = { - body: { - 'pixels': [ - 'https://b1.com/usersync', - 'https://b2.com/usersync' - ] - } - }; - const syncOptions = { - pixelEnabled: true - } - const userSyncPixels = spec.getUserSyncs(syncOptions, [serverResponse]) - expect(userSyncPixels).to.have.lengthOf(2); - expect(userSyncPixels[0].url).to.equal('https://b1.com/usersync') - expect(userSyncPixels[1].url).to.equal('https://b2.com/usersync') + describe('Test getUserSyncs', function () { + it('getUserSyncs should return empty array', function () { + expect(spec.getUserSyncs()).to.be.an('array').that.is.empty; }); }); diff --git a/test/spec/modules/optimeraRtdProvider_spec.js b/test/spec/modules/optimeraRtdProvider_spec.js index aec8b79045e..8b1866d044a 100644 --- a/test/spec/modules/optimeraRtdProvider_spec.js +++ b/test/spec/modules/optimeraRtdProvider_spec.js @@ -1,6 +1,5 @@ import * as optimeraRTD from '../../../modules/optimeraRtdProvider.js'; - -const utils = require('src/utils.js'); +let utils = require('src/utils.js'); describe('Optimera RTD sub module', () => { it('should init, return true, and set the params', () => { @@ -32,86 +31,40 @@ describe('Optimera RTD score file properly sets targeting values', () => { const scores = { 'div-0': ['A1', 'A2'], 'div-1': ['A3', 'A4'], - device: { - de: { + 'device': { + 'de': { 'div-0': ['A5', 'A6'], 'div-1': ['A7', 'A8'], - insights: { - ilv: ['div-0'], - miv: ['div-4'], - } }, - mo: { + 'mo': { 'div-0': ['A9', 'B0'], 'div-1': ['B1', 'B2'], - insights: { - ilv: ['div-1'], - miv: ['div-2'], - } } - }, - insights: { - ilv: ['div-5'], - miv: ['div-6'], } }; - it('Properly set the score file url and scores', () => { + it('Properly set the score file url', () => { optimeraRTD.setScores(JSON.stringify(scores)); expect(optimeraRTD.optimeraTargeting['div-0']).to.include.ordered.members(['A5', 'A6']); expect(optimeraRTD.optimeraTargeting['div-1']).to.include.ordered.members(['A7', 'A8']); }); }); -describe('Optimera RTD propery sets the window.optimera object', () => { - const scores = { - 'div-0': ['A1', 'A2'], - 'div-1': ['A3', 'A4'], - device: { - de: { - 'div-0': ['A5', 'A6'], - 'div-1': ['A7', 'A8'], - insights: { - ilv: ['div-0'], - miv: ['div-4'], - } - }, - mo: { - 'div-0': ['A9', 'B0'], - 'div-1': ['B1', 'B2'], - insights: { - ilv: ['div-1'], - miv: ['div-2'], - } - } - }, - insights: { - ilv: ['div-5'], - miv: ['div-6'], - } - }; - it('Properly set the score file url and scores', () => { - optimeraRTD.setScores(JSON.stringify(scores)); - expect(window.optimera.data['div-1']).to.include.ordered.members(['A7', 'A8']); - expect(window.optimera.insights.ilv).to.include.ordered.members(['div-0']); - }); -}); - describe('Optimera RTD targeting object is properly formed', () => { const adDivs = ['div-0', 'div-1']; it('applyTargeting properly created the targeting object', () => { const targeting = optimeraRTD.returnTargetingData(adDivs); - expect(targeting).to.deep.include({ 'div-0': { optimera: [['A5', 'A6']] } }); - expect(targeting).to.deep.include({ 'div-1': { optimera: [['A7', 'A8']] } }); + expect(targeting).to.deep.include({'div-0': {'optimera': [['A5', 'A6']]}}); + expect(targeting).to.deep.include({'div-1': {'optimera': [['A7', 'A8']]}}); }); }); describe('Optimera RTD error logging', () => { let utilsLogErrorStub; - beforeEach(() => { + beforeEach(function () { utilsLogErrorStub = sinon.stub(utils, 'logError'); }); - afterEach(() => { + afterEach(function () { utilsLogErrorStub.restore(); }); diff --git a/test/spec/modules/optimonAnalyticsAdapter_spec.js b/test/spec/modules/optimonAnalyticsAdapter_spec.js index c50bfcb170f..b5b76ce3fde 100644 --- a/test/spec/modules/optimonAnalyticsAdapter_spec.js +++ b/test/spec/modules/optimonAnalyticsAdapter_spec.js @@ -2,7 +2,7 @@ import * as utils from 'src/utils.js'; import { expect } from 'chai'; import optimonAnalyticsAdapter from '../../../modules/optimonAnalyticsAdapter.js'; import adapterManager from 'src/adapterManager'; -import * as events from 'src/events'; +import events from 'src/events'; import constants from 'src/constants.json' const AD_UNIT_CODE = 'demo-adunit-1'; diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index 750524cf47f..0a18799ad4b 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -283,27 +283,6 @@ describe('orbidderBidAdapter', () => { }); }); - describe('buildRequests with price floor module', () => { - const bidRequest = deepClone(defaultBidRequestBanner); - bidRequest.params.bidfloor = 1; - bidRequest.getFloor = (floorObj) => { - return { - floor: bidRequest.floors.values['banner|640x480'], - currency: floorObj.currency, - mediaType: floorObj.mediaType - } - }; - - bidRequest.floors = { - currency: 'EUR', - values: { - 'banner|640x480': 15.07 - } - }; - const request = buildRequest(bidRequest); - expect(request.data.params.bidfloor).to.equal(15.07); - }); - describe('interpretResponse', () => { it('banner: should get correct bid response', () => { const serverResponse = [ diff --git a/test/spec/modules/otmBidAdapter_spec.js b/test/spec/modules/otmBidAdapter_spec.js deleted file mode 100644 index ce033d0fba5..00000000000 --- a/test/spec/modules/otmBidAdapter_spec.js +++ /dev/null @@ -1,88 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/otmBidAdapter'; - -describe('otmBidAdapter', function () { - it('pub_params', function () { - expect(spec.isBidRequestValid({ - bidder: 'otm', - params: { - tid: '123', - bidfloor: 20 - } - })).to.equal(true); - }); - - it('generated_params common case', function () { - const bidRequestData = [{ - bidId: 'bid1234', - bidder: 'otm', - params: { - tid: '123', - bidfloor: 20, - domain: 'github.com' - }, - sizes: [[240, 400]] - }]; - - const request = spec.buildRequests(bidRequestData); - const req_data = request[0].data; - - expect(req_data.bidid).to.equal('bid1234'); - expect(req_data.domain).to.equal('github.com'); - }); - - it('generated_params should return top level origin as domain if not defined', function () { - const bidRequestData = [{ - bidId: 'bid1234', - bidder: 'otm', - params: { - tid: '123', - bidfloor: 20 - }, - sizes: [[240, 400]] - }]; - - const bidderRequest = {refererInfo: {referer: `https://github.com:3000/`}} - - const request = spec.buildRequests(bidRequestData, bidderRequest); - const req_data = request[0].data; - - expect(req_data.domain).to.equal(`github.com:3000`); - }); - - it('response_params common case', function () { - const bidRequestData = { - data: { - bidId: 'bid1234' - } - }; - - const serverResponse = { - body: [ - { - 'auctionid': '3c6f8e22-541b-485c-9214-e974d9fb1b6f', - 'cpm': 847.097, - 'ad': 'test html', - 'w': 240, - 'h': 400, - 'currency': 'RUB', - 'ttl': 300, - 'creativeid': '1_7869053', - 'bidid': '101f211def7c99', - 'transactionid': 'transaction_id_1' - } - ] - }; - - const bids = spec.interpretResponse(serverResponse, bidRequestData); - expect(bids).to.have.lengthOf(1); - const bid = bids[0]; - expect(bid.cpm).to.equal(847.097); - expect(bid.currency).to.equal('RUB'); - expect(bid.width).to.equal(240); - expect(bid.height).to.equal(400); - expect(bid.netRevenue).to.equal(true); - expect(bid.requestId).to.equal('101f211def7c99'); - expect(bid.ad).to.equal('test html'); - }); -}); diff --git a/test/spec/modules/outbrainBidAdapter_spec.js b/test/spec/modules/outbrainBidAdapter_spec.js index 5dbdd049d82..a5f23240a7c 100644 --- a/test/spec/modules/outbrainBidAdapter_spec.js +++ b/test/spec/modules/outbrainBidAdapter_spec.js @@ -2,7 +2,6 @@ import {expect} from 'chai'; import {spec} from 'modules/outbrainBidAdapter.js'; import {config} from 'src/config.js'; import {server} from 'test/mocks/xhr'; -import { createEidsArray } from 'modules/userId/eids.js'; describe('Outbrain Adapter', function () { describe('Bid request and response', function () { @@ -100,38 +99,6 @@ describe('Outbrain Adapter', function () { } expect(spec.isBidRequestValid(bid)).to.equal(false) }) - it('should fail if tag id is not string', function () { - const bid = { - bidder: 'outbrain', - params: { - tagid: 123 - }, - ...nativeBidRequestParams, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - it('should fail if badv does not include strings', function () { - const bid = { - bidder: 'outbrain', - params: { - tagid: 123, - badv: ['a', 2, 'c'] - }, - ...nativeBidRequestParams, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - it('should fail if bcat does not include strings', function () { - const bid = { - bidder: 'outbrain', - params: { - tagid: 123, - bcat: ['a', 2, 'c'] - }, - ...nativeBidRequestParams, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) it('should succeed with outbrain config', function () { const bid = { bidder: 'outbrain', @@ -377,80 +344,6 @@ describe('Outbrain Adapter', function () { config.resetConfig() }); - - it('should pass extended ids', function () { - let bidRequest = { - bidId: 'bidId', - params: {}, - userIdAsEids: createEidsArray({ - idl_env: 'id-value', - }), - ...commonBidRequest, - }; - - let res = spec.buildRequests([bidRequest], commonBidderRequest); - const resData = JSON.parse(res.data) - expect(resData.user.ext.eids).to.deep.equal([ - {source: 'liveramp.com', uids: [{id: 'id-value', atype: 3}]} - ]); - }); - - it('should pass bidfloor', function () { - const bidRequest = { - ...commonBidRequest, - ...nativeBidRequestParams, - } - bidRequest.getFloor = function() { - return { - currency: 'USD', - floor: 1.23, - } - } - - const res = spec.buildRequests([bidRequest], commonBidderRequest) - const resData = JSON.parse(res.data) - expect(resData.imp[0].bidfloor).to.equal(1.23) - }); - - it('should transform string sizes to numbers', function () { - let bidRequest = { - bidId: 'bidId', - params: {}, - ...commonBidRequest, - ...nativeBidRequestParams, - }; - bidRequest.nativeParams.image.sizes = ['120', '100'] - - const expectedNativeAssets = { - assets: [ - { - required: 1, - id: 3, - img: { - type: 3, - w: 120, - h: 100 - } - }, - { - required: 1, - id: 0, - title: {} - }, - { - required: 0, - id: 5, - data: { - type: 1 - } - } - ] - } - - let res = spec.buildRequests([bidRequest], commonBidderRequest); - const resData = JSON.parse(res.data) - expect(resData.imp[0].native.request).to.equal(JSON.stringify(expectedNativeAssets)); - }); }) describe('interpretResponse', function () { @@ -471,7 +364,7 @@ describe('Outbrain Adapter', function () { impid: '1', price: 1.1, nurl: 'http://example.com/win/${AUCTION_PRICE}', - adm: '{"ver":"1.2","assets":[{"id":3,"required":1,"img":{"url":"http://example.com/img/url","w":120,"h":100}},{"id":0,"required":1,"title":{"text":"Test title"}},{"id":5,"data":{"value":"Test sponsor"}}],"privacy":"http://example.com/privacy","link":{"url":"http://example.com/click/url"},"eventtrackers":[{"event":1,"method":1,"url":"http://example.com/impression"}]}', + adm: '{"ver":"1.2","assets":[{"id":3,"required":1,"img":{"url":"http://example.com/img/url","w":120,"h":100}},{"id":0,"required":1,"title":{"text":"Test title"}},{"id":5,"data":{"value":"Test sponsor"}}],"link":{"url":"http://example.com/click/url"},"eventtrackers":[{"event":1,"method":1,"url":"http://example.com/impression"}]}', adomain: [ 'example.com' ], @@ -524,8 +417,7 @@ describe('Outbrain Adapter', function () { sponsoredBy: 'Test sponsor', impressionTrackers: [ 'http://example.com/impression', - ], - privacyLink: 'http://example.com/privacy' + ] } } ] diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index 658af310ea5..f9941b41189 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -69,6 +69,8 @@ var validBidRequestsMulti = [ transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; +// use 'pubcid', 'tdid', 'id5id', 'parrableId', 'idl_env', 'criteoId' +// see http://prebid.org/dev-docs/modules/userId.html var validBidRequestsWithUserIdData = [ { adUnitCode: 'div-gpt-ad-1460505748561-0', @@ -289,6 +291,7 @@ var validBidRequests1OutstreamVideo2020 = [ } ]; +// WHEN sent as bidderRequest to buildRequests you should send the child: .bidderRequest var validBidderRequest1OutstreamVideo2020 = { bidderRequest: { auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', @@ -391,6 +394,7 @@ var validBidderRequest1OutstreamVideo2020 = { timeout: 3000 } }; +// WHEN sent as bidderRequest to buildRequests you should send the child: .bidderRequest var validBidderRequest = { bidderRequest: { auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', @@ -415,6 +419,11 @@ var validBidderRequest = { } }; +// bidder request with GDPR - change the values for testing: +// gdprConsent.gdprApplies (true/false) +// gdprConsent.vendorData.purposeConsents (make empty, make null, remove it) +// gdprConsent.vendorData.vendorConsents (remove 524, remove all, make the element null, remove it) +// WHEN sent as bidderRequest to buildRequests you should send the child: .bidderRequest var bidderRequestWithFullGdpr = { bidderRequest: { auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', @@ -503,6 +512,7 @@ var gdpr1 = { 'gdprApplies': true }; +// simulating the Mirror var bidderRequestWithPartialGdpr = { bidderRequest: { auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', @@ -548,6 +558,7 @@ var bidderRequestWithPartialGdpr = { } }; +// make sure the impid matches the request bidId var validResponse = { 'body': { 'id': 'd6198807-7a53-4141-b2db-d2cb754d68ba', @@ -1102,6 +1113,7 @@ var multiRequest1 = [ } ]; +// WHEN sent as bidderRequest to buildRequests you should send the child: .bidderRequest var multiBidderRequest1 = { bidderRequest: { 'bidderCode': 'ozone', @@ -1495,6 +1507,7 @@ var multiResponse1 = { describe('ozone Adapter', function () { describe('isBidRequestValid', function () { + // A test ad unit that will consistently return test creatives let validBidReq = { bidder: BIDDER_CODE, params: { @@ -1928,6 +1941,7 @@ describe('ozone Adapter', function () { const request = spec.buildRequests(validBidRequestsNoSizes, validBidderRequest.bidderRequest); expect(request).to.be.a('array'); expect(request[0]).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); + // need to reset the singleRequest config flag: config.setConfig({'ozone': {'singleRequest': true}}); }); @@ -1951,6 +1965,7 @@ describe('ozone Adapter', function () { expect(payload.user.ext.consent).to.equal(consentString); }); + // mirror it('should add gdpr consent information to the request when vendorData is missing vendorConsents (Mirror)', function () { let consentString = 'BOcocyaOcocyaAfEYDENCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NphLgA=='; let bidderRequest = validBidderRequest.bidderRequest; @@ -2003,6 +2018,7 @@ describe('ozone Adapter', function () { }; let bidRequests = validBidRequests; + // values from http://prebid.org/dev-docs/modules/userId.html#pubcommon-id bidRequests[0]['userId'] = { 'digitrustid': {data: {id: 'DTID', keyv: 4, privacy: {optout: false}, producer: 'ABC', version: 2}}, 'id5id': { uid: '1111', ext: { linkType: 2, abTestingControlGroup: false } }, @@ -2022,11 +2038,13 @@ describe('ozone Adapter', function () { it('should pick up the value of pubcid when built using the pubCommonId module (not userId)', function () { let bidRequests = validBidRequests; + // values from http://prebid.org/dev-docs/modules/userId.html#pubcommon-id bidRequests[0]['userId'] = { 'digitrustid': {data: {id: 'DTID', keyv: 4, privacy: {optout: false}, producer: 'ABC', version: 2}}, 'id5id': { uid: '1111', ext: { linkType: 2, abTestingControlGroup: false } }, 'idl_env': '3333', 'parrableid': 'eidVersion.encryptionKeyReference.encryptedValue', + // 'pubcid': '5555', // remove pubcid from here to emulate the OLD module & cause the failover code to kick in 'tdid': '6666', 'sharedid': {'id': '01EAJWWNEPN3CYMM5N8M5VXY22', 'third': '01EAJWWNEPN3CYMM5N8M5VXY22'} }; @@ -2152,6 +2170,7 @@ describe('ozone Adapter', function () { }); it('should use oztestmode GET value if set', function() { var specMock = utils.deepClone(spec); + // mock the getGetParametersAsObject function to simulate GET parameters for oztestmode: specMock.getGetParametersAsObject = function() { return {'oztestmode': 'mytestvalue_123'}; }; @@ -2162,6 +2181,7 @@ describe('ozone Adapter', function () { }); it('should pass through GET params if present: ozf, ozpf, ozrp, ozip', function() { var specMock = utils.deepClone(spec); + // mock the getGetParametersAsObject function to simulate GET parameters : specMock.getGetParametersAsObject = function() { return {ozf: '1', ozpf: '0', ozrp: '2', ozip: '123'}; }; @@ -2174,6 +2194,7 @@ describe('ozone Adapter', function () { }); it('should pass through GET params if present: ozf, ozpf, ozrp, ozip with alternative values', function() { var specMock = utils.deepClone(spec); + // mock the getGetParametersAsObject function to simulate GET parameters : specMock.getGetParametersAsObject = function() { return {ozf: 'false', ozpf: 'true', ozrp: 'xyz', ozip: 'hello'}; }; @@ -2186,6 +2207,7 @@ describe('ozone Adapter', function () { }); it('should use oztestmode GET value if set, even if there is no customdata in config', function() { var specMock = utils.deepClone(spec); + // mock the getGetParametersAsObject function to simulate GET parameters for oztestmode: specMock.getGetParametersAsObject = function() { return {'oztestmode': 'mytestvalue_123'}; }; @@ -2195,6 +2217,7 @@ describe('ozone Adapter', function () { expect(data.imp[0].ext.ozone.customData[0].targeting.oztestmode).to.equal('mytestvalue_123'); }); it('should use GET values auction=dev & cookiesync=dev if set', function() { + // mock the getGetParametersAsObject function to simulate GET parameters for oztestmode: var specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { return {}; @@ -2205,6 +2228,8 @@ describe('ozone Adapter', function () { let cookieUrl = specMock.getCookieSyncUrl(); expect(cookieUrl).to.equal('https://elb.the-ozone-project.com/static/load-cookie.html'); + // now mock the response from getGetParametersAsObject & do the request again + specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { return {'auction': 'dev', 'cookiesync': 'dev'}; @@ -2216,6 +2241,7 @@ describe('ozone Adapter', function () { expect(cookieUrl).to.equal('https://test.ozpr.net/static/load-cookie.html'); }); it('should use a valid ozstoredrequest GET value if set to override the placementId values, and set oz_rw if we find it', function() { + // mock the getGetParametersAsObject function to simulate GET parameters for ozstoredrequest: var specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { return {'ozstoredrequest': '1122334455'}; // 10 digits are valid @@ -2226,6 +2252,7 @@ describe('ozone Adapter', function () { expect(data.imp[0].ext.prebid.storedrequest.id).to.equal('1122334455'); }); it('should NOT use an invalid ozstoredrequest GET value if set to override the placementId values, and set oz_rw to 0', function() { + // mock the getGetParametersAsObject function to simulate GET parameters for ozstoredrequest: var specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { return {'ozstoredrequest': 'BADVAL'}; // 10 digits are valid @@ -2397,26 +2424,6 @@ describe('ozone Adapter', function () { expect(utils.deepAccess(payload, 'imp.0.floor.banner.floor')).to.equal(0.8); config.resetConfig(); }); - - it('handles schain object in each bidrequest (will be the same in each br)', function () { - let br = JSON.parse(JSON.stringify(validBidRequests)); - let schainConfigObject = { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'bidderA.com', - 'sid': '00001', - 'hp': 1 - } - ] - }; - br[0]['schain'] = schainConfigObject; - const request = spec.buildRequests(br, validBidderRequest.bidderRequest); - const data = JSON.parse(request.data); - expect(data.source.ext).to.haveOwnProperty('schain'); - expect(data.source.ext.schain).to.deep.equal(schainConfigObject); // .deep.equal() : Target object deeply (but not strictly) equals `{a: 1}` - }); }); describe('interpretResponse', function () { @@ -2617,6 +2624,7 @@ describe('ozone Adapter', function () { expect(result[1]['impid']).to.equal('3025f169863b7f8'); expect(result[1]['id']).to.equal('18552976939844999'); expect(result[1]['adserverTargeting']['oz_ozappnexus_adId']).to.equal('3025f169863b7f8-0-oz-2'); + // change the bid values so a different second bid for an impid by the same bidder gets dropped validres = JSON.parse(JSON.stringify(multiResponse1)); validres.body.seatbid[0].bid[1].price = 1.1; validres.body.seatbid[0].bid[1].cpm = 1.1; @@ -2639,6 +2647,7 @@ describe('ozone Adapter', function () { expect(result).to.be.empty; }); it('should append the various values if they exist', function() { + // get the cookie bag populated spec.buildRequests(validBidRequests, validBidderRequest.bidderRequest); const result = spec.getUserSyncs({iframeEnabled: true}, 'good server response', gdpr1); expect(result).to.be.an('array'); @@ -2648,12 +2657,14 @@ describe('ozone Adapter', function () { expect(result[0].url).to.include('gdpr_consent=BOh7mtYOh7mtYAcABBENCU-AAAAncgPIXJiiAoao0PxBFkgCAC8ACIAAQAQQAAIAAAIAAAhBGAAAQAQAEQgAAAAAAABAAAAAAAAAAAAAAACAAAAAAAACgAAAAABAAAAQAAAAAAA'); }); it('should append ccpa (usp data)', function() { + // get the cookie bag populated spec.buildRequests(validBidRequests, validBidderRequest.bidderRequest); const result = spec.getUserSyncs({iframeEnabled: true}, 'good server response', gdpr1, '1YYN'); expect(result).to.be.an('array'); expect(result[0].url).to.include('usp_consent=1YYN'); }); it('should use "" if no usp is sent to cookieSync', function() { + // get the cookie bag populated spec.buildRequests(validBidRequests, validBidderRequest.bidderRequest); const result = spec.getUserSyncs({iframeEnabled: true}, 'good server response', gdpr1); expect(result).to.be.an('array'); @@ -2876,27 +2887,4 @@ describe('ozone Adapter', function () { expect(response[1].bid.length).to.equal(2); }); }); - /** - * spec.getWhitelabelConfigItem test - get a config value for a whitelabelled bidder, - * from a standard ozone.oz_xxxx_yyy string - */ - describe('getWhitelabelConfigItem', function() { - it('should fetch the whitelabelled equivalent config value correctly', function () { - var specMock = utils.deepClone(spec); - config.setConfig({'ozone': {'oz_omp_floor': 'ozone-floor-value'}}); - config.setConfig({'markbidder': {'mb_omp_floor': 'markbidder-floor-value'}}); - specMock.propertyBag.whitelabel = {bidder: 'ozone', keyPrefix: 'oz'}; - let testKey = 'ozone.oz_omp_floor'; - let ozone_value = specMock.getWhitelabelConfigItem(testKey); - expect(ozone_value).to.equal('ozone-floor-value'); - specMock.propertyBag.whitelabel = {bidder: 'markbidder', keyPrefix: 'mb'}; - let markbidder_config = specMock.getWhitelabelConfigItem(testKey); - expect(markbidder_config).to.equal('markbidder-floor-value'); - config.setConfig({'markbidder': {'singleRequest': 'markbidder-singlerequest-value'}}); - let testKey2 = 'ozone.singleRequest'; - let markbidder_config2 = specMock.getWhitelabelConfigItem(testKey2); - expect(markbidder_config2).to.equal('markbidder-singlerequest-value'); - config.resetConfig(); - }); - }); }); diff --git a/test/spec/modules/parrableIdSystem_spec.js b/test/spec/modules/parrableIdSystem_spec.js index a6e6185bbb2..44118fb50de 100644 --- a/test/spec/modules/parrableIdSystem_spec.js +++ b/test/spec/modules/parrableIdSystem_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import {find} from 'src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; import { config } from 'src/config.js'; import * as utils from 'src/utils.js'; import { newStorageManager } from 'src/storageManager.js'; @@ -8,7 +8,6 @@ import { uspDataHandler } from 'src/adapterManager.js'; import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; import { parrableIdSubmodule } from 'modules/parrableIdSystem.js'; import { server } from 'test/mocks/xhr.js'; -import {mockGdprConsent} from '../../helpers/consentData.js'; const storage = newStorageManager(); @@ -640,22 +639,18 @@ describe('Parrable ID System', function() { describe('userId requestBids hook', function() { let adUnits; - let sandbox; beforeEach(function() { - sandbox = sinon.sandbox.create(); - mockGdprConsent(sandbox); adUnits = [getAdUnitMock()]; writeParrableCookie({ eid: P_COOKIE_EID, ibaOptout: true }); - init(config); setSubmoduleRegistry([parrableIdSubmodule]); + init(config); config.setConfig(getConfigMock()); }); afterEach(function() { removeParrableCookie(); storage.setCookie(P_COOKIE_NAME, '', EXPIRED_COOKIE_DATE); - sandbox.restore(); }); it('when a stored Parrable ID exists it is added to bids', function(done) { diff --git a/test/spec/modules/permutiveRtdProvider_spec.js b/test/spec/modules/permutiveRtdProvider_spec.js index 6b44ec2b065..7cf6b66f839 100644 --- a/test/spec/modules/permutiveRtdProvider_spec.js +++ b/test/spec/modules/permutiveRtdProvider_spec.js @@ -51,46 +51,6 @@ describe('permutiveRtdProvider', function () { }]) }) }) - it('should include ortb2 user data transformation for IAB audience taxonomy', function() { - const moduleConfig = getConfig() - const bidderConfig = config.getBidderConfig() - const acBidders = moduleConfig.params.acBidders - const expectedTargetingData = transformedTargeting().ac.map(seg => { - return { id: seg } - }) - - Object.assign( - moduleConfig.params, - { - transformations: [{ - id: 'iab', - config: { - segtax: 4, - iabIds: { - 1000001: '9000009', - 1000002: '9000008' - } - } - }] - } - ) - - setBidderRtb({}, moduleConfig) - - acBidders.forEach(bidder => { - expect(bidderConfig[bidder].ortb2.user.data).to.deep.include.members([ - { - name: 'permutive.com', - segment: expectedTargetingData - }, - { - name: 'permutive.com', - ext: { segtax: 4 }, - segment: [{ id: '9000009' }, { id: '9000008' }] - } - ]) - }) - }) it('should not overwrite ortb2 config', function () { const moduleConfig = getConfig() const bidderConfig = config.getBidderConfig() @@ -118,15 +78,7 @@ describe('permutiveRtdProvider', function () { config: sampleOrtbConfig }) - const transformedUserData = { - name: 'transformation', - ext: { test: true }, - segment: [1, 2, 3] - } - - setBidderRtb({}, moduleConfig, { - testTransformation: userData => transformedUserData - }) + setBidderRtb({}, moduleConfig) acBidders.forEach(bidder => { expect(bidderConfig[bidder].ortb2.site.name).to.equal(sampleOrtbConfig.ortb2.site.name) @@ -341,10 +293,6 @@ describe('permutiveRtdProvider', function () { expect(isAcEnabled({ params: { acBidders: ['ozone'] } }, 'ozone')).to.equal(true) expect(isAcEnabled({ params: { acBidders: ['kjdvb'] } }, 'ozone')).to.equal(false) }) - it('checks if AC is enabled for Index', function () { - expect(isAcEnabled({ params: { acBidders: ['ix'] } }, 'ix')).to.equal(true) - expect(isAcEnabled({ params: { acBidders: ['kjdvb'] } }, 'ix')).to.equal(false) - }) }) }) @@ -365,7 +313,7 @@ function getConfig () { name: 'permutive', waitForIt: true, params: { - acBidders: ['appnexus', 'rubicon', 'ozone', 'trustx', 'ix'], + acBidders: ['appnexus', 'rubicon', 'ozone', 'trustx'], maxSegs: 500 } } @@ -378,7 +326,7 @@ function transformedTargeting () { ac: [...data._pcrprs, ...data._ppam, ...data._psegs.filter(seg => seg >= 1000000)], appnexus: data._papns, rubicon: data._prubicons, - gam: data._pdfps, + gam: data._pdfps } } diff --git a/test/spec/modules/pilotxBidAdapter_spec.js b/test/spec/modules/pilotxBidAdapter_spec.js deleted file mode 100644 index 2ef31c0a8f5..00000000000 --- a/test/spec/modules/pilotxBidAdapter_spec.js +++ /dev/null @@ -1,244 +0,0 @@ -// import or require modules necessary for the test, e.g.: -import { expect } from 'chai'; // may prefer 'assert' in place of 'expect' -import { spec } from '../../../modules/pilotxBidAdapter.js'; - -describe('pilotxAdapter', function () { - describe('isBidRequestValid', function () { - let banner; - beforeEach(function () { - banner = { - bidder: 'pilotx', - adUnitCode: 'adunit-test', - mediaTypes: { banner: {} }, - sizes: [[300, 250], [468, 60]], - bidId: '2de8c82e30665a', - params: { - placementId: '1' - } - }; - }); - - it('should return false if sizes is empty', function () { - banner.sizes = [] - expect(spec.isBidRequestValid(banner)).to.equal(false); - }); - it('should return true if all is valid/ is not empty', function () { - expect(spec.isBidRequestValid(banner)).to.equal(true); - }); - it('should return false if there is no placement id found', function () { - banner.params = {} - expect(spec.isBidRequestValid(banner)).to.equal(false); - }); - it('should return false if sizes is empty', function () { - banner.sizes = [] - expect(spec.isBidRequestValid(banner)).to.equal(false); - }); - it('should return false for no size and empty params', function() { - const emptySizes = { - bidder: 'pilotx', - adUnitCode: 'adunit-test', - mediaTypes: { banner: {} }, - bidId: '2de8c82e30665a', - params: { - placementId: '1', - sizes: [] - } - }; - expect(spec.isBidRequestValid(emptySizes)).to.equal(false); - }) - it('should return true for no size and valid size params', function() { - const emptySizes = { - bidder: 'pilotx', - adUnitCode: 'adunit-test', - mediaTypes: { banner: {} }, - bidId: '2de8c82e30665a', - params: { - placementId: '1', - sizes: [[300, 250], [468, 60]] - } - }; - expect(spec.isBidRequestValid(emptySizes)).to.equal(true); - }) - it('should return false for no size items', function() { - const emptySizes = { - bidder: 'pilotx', - adUnitCode: 'adunit-test', - mediaTypes: { banner: {} }, - bidId: '2de8c82e30665a', - params: { - placementId: '1' - } - }; - expect(spec.isBidRequestValid(emptySizes)).to.equal(false); - }) - }); - - describe('buildRequests', function () { - const mockRequest = { refererInfo: {} }; - const mockRequestGDPR = { - refererInfo: {}, - gdprConsent: { - consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', - gdprApplies: true - } - - } - const mockVideo1 = [{ - adUnitCode: 'video1', - auctionId: '01618029-7ae9-4e98-a73a-1ed0c817f414', - bidId: '2a59588c0114fa', - bidRequestsCount: 1, - bidder: 'pilotx', - bidderRequestId: '1f6b4ba2039726', - bidderRequestsCount: 1, - bidderWinsCount: 0, - crumbs: { pubcid: 'de5240ef-ff80-4b55-8837-26a11cfbf64c' }, - mediaTypes: { - video: { - context: 'instream', - mimes: ['video/mp4'], - playbackmethod: [2], - playerSize: [[640, 480]], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - skip: 1 - } - }, - ortb2Imp: { - ext: { - data: { - pbadslot: 'video1' - } - } - }, - params: { placementId: '379' }, - sizes: [[640, 480]], - src: 'client', - transactionId: 'fec9f2ff-da13-4921-8437-8d679c2be7fe', - }]; - const mockVideo2 = [{ - adUnitCode: 'video1', - auctionId: '01618029-7ae9-4e98-a73a-1ed0c817f414', - bidId: '2a59588c0114fa', - bidRequestsCount: 1, - bidder: 'pilotx', - bidderRequestId: '1f6b4ba2039726', - bidderRequestsCount: 1, - bidderWinsCount: 0, - crumbs: { pubcid: 'de5240ef-ff80-4b55-8837-26a11cfbf64c' }, - mediaTypes: { - video: { - context: 'instream', - mimes: ['video/mp4'], - playbackmethod: [2], - playerSize: [[640, 480]], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - skip: 1 - } - }, - ortb2Imp: { - ext: { - data: { - pbadslot: 'video1' - } - } - }, - params: { placementId: '379' }, - sizes: [640, 480], - src: 'client', - transactionId: 'fec9f2ff-da13-4921-8437-8d679c2be7fe', - }]; - it('should return correct response', function () { - const builtRequest = spec.buildRequests(mockVideo1, mockRequest) - let builtRequestData = builtRequest.data - let data = JSON.parse(builtRequestData) - expect(data['379'].bidId).to.equal(mockVideo1[0].bidId) - }); - it('should return correct response for only array of size', function () { - const builtRequest = spec.buildRequests(mockVideo2, mockRequest) - let builtRequestData = builtRequest.data - let data = JSON.parse(builtRequestData) - expect(data['379'].sizes[0][0]).to.equal(mockVideo2[0].sizes[0]) - expect(data['379'].sizes[0][1]).to.equal(mockVideo2[0].sizes[1]) - }); - it('should be valid and pass gdpr items correctly', function () { - const builtRequest = spec.buildRequests(mockVideo2, mockRequestGDPR) - let builtRequestData = builtRequest.data - let data = JSON.parse(builtRequestData) - expect(data['379'].gdprConsentString).to.equal(mockRequestGDPR.gdprConsent.consentString) - expect(data['379'].gdprConsentRequired).to.equal(mockRequestGDPR.gdprConsent.gdprApplies) - }); - }); - describe('interpretResponse', function () { - const bidRequest = {} - const serverResponse = { - cpm: 2.5, - creativeId: 'V9060', - currency: 'US', - height: 480, - mediaType: 'video', - netRevenue: false, - requestId: '273b39c74069cb', - ttl: 3000, - vastUrl: 'http://testadserver.com/ads?&k=60cd901ad8ab70c9cedf373cb17b93b8&pid=379&tid=91342717', - width: 640 - } - const serverResponseVideo = { - body: serverResponse - } - const serverResponse2 = { - cpm: 2.5, - creativeId: 'V9060', - currency: 'US', - height: 480, - mediaType: 'banner', - netRevenue: false, - requestId: '273b39c74069cb', - ttl: 3000, - vastUrl: 'http://testadserver.com/ads?&k=60cd901ad8ab70c9cedf373cb17b93b8&pid=379&tid=91342717', - width: 640 - } - const serverResponseBanner = { - body: serverResponse2 - } - it('should be valid from bidRequest for video', function () { - const bidResponses = spec.interpretResponse(serverResponseVideo, bidRequest) - expect(bidResponses[0].requestId).to.equal(serverResponse.requestId) - expect(bidResponses[0].cpm).to.equal(serverResponse.cpm) - expect(bidResponses[0].width).to.equal(serverResponse.width) - expect(bidResponses[0].height).to.equal(serverResponse.height) - expect(bidResponses[0].creativeId).to.equal(serverResponse.creativeId) - expect(bidResponses[0].currency).to.equal(serverResponse.currency) - expect(bidResponses[0].netRevenue).to.equal(serverResponse.netRevenue) - expect(bidResponses[0].ttl).to.equal(serverResponse.ttl) - expect(bidResponses[0].vastUrl).to.equal(serverResponse.vastUrl) - expect(bidResponses[0].mediaType).to.equal(serverResponse.mediaType) - expect(bidResponses[0].meta.mediaType).to.equal(serverResponse.mediaType) - }); - it('should be valid from bidRequest for banner', function () { - const bidResponses = spec.interpretResponse(serverResponseBanner, bidRequest) - expect(bidResponses[0].requestId).to.equal(serverResponse2.requestId) - expect(bidResponses[0].cpm).to.equal(serverResponse2.cpm) - expect(bidResponses[0].width).to.equal(serverResponse2.width) - expect(bidResponses[0].height).to.equal(serverResponse2.height) - expect(bidResponses[0].creativeId).to.equal(serverResponse2.creativeId) - expect(bidResponses[0].currency).to.equal(serverResponse2.currency) - expect(bidResponses[0].netRevenue).to.equal(serverResponse2.netRevenue) - expect(bidResponses[0].ttl).to.equal(serverResponse2.ttl) - expect(bidResponses[0].ad).to.equal(serverResponse2.ad) - expect(bidResponses[0].mediaType).to.equal(serverResponse2.mediaType) - expect(bidResponses[0].meta.mediaType).to.equal(serverResponse2.mediaType) - }); - }); - describe('setPlacementID', function () { - const multiplePlacementIds = ['380', '381'] - it('should be valid with an array of placement ids passed', function () { - const placementID = spec.setPlacementID(multiplePlacementIds) - expect(placementID).to.equal('380#381') - }); - it('should be valid with single placement ID passed', function () { - const placementID = spec.setPlacementID('381') - expect(placementID).to.equal('381') - }); - }); - // Add other `describe` or `it` blocks as necessary -}); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 3edb89dd573..dab68960644 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -4,21 +4,10 @@ import adapterManager from 'src/adapterManager.js'; import * as utils from 'src/utils.js'; import { ajax } from 'src/ajax.js'; import { config } from 'src/config.js'; -import * as events from 'src/events.js'; +import events from 'src/events.js'; import CONSTANTS from 'src/constants.json'; import { server } from 'test/mocks/xhr.js'; import { createEidsArray } from 'modules/userId/eids.js'; -import { deepAccess, deepClone } from 'src/utils.js'; -import 'modules/appnexusBidAdapter.js' // appnexus alias test -import 'modules/rubiconBidAdapter.js' // rubicon alias test -import 'src/prebid.js' // $$PREBID_GLOBAL$$.aliasBidder test -import 'modules/currency.js' // adServerCurrency test -import { hook } from '../../../src/hook.js'; -import { decorateAdUnitsWithNativeParams } from '../../../src/native.js'; -import { auctionManager } from '../../../src/auctionManager.js'; -import { stubAuctionIndex } from '../../helpers/indexStub.js'; -import { registerBidder } from 'src/adapters/bidderFactory.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; let CONFIG = { accountId: '1', @@ -285,7 +274,7 @@ const RESPONSE_OPENRTB = { 'win': 'http://wurl.org?id=333' }, 'meta': { - 'dchain': { 'ver': '1.0', 'complete': 0, 'nodes': [{ 'asi': 'magnite.com', 'bsid': '123456789', }] } + 'dchain': { 'ver': '1.0', 'complete': 0, 'nodes': [ { 'asi': 'magnite.com', 'bsid': '123456789', } ] } } }, 'bidder': { @@ -458,18 +447,6 @@ describe('S2S Adapter', function () { addBidResponse = sinon.spy(), done = sinon.spy(); - function prepRequest(req) { - req.ad_units.forEach((adUnit) => { - delete adUnit.nativeParams - }); - decorateAdUnitsWithNativeParams(req.ad_units); - } - - before(() => { - hook.ready(); - prepRequest(REQUEST); - }); - beforeEach(function () { config.resetConfig(); adapter = new Adapter(); @@ -530,18 +507,7 @@ describe('S2S Adapter', function () { resetSyncedStatus(); }); - it('should set id to auction ID and source.tid to tid', function () { - config.setConfig({ s2sConfig: CONFIG }); - - adapter.callBids(OUTSTREAM_VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); - - const requestBid = JSON.parse(server.requests[0].requestBody); - expect(requestBid.id).to.equal('173afb6d132ba3'); - expect(requestBid.source).to.be.an('object'); - expect(requestBid.source.tid).to.equal('437fbbf5-33f5-487a-8e16-a7112903cfe5'); - }); - - it('should block request if config did not define p1Consent URL in endpoint object config', function () { + it('should block request if config did not define p1Consent URL in endpoint object config', function() { let badConfig = utils.deepClone(CONFIG); badConfig.endpoint = { noP1Consent: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }; config.setConfig({ s2sConfig: badConfig }); @@ -554,7 +520,7 @@ describe('S2S Adapter', function () { expect(server.requests.length).to.equal(0); }); - it('should block request if config did not define noP1Consent URL in endpoint object config', function () { + it('should block request if config did not define noP1Consent URL in endpoint object config', function() { let badConfig = utils.deepClone(CONFIG); badConfig.endpoint = { p1Consent: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }; config.setConfig({ s2sConfig: badConfig }); @@ -582,7 +548,7 @@ describe('S2S Adapter', function () { expect(server.requests.length).to.equal(0); }); - it('should block request if config did not define any URLs in endpoint object config', function () { + it('should block request if config did not define any URLs in endpoint object config', function() { let badConfig = utils.deepClone(CONFIG); badConfig.endpoint = {}; config.setConfig({ s2sConfig: badConfig }); @@ -984,11 +950,11 @@ describe('S2S Adapter', function () { ).to.be.true; // if getFloor does not return number - getFloorResponse = { currency: 'EUR', floor: 'not a number' }; + getFloorResponse = {currency: 'EUR', floor: 'not a number'}; runTest(undefined, undefined); // if getFloor does not return currency - getFloorResponse = { floor: 1.1 }; + getFloorResponse = {floor: 1.1}; runTest(undefined, undefined); }); @@ -1003,7 +969,7 @@ describe('S2S Adapter', function () { sinon.spy(BID_REQUESTS[0].bids[0], 'getFloor'); // returns USD and string floor - getFloorResponse = { currency: 'USD', floor: '1.23' }; + getFloorResponse = {currency: 'USD', floor: '1.23'}; runTest(1.23, 'USD'); // make sure getFloor was called expect( @@ -1013,7 +979,7 @@ describe('S2S Adapter', function () { ).to.be.true; // returns non USD and number floor - getFloorResponse = { currency: 'EUR', floor: 0.85 }; + getFloorResponse = {currency: 'EUR', floor: 0.85}; runTest(0.85, 'EUR'); }); @@ -1030,7 +996,7 @@ describe('S2S Adapter', function () { sinon.spy(BID_REQUESTS[0].bids[0], 'getFloor'); // returns USD and string floor - getFloorResponse = { currency: 'JPY', floor: 97.2 }; + getFloorResponse = {currency: 'JPY', floor: 97.2}; runTest(97.2, 'JPY'); // make sure getFloor was called with JPY expect( @@ -1039,205 +1005,6 @@ describe('S2S Adapter', function () { }) ).to.be.true; }); - - it('should find the floor when not all bidderRequests contain it', () => { - config.setConfig({ - s2sConfig: { - ...CONFIG, - bidders: ['b1', 'b2'] - }, - }); - const bidderRequests = [ - { - ...BID_REQUESTS[0], - bidderCode: 'b1', - bids: [{ - bidder: 'b1', - bidId: 1, - }] - }, - { - ...BID_REQUESTS[0], - bidderCode: 'b2', - bids: [{ - bidder: 'b2', - bidId: 2, - getFloor: () => ({ - currency: 'CUR', - floor: 123 - }) - }], - } - ]; - const adUnits = [ - { - code: 'au1', - transactionId: 't1', - mediaTypes: { - banner: {sizes: [1, 1]} - }, - bids: [{bidder: 'b1', bid_id: 1}] - }, - { - code: 'au2', - transactionId: 't2', - bids: [{bidder: 'b2', bid_id: 2}], - mediaTypes: { - banner: {sizes: [1, 1]} - } - } - ]; - const s2sReq = { - ...REQUEST, - ad_units: adUnits - } - - adapter.callBids(s2sReq, bidderRequests, addBidResponse, done, ajax); - - const pbsReq = JSON.parse(server.requests[server.requests.length - 1].requestBody); - const [imp1, imp2] = pbsReq.imp; - - expect(imp1.bidfloor).to.be.undefined; - expect(imp1.bidfloorcur).to.be.undefined; - - expect(imp2.bidfloor).to.eql(123); - expect(imp2.bidfloorcur).to.eql('CUR'); - }); - - describe('when different bids have different floors', () => { - let s2sReq; - beforeEach(() => { - config.setConfig({ - s2sConfig: { - ...CONFIG, - bidders: ['b1', 'b2', 'b3'] - }, - }); - BID_REQUESTS = [ - { - ...BID_REQUESTS[0], - bidderCode: 'b2', - bids: [{ - bidder: 'b2', - bidId: 2, - getFloor: () => ({ - currency: '1', - floor: 2 - }) - }], - }, - { - ...BID_REQUESTS[0], - bidderCode: 'b1', - bids: [{ - bidder: 'b1', - bidId: 1, - getFloor: () => ({ - floor: 10, - currency: '0.1' - }) - }] - }, - { - ...BID_REQUESTS[0], - bidderCode: 'b3', - bids: [{ - bidder: 'b3', - bidId: 3, - getFloor: () => ({ - currency: '10', - floor: 1 - }) - }], - } - ]; - s2sReq = { - ...REQUEST, - ad_units: [ - { - code: 'au1', - transactionId: 't1', - mediaTypes: { - banner: {sizes: [1, 1]} - }, - bids: [ - {bidder: 'b2', bid_id: 2}, - {bidder: 'b3', bid_id: 3}, - {bidder: 'b1', bid_id: 1}, - ] - } - ] - }; - }); - - Object.entries({ - 'cannot compute a floor': (bid) => { bid.getFloor = () => { throw new Error() } }, - 'does not set a floor': (bid) => { delete bid.getFloor; }, - }).forEach(([t, updateBid]) => { - it(`should not set pricefloor if any one of them ${t}`, () => { - updateBid(BID_REQUESTS[1].bids[0]); - adapter.callBids(s2sReq, BID_REQUESTS, addBidResponse, done, ajax); - const pbsReq = JSON.parse(server.requests[server.requests.length - 1].requestBody); - expect(pbsReq.imp[0].bidfloor).to.be.undefined; - expect(pbsReq.imp[0].bidfloorcur).to.be.undefined; - }); - }) - - Object.entries({ - 'is available': { - expectDesc: 'minimum after conversion', - expectedFloor: 10, - expectedCur: '0.1', - conversionFn: (amount, from, to) => { - from = parseFloat(from); - to = parseFloat(to); - return amount * from / to; - }, - }, - 'is not available': { - expectDesc: 'absolute minimum', - expectedFloor: 1, - expectedCur: '10', - conversionFn: null - }, - 'is not working': { - expectDesc: 'first', - expectedFloor: 2, - expectedCur: '1', - conversionFn: () => { - throw new Error(); - } - } - }).forEach(([t, {expectDesc, expectedFloor, expectedCur, conversionFn}]) => { - describe(`and currency conversion ${t}`, () => { - let mockConvertCurrency; - const origConvertCurrency = getGlobal().convertCurrency; - beforeEach(() => { - if (conversionFn) { - getGlobal().convertCurrency = mockConvertCurrency = sinon.stub().callsFake(conversionFn) - } else { - mockConvertCurrency = null; - delete getGlobal().convertCurrency; - } - }); - - afterEach(() => { - if (origConvertCurrency != null) { - getGlobal().convertCurrency = origConvertCurrency; - } else { - delete getGlobal().convertCurrency; - } - }) - - it(`should pick the ${expectDesc}`, () => { - adapter.callBids(s2sReq, BID_REQUESTS, addBidResponse, done, ajax); - const pbsReq = JSON.parse(server.requests[server.requests.length - 1].requestBody); - expect(pbsReq.imp[0].bidfloor).to.eql(expectedFloor); - expect(pbsReq.imp[0].bidfloorcur).to.eql(expectedCur); - }); - }); - }); - }); }); it('adds device.w and device.h even if the config lacks a device object', function () { @@ -1279,14 +1046,12 @@ describe('S2S Adapter', function () { 'assets': [ { 'required': 1, - 'id': 0, 'title': { 'len': 800 } }, { 'required': 1, - 'id': 1, 'img': { 'type': 3, 'w': 989, @@ -1295,7 +1060,6 @@ describe('S2S Adapter', function () { }, { 'required': 1, - 'id': 2, 'img': { 'type': 1, 'wmin': 10, @@ -1307,7 +1071,6 @@ describe('S2S Adapter', function () { }, { 'required': 1, - 'id': 3, 'data': { 'type': 1 } @@ -1318,19 +1081,6 @@ describe('S2S Adapter', function () { }); }); - it('should not include ext.aspectratios if adunit\'s aspect_ratios do not define radio_width and ratio_height', () => { - const req = deepClone(REQUEST); - req.ad_units[0].mediaTypes.native.icon.aspect_ratios[0] = { 'min_width': 1, 'min_height': 2 }; - prepRequest(req); - adapter.callBids(req, BID_REQUESTS, addBidResponse, done, ajax); - const nativeReq = JSON.parse(JSON.parse(server.requests[0].requestBody).imp[0].native.request); - const icons = nativeReq.assets.map((a) => a.img).filter((img) => img && img.type === 1); - expect(icons).to.have.length(1); - expect(icons[0].hmin).to.equal(2); - expect(icons[0].wmin).to.equal(1); - expect(deepAccess(icons[0], 'ext.aspectratios')).to.be.undefined; - }) - it('adds site if app is not present', function () { const _config = { s2sConfig: CONFIG, @@ -1424,22 +1174,16 @@ describe('S2S Adapter', function () { }); }); - it('skips pbs alias when skipPbsAliasing is enabled in adapter', function () { + it('skips pbs alias when skipPbsAliasing is enabled in adapter', function() { const s2sConfig = Object.assign({}, CONFIG, { endpoint: { p1Consent: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' } }); config.setConfig({ s2sConfig: s2sConfig }); - registerBidder({ - code: 'bidderCodeForTestSkipBPSAlias', - aliases: [{ - code: 'bidderCodeForTestSkipBPSAlias_Alias', - skipPbsAliasing: true - }] - }) + const aliasBidder = { - bidder: 'bidderCodeForTestSkipBPSAlias_Alias', + bidder: 'mediafuse', params: { aid: 123 } }; @@ -1476,7 +1220,7 @@ describe('S2S Adapter', function () { const alias = 'foobar_1'; const aliasBidder = { bidder: alias, - params: { aid: 1234567 } + params: { aid: 123456 } }; const request = utils.deepClone(REQUEST); @@ -1944,7 +1688,7 @@ describe('S2S Adapter', function () { maxbids: 2 }]; - config.setConfig({ multibid: multibid }); + config.setConfig({multibid: multibid}); adapter.callBids(REQUEST, bidRequests, addBidResponse, done, ajax); const parsedRequestBody = JSON.parse(server.requests[0].requestBody); @@ -1958,25 +1702,19 @@ describe('S2S Adapter', function () { adapter.callBids(s2sBidRequest, bidRequests, addBidResponse, done, ajax); const parsedRequestBody = JSON.parse(server.requests[0].requestBody); - expect(parsedRequestBody.ext.prebid.channel).to.deep.equal({ name: 'pbjs', version: 'v$prebid.version$' }); + expect(parsedRequestBody.ext.prebid.channel).to.deep.equal({name: 'pbjs', version: 'v$prebid.version$'}); }); - it('extPrebid is now mergedDeep -> should include default channel as well', () => { + it('does not set pbjs version in request if channel does exist in s2sConfig', () => { const s2sBidRequest = utils.deepClone(REQUEST); const bidRequests = utils.deepClone(BID_REQUESTS); - utils.deepSetValue(s2sBidRequest, 's2sConfig.extPrebid.channel', { test: 1 }); + utils.deepSetValue(s2sBidRequest, 's2sConfig.extPrebid.channel', {test: 1}); adapter.callBids(s2sBidRequest, bidRequests, addBidResponse, done, ajax); const parsedRequestBody = JSON.parse(server.requests[0].requestBody); - - // extPrebid is now deep merged with - expect(parsedRequestBody.ext.prebid.channel).to.deep.equal({ - name: 'pbjs', - test: 1, - version: 'v$prebid.version$' - }); + expect(parsedRequestBody.ext.prebid.channel).to.deep.equal({test: 1}); }); it('passes first party data in request', () => { @@ -2007,12 +1745,10 @@ describe('S2S Adapter', function () { interests: ['cars'] } }; - const bcat = ['IAB25', 'IAB7-39']; - const badv = ['blockedAdv-1.com', 'blockedAdv-2.com']; - const allowedBidders = ['rubicon', 'appnexus']; + const allowedBidders = [ 'rubicon', 'appnexus' ]; const expected = allowedBidders.map(bidder => ({ - bidders: [bidder], + bidders: [ bidder ], config: { ortb2: { site: { @@ -2033,26 +1769,19 @@ describe('S2S Adapter', function () { interests: ['cars'] } } - }, - bcat: ['IAB25', 'IAB7-39'], - badv: ['blockedAdv-1.com', 'blockedAdv-2.com'] + } } } })); - const commonContextExpected = utils.mergeDeep({ - 'page': 'http://mytestpage.com', - 'publisher': { 'id': '1' } - }, commonContext); + const commonContextExpected = utils.mergeDeep({'page': 'http://mytestpage.com', 'publisher': {'id': '1'}}, commonContext); - config.setConfig({ fpd: { context: commonContext, user: commonUser, badv, bcat } }); - config.setBidderConfig({ bidders: allowedBidders, config: { fpd: { context, user, bcat, badv } } }); + config.setConfig({ fpd: { context: commonContext, user: commonUser } }); + config.setBidderConfig({ bidders: allowedBidders, config: { fpd: { context, user } } }); adapter.callBids(s2sBidRequest, bidRequests, addBidResponse, done, ajax); const parsedRequestBody = JSON.parse(server.requests[0].requestBody); expect(parsedRequestBody.ext.prebid.bidderconfig).to.deep.equal(expected); expect(parsedRequestBody.site).to.deep.equal(commonContextExpected); expect(parsedRequestBody.user).to.deep.equal(commonUser); - expect(parsedRequestBody.badv).to.deep.equal(badv); - expect(parsedRequestBody.bcat).to.deep.equal(bcat); }); describe('pbAdSlot config', function () { @@ -2297,7 +2026,7 @@ describe('S2S Adapter', function () { }); it('should pass through default adserverTargeting if present in bidObject for video request', function () { - config.setConfig({ s2sConfig: CONFIG }); + config.setConfig({s2sConfig: CONFIG}); const cacheResponse = utils.deepClone(RESPONSE_OPENRTB); const targetingTestData = { hb_cache_path: '/cache', @@ -2319,7 +2048,7 @@ describe('S2S Adapter', function () { }); }); - it('should set the bidResponse currency to whats in the PBS response', function () { + it('should set the bidResponse currency to whats in the PBS response', function() { adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.requests[0].respond(200, {}, JSON.stringify(RESPONSE_OPENRTB)); sinon.assert.calledOnce(addBidResponse); @@ -2327,7 +2056,7 @@ describe('S2S Adapter', function () { expect(pbjsResponse).to.have.property('currency', 'EUR'); }); - it('should set the default bidResponse currency when not specified in OpenRTB', function () { + it('should set the default bidResponse currency when not specified in OpenRTB', function() { let modifiedResponse = utils.deepClone(RESPONSE_OPENRTB); modifiedResponse.cur = ''; adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -2639,8 +2368,11 @@ describe('S2S Adapter', function () { }); it('handles OpenRTB native responses', function () { - const stub = sinon.stub(auctionManager, 'index'); - stub.get(() => stubAuctionIndex({ adUnits: REQUEST.ad_units })); + sinon.stub(utils, 'getBidRequest').returns({ + adUnitCode: 'div-gpt-ad-1460505748561-0', + bidder: 'appnexus', + bidId: '123' + }); const s2sConfig = Object.assign({}, CONFIG, { endpoint: { p1Consent: 'https://prebidserverurl/openrtb2/auction?querystring=param' @@ -2663,81 +2395,7 @@ describe('S2S Adapter', function () { expect(response).to.have.property('requestId', '123'); expect(response).to.have.property('cpm', 10); - stub.restore(); - }); - - it('does not (by default) allow bids that were not requested', function () { - config.setConfig({ s2sConfig: CONFIG }); - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); - const response = deepClone(RESPONSE_OPENRTB); - response.seatbid[0].seat = 'unknown'; - server.requests[0].respond(200, {}, JSON.stringify(response)); - - expect(addBidResponse.called).to.be.false; - }); - - it('allows unrequested bids if config.allowUnknownBidderCodes', function () { - const cfg = { ...CONFIG, allowUnknownBidderCodes: true }; - config.setConfig({ s2sConfig: cfg }); - adapter.callBids({ ...REQUEST, s2sConfig: cfg }, BID_REQUESTS, addBidResponse, done, ajax); - const response = deepClone(RESPONSE_OPENRTB); - response.seatbid[0].seat = 'unknown'; - server.requests[0].respond(200, {}, JSON.stringify(response)); - - expect(addBidResponse.calledWith(sinon.match.any, sinon.match({ bidderCode: 'unknown' }))).to.be.true; - }); - - it('uses "null" request\'s ID for all responses, when a null request is present', function () { - const cfg = {...CONFIG, allowUnknownBidderCodes: true}; - config.setConfig({s2sConfig: cfg}); - const req = {...REQUEST, s2sConfig: cfg, ad_units: [{...REQUEST.ad_units[0], bids: [{bidder: null, bid_id: 'testId'}]}]}; - const bidReq = {...BID_REQUESTS[0], bidderCode: null, bids: [{...BID_REQUESTS[0].bids[0], bidder: null, bidId: 'testId'}]} - adapter.callBids(req, [bidReq], addBidResponse, done, ajax); - const response = deepClone(RESPONSE_OPENRTB); - response.seatbid[0].seat = 'storedImpression'; - server.requests[0].respond(200, {}, JSON.stringify(response)); - sinon.assert.calledWith(addBidResponse, sinon.match.any, sinon.match({bidderCode: 'storedImpression', requestId: 'testId'})) - }); - - it('copies ortb2Imp to response when there is only a null bid', () => { - const cfg = {...CONFIG}; - config.setConfig({s2sConfig: cfg}); - const ortb2Imp = {ext: {prebid: {storedrequest: 'value'}}}; - const req = {...REQUEST, s2sConfig: cfg, ad_units: [{...REQUEST.ad_units[0], bids: [{bidder: null, bid_id: 'testId'}], ortb2Imp}]}; - const bidReq = {...BID_REQUESTS[0], bidderCode: null, bids: [{...BID_REQUESTS[0].bids[0], bidder: null, bidId: 'testId'}]} - adapter.callBids(req, [bidReq], addBidResponse, done, ajax); - const actual = JSON.parse(server.requests[0].requestBody); - sinon.assert.match(actual.imp[0], sinon.match(ortb2Imp)); - }); - - describe('on sync requested with no cookie', () => { - let cfg, req, csRes; - - beforeEach(() => { - cfg = utils.deepClone(CONFIG); - req = utils.deepClone(REQUEST); - cfg.syncEndpoint = { p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync' }; - req.s2sConfig = cfg; - config.setConfig({ s2sConfig: cfg }); - csRes = utils.deepClone(RESPONSE_NO_COOKIE); - }); - - afterEach(() => { - resetSyncedStatus(); - }) - - Object.entries({ - iframe: () => utils.insertUserSyncIframe, - image: () => utils.triggerPixel, - }).forEach(([type, syncer]) => { - it(`passes timeout to ${type} syncs`, () => { - cfg.syncTimeout = 123; - csRes.bidder_status[0].usersync.type = type; - adapter.callBids(req, BID_REQUESTS, addBidResponse, done, ajax); - server.requests[0].respond(200, {}, JSON.stringify(csRes)); - expect(syncer().args[0]).to.include.members([123]); - }); - }); + utils.getBidRequest.restore(); }); }); @@ -2862,6 +2520,21 @@ describe('S2S Adapter', function () { sinon.assert.calledOnce(logErrorSpy); }); + it('should log an error when bidders is missing', function () { + const options = { + accountId: '1', + enabled: true, + timeout: 1000, + adapter: 's2s', + endpoint: { + p1Consent: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + } + }; + + config.setConfig({ s2sConfig: options }); + sinon.assert.calledOnce(logErrorSpy); + }); + it('should log an error when endpoint is missing', function () { const options = { accountId: '1', @@ -2902,14 +2575,8 @@ describe('S2S Adapter', function () { expect(vendorConfig).to.have.property('adapter', 'prebidServer'); expect(vendorConfig.bidders).to.deep.equal(['appnexus']); expect(vendorConfig.enabled).to.be.true; - expect(vendorConfig.endpoint).to.deep.equal({ - p1Consent: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', - noP1Consent: 'https://prebid.adnxs-simple.com/pbs/v1/openrtb2/auction' - }); - expect(vendorConfig.syncEndpoint).to.deep.equal({ - p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync', - noP1Consent: 'https://prebid.adnxs-simple.com/pbs/v1/cookie_sync' - }); + expect(vendorConfig.endpoint).to.deep.equal({p1Consent: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', noP1Consent: 'https://prebid.adnxs-simple.com/pbs/v1/openrtb2/auction'}); + expect(vendorConfig.syncEndpoint).to.deep.equal({p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync', noP1Consent: 'https://prebid.adnxs-simple.com/pbs/v1/cookie_sync'}); expect(vendorConfig).to.have.property('timeout', 750); }); @@ -2929,10 +2596,7 @@ describe('S2S Adapter', function () { expect(vendorConfig).to.have.property('adapter', 'prebidServer'); expect(vendorConfig.bidders).to.deep.equal(['appnexus']); expect(vendorConfig.enabled).to.be.true; - expect(vendorConfig.endpoint).to.deep.equal({ - p1Consent: 'https://ib.adnxs.com/openrtb2/prebid', - noP1Consent: 'https://ib.adnxs-simple.com/openrtb2/prebid' - }); + expect(vendorConfig.endpoint).to.deep.equal({p1Consent: 'https://ib.adnxs.com/openrtb2/prebid', noP1Consent: 'https://ib.adnxs-simple.com/openrtb2/prebid'}); expect(vendorConfig.syncEndpoint).to.be.undefined; expect(vendorConfig).to.have.property('timeout', 750); }); @@ -2953,14 +2617,8 @@ describe('S2S Adapter', function () { expect(vendorConfig).to.have.property('adapter', 'prebidServer'); expect(vendorConfig.bidders).to.deep.equal(['rubicon']); expect(vendorConfig.enabled).to.be.true; - expect(vendorConfig.endpoint).to.deep.equal({ - p1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction', - noP1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction' - }); - expect(vendorConfig.syncEndpoint).to.deep.equal({ - p1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync', - noP1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync' - }); + expect(vendorConfig.endpoint).to.deep.equal({p1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction', noP1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction'}); + expect(vendorConfig.syncEndpoint).to.deep.equal({p1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync', noP1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync'}); expect(vendorConfig).to.have.property('timeout', 750); }); @@ -2979,14 +2637,8 @@ describe('S2S Adapter', function () { 'bidders': ['rubicon'], 'defaultVendor': 'rubicon', 'enabled': true, - 'endpoint': { - p1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction', - noP1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction' - }, - 'syncEndpoint': { - p1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync', - noP1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync' - }, + 'endpoint': {p1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction', noP1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction'}, + 'syncEndpoint': {p1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync', noP1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync'}, 'timeout': 750 }) }); @@ -3007,14 +2659,8 @@ describe('S2S Adapter', function () { accountId: 'abc', bidders: ['rubicon'], defaultVendor: 'rubicon', - endpoint: { - p1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction', - noP1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction' - }, - syncEndpoint: { - p1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync', - noP1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync' - }, + endpoint: {p1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction', noP1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction'}, + syncEndpoint: {p1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync', noP1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync'}, }) }); @@ -3050,8 +2696,7 @@ describe('S2S Adapter', function () { config.setConfig({ s2sConfig: { syncUrlModifier: { - appnexus: () => { - } + appnexus: () => { } } } }); @@ -3063,7 +2708,7 @@ describe('S2S Adapter', function () { // Add syncEndpoint so that the request goes to the User Sync endpoint // Modify the bidders property to include an alias for Rubicon adapter - s2sConfig.syncEndpoint = { p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync' }; + s2sConfig.syncEndpoint = {p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync'}; s2sConfig.bidders = ['appnexus', 'rubicon-alias']; const s2sBidRequest = utils.deepClone(REQUEST); @@ -3134,7 +2779,7 @@ describe('S2S Adapter', function () { it('should add cooperative sync flag to cookie_sync request if property is present', function () { let s2sConfig = utils.deepClone(CONFIG); s2sConfig.coopSync = false; - s2sConfig.syncEndpoint = { p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync' }; + s2sConfig.syncEndpoint = {p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync'}; const s2sBidRequest = utils.deepClone(REQUEST); s2sBidRequest.s2sConfig = s2sConfig; @@ -3149,7 +2794,7 @@ describe('S2S Adapter', function () { it('should not add cooperative sync flag to cookie_sync request if property is not present', function () { let s2sConfig = utils.deepClone(CONFIG); - s2sConfig.syncEndpoint = { p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync' }; + s2sConfig.syncEndpoint = {p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync'}; const s2sBidRequest = utils.deepClone(REQUEST); s2sBidRequest.s2sConfig = s2sConfig; @@ -3162,26 +2807,8 @@ describe('S2S Adapter', function () { expect(requestBid.coopSync).to.be.undefined; }); - it('should set imp banner if ortb2Imp.banner is present', function () { - const consentConfig = { s2sConfig: CONFIG }; - config.setConfig(consentConfig); - const bidRequest = utils.deepClone(REQUEST); - bidRequest.ad_units[0].ortb2Imp = { - banner: { - api: 7 - }, - instl: 1 - }; - - adapter.callBids(bidRequest, BID_REQUESTS, addBidResponse, done, ajax); - const parsedRequestBody = JSON.parse(server.requests[0].requestBody); - - expect(parsedRequestBody.imp[0].banner.api).to.equal(7); - expect(parsedRequestBody.imp[0].instl).to.equal(1); - }); - it('adds debug flag', function () { - config.setConfig({ debug: true }); + config.setConfig({debug: true}); let bidRequest = utils.deepClone(BID_REQUESTS); diff --git a/test/spec/modules/priceFloors_spec.js b/test/spec/modules/priceFloors_spec.js index 6ea58e8c47a..548d2789d3e 100644 --- a/test/spec/modules/priceFloors_spec.js +++ b/test/spec/modules/priceFloors_spec.js @@ -14,12 +14,7 @@ import { fieldMatchingFunctions, allowedFields } from 'modules/priceFloors.js'; -import * as events from 'src/events.js'; -import * as mockGpt from '../integration/faker/googletag.js'; -import 'src/prebid.js'; -import {createBid} from '../../../src/bidfactory.js'; -import {auctionManager} from '../../../src/auctionManager.js'; -import {stubAuctionIndex} from '../../helpers/indexStub.js'; +import events from 'src/events.js'; describe('the price floors module', function () { let logErrorSpy; @@ -113,7 +108,6 @@ describe('the price floors module', function () { bidder: 'rubicon', adUnitCode: 'test_div_1', auctionId: '1234-56-789', - transactionId: 'tr_test_div_1' }; function getAdUnitMock(code = 'adUnit-code') { @@ -230,44 +224,6 @@ describe('the price floors module', function () { }); describe('getFirstMatchingFloor', function () { - it('uses a 0 floor as overrite', function () { - let inputFloorData = { - currency: 'USD', - schema: { - delimiter: '|', - fields: ['adUnitCode'] - }, - values: { - 'test_div_1': 0, - 'test_div_2': 2 - }, - default: 0.5 - }; - - expect(getFirstMatchingFloor(inputFloorData, basicBidRequest, {mediaType: 'banner', size: '*'})).to.deep.equal({ - floorMin: 0, - floorRuleValue: 0, - matchingFloor: 0, - matchingData: 'test_div_1', - matchingRule: 'test_div_1' - }); - - expect(getFirstMatchingFloor(inputFloorData, {...basicBidRequest, adUnitCode: 'test_div_2'}, {mediaType: 'banner', size: '*'})).to.deep.equal({ - floorMin: 0, - floorRuleValue: 2, - matchingFloor: 2, - matchingData: 'test_div_2', - matchingRule: 'test_div_2' - }); - - expect(getFirstMatchingFloor(inputFloorData, {...basicBidRequest, adUnitCode: 'test_div_3'}, {mediaType: 'banner', size: '*'})).to.deep.equal({ - floorMin: 0, - floorRuleValue: 0.5, - matchingFloor: 0.5, - matchingData: 'test_div_3', - matchingRule: undefined - }); - }); it('selects the right floor for different mediaTypes', function () { // banner with * size (not in rule file so does not do anything) expect(getFirstMatchingFloor({...basicFloorData}, basicBidRequest, {mediaType: 'banner', size: '*'})).to.deep.equal({ @@ -442,90 +398,6 @@ describe('the price floors module', function () { matchingFloor: 5.0 }); }); - describe('with gpt enabled', function () { - let gptFloorData; - let indexStub, adUnits; - beforeEach(function () { - gptFloorData = { - currency: 'USD', - schema: { - fields: ['gptSlot'] - }, - values: { - '/12345/sports/soccer': 1.1, - '/12345/sports/basketball': 2.2, - '/12345/news/politics': 3.3, - '/12345/news/weather': 4.4, - '*': 5.5, - }, - default: 0.5 - }; - // reset it so no lingering stuff from other test specs - mockGpt.reset(); - mockGpt.makeSlot({ - code: '/12345/sports/soccer', - divId: 'test_div_1' - }); - mockGpt.makeSlot({ - code: '/12345/sports/basketball', - divId: 'test_div_2' - }); - indexStub = sinon.stub(auctionManager, 'index'); - indexStub.get(() => stubAuctionIndex({adUnits})) - }); - afterEach(function () { - // reset it so no lingering stuff from other test specs - mockGpt.reset(); - indexStub.restore(); - }); - it('picks the right rule when looking for gptSlot', function () { - expect(getFirstMatchingFloor(gptFloorData, basicBidRequest)).to.deep.equal({ - floorMin: 0, - floorRuleValue: 1.1, - matchingFloor: 1.1, - matchingData: '/12345/sports/soccer', - matchingRule: '/12345/sports/soccer' - }); - - let newBidRequest = { ...basicBidRequest, adUnitCode: 'test_div_2' } - expect(getFirstMatchingFloor(gptFloorData, newBidRequest)).to.deep.equal({ - floorMin: 0, - floorRuleValue: 2.2, - matchingFloor: 2.2, - matchingData: '/12345/sports/basketball', - matchingRule: '/12345/sports/basketball' - }); - }); - it('picks the gptSlot from the adUnit and does not call the slotMatching', function () { - const newBidRequest1 = { ...basicBidRequest, transactionId: 'au1' }; - adUnits = [{code: newBidRequest1.code, transactionId: 'au1'}]; - utils.deepSetValue(adUnits[0], 'ortb2Imp.ext.data.adserver', { - name: 'gam', - adslot: '/12345/news/politics' - }) - expect(getFirstMatchingFloor(gptFloorData, newBidRequest1)).to.deep.equal({ - floorMin: 0, - floorRuleValue: 3.3, - matchingFloor: 3.3, - matchingData: '/12345/news/politics', - matchingRule: '/12345/news/politics' - }); - - const newBidRequest2 = { ...basicBidRequest, adUnitCode: 'test_div_2', transactionId: 'au2' }; - adUnits = [{code: newBidRequest2.adUnitCode, transactionId: newBidRequest2.transactionId}]; - utils.deepSetValue(adUnits[0], 'ortb2Imp.ext.data.adserver', { - name: 'gam', - adslot: '/12345/news/weather' - }) - expect(getFirstMatchingFloor(gptFloorData, newBidRequest2)).to.deep.equal({ - floorMin: 0, - floorRuleValue: 4.4, - matchingFloor: 4.4, - matchingData: '/12345/news/weather', - matchingRule: '/12345/news/weather' - }); - }); - }); }); describe('pre-auction tests', function () { let exposedAdUnits; @@ -1614,12 +1486,17 @@ describe('the price floors module', function () { }); }); describe('bidResponseHook tests', function () { - const AUCTION_ID = '123456'; - let returnedBidResponse, indexStub; - let adUnit = { - transactionId: 'au', - code: 'test_div_1' - } + let returnedBidResponse; + let bidderRequest = { + bidderCode: 'appnexus', + auctionId: '123456', + bids: [{ + bidder: 'appnexus', + adUnitCode: 'test_div_1', + auctionId: '123456', + bidId: '1111' + }] + }; let basicBidResponse = { bidderCode: 'appnexus', width: 300, @@ -1627,46 +1504,38 @@ describe('the price floors module', function () { cpm: 0.5, mediaType: 'banner', requestId: '1111', - transactionId: 'au', }; beforeEach(function () { returnedBidResponse = {}; - indexStub = sinon.stub(auctionManager, 'index'); - indexStub.get(() => stubAuctionIndex({adUnits: [adUnit]})); }); - - afterEach(() => { - indexStub.restore(); - }); - function runBidResponse(bidResp = basicBidResponse) { let next = (adUnitCode, bid) => { returnedBidResponse = bid; }; - addBidResponseHook(next, bidResp.adUnitCode, Object.assign(createBid(CONSTANTS.STATUS.GOOD, {auctionId: AUCTION_ID}), bidResp)); + addBidResponseHook.bind({ bidderRequest })(next, bidResp.adUnitCode, bidResp); }; it('continues with the auction if not floors data is present without any flooring', function () { runBidResponse(); expect(returnedBidResponse).to.not.haveOwnProperty('floorData'); }); it('if no matching rule it should not floor and should call log warn', function () { - _floorDataForAuction[AUCTION_ID] = utils.deepClone(basicFloorConfig); - _floorDataForAuction[AUCTION_ID].data.values = { 'video': 1.0 }; + _floorDataForAuction[bidderRequest.auctionId] = utils.deepClone(basicFloorConfig); + _floorDataForAuction[bidderRequest.auctionId].data.values = { 'video': 1.0 }; runBidResponse(); expect(returnedBidResponse).to.not.haveOwnProperty('floorData'); expect(logWarnSpy.calledOnce).to.equal(true); }); it('if it finds a rule and floors should update the bid accordingly', function () { - _floorDataForAuction[AUCTION_ID] = utils.deepClone(basicFloorConfig); - _floorDataForAuction[AUCTION_ID].data.values = { 'banner': 1.0 }; + _floorDataForAuction[bidderRequest.auctionId] = utils.deepClone(basicFloorConfig); + _floorDataForAuction[bidderRequest.auctionId].data.values = { 'banner': 1.0 }; runBidResponse(); expect(returnedBidResponse).to.haveOwnProperty('floorData'); expect(returnedBidResponse.status).to.equal(CONSTANTS.BID_STATUS.BID_REJECTED); expect(returnedBidResponse.cpm).to.equal(0); }); it('if it finds a rule and does not floor should update the bid accordingly', function () { - _floorDataForAuction[AUCTION_ID] = utils.deepClone(basicFloorConfig); - _floorDataForAuction[AUCTION_ID].data.values = { 'banner': 0.3 }; + _floorDataForAuction[bidderRequest.auctionId] = utils.deepClone(basicFloorConfig); + _floorDataForAuction[bidderRequest.auctionId].data.values = { 'banner': 0.3 }; runBidResponse(); expect(returnedBidResponse).to.haveOwnProperty('floorData'); expect(returnedBidResponse.floorData).to.deep.equal({ @@ -1688,7 +1557,7 @@ describe('the price floors module', function () { expect(returnedBidResponse.cpm).to.equal(0.5); }); it('if should work with more complex rules and update accordingly', function () { - _floorDataForAuction[AUCTION_ID] = { + _floorDataForAuction[bidderRequest.auctionId] = { ...basicFloorConfig, data: { currency: 'USD', @@ -1774,49 +1643,4 @@ describe('the price floors module', function () { expect(_floorDataForAuction[AUCTION_END_EVENT.auctionId]).to.be.undefined; }); }); - - describe('fieldMatchingFunctions', () => { - let sandbox; - - const req = { - ...basicBidRequest, - } - - const resp = { - transactionId: req.transactionId, - size: [100, 100], - mediaType: 'banner', - } - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - sandbox.stub(auctionManager, 'index').get(() => stubAuctionIndex({ - adUnits: [ - { - code: req.adUnitCode, - transactionId: req.transactionId, - ortb2Imp: {ext: {data: {adserver: {name: 'gam', adslot: 'slot'}}}} - } - ] - })); - }); - - afterEach(() => { - sandbox.restore(); - }) - - Object.entries({ - size: '100x100', - mediaType: resp.mediaType, - gptSlot: 'slot', - domain: 'localhost', - adUnitCode: req.adUnitCode, - }).forEach(([test, expected]) => { - describe(`${test}`, () => { - it('should work with only bidResponse', () => { - expect(fieldMatchingFunctions[test](undefined, resp)).to.eql(expected) - }) - }); - }) - }); }); diff --git a/test/spec/modules/pubgeniusBidAdapter_spec.js b/test/spec/modules/pubgeniusBidAdapter_spec.js index 4599eb2a6fa..6568f7aa782 100644 --- a/test/spec/modules/pubgeniusBidAdapter_spec.js +++ b/test/spec/modules/pubgeniusBidAdapter_spec.js @@ -173,7 +173,7 @@ describe('pubGENIUS adapter', () => { expectedRequest = { method: 'POST', - url: 'https://auction.adpearl.io/prebid/auction', + url: 'https://ortb.adpearl.io/prebid/auction', data: { id: 'fake-auction-id', imp: [ @@ -493,7 +493,7 @@ describe('pubGENIUS adapter', () => { }; expectedSync = { type: 'iframe', - url: 'https://auction.adpearl.io/usersync/pixels.html?', + url: 'https://ortb.adpearl.io/usersync/pixels.html?', }; }); @@ -551,7 +551,7 @@ describe('pubGENIUS adapter', () => { onTimeout(timeoutData); expect(server.requests[0].method).to.equal('POST'); - expect(server.requests[0].url).to.equal('https://auction.adpearl.io/prebid/events?type=timeout'); + expect(server.requests[0].url).to.equal('https://ortb.adpearl.io/prebid/events?type=timeout'); expect(JSON.parse(server.requests[0].requestBody)).to.deep.equal(timeoutData); }); }); diff --git a/test/spec/modules/publinkIdSystem_spec.js b/test/spec/modules/publinkIdSystem_spec.js deleted file mode 100644 index 4656afe1585..00000000000 --- a/test/spec/modules/publinkIdSystem_spec.js +++ /dev/null @@ -1,169 +0,0 @@ -import {publinkIdSubmodule} from 'modules/publinkIdSystem.js'; -import {getStorageManager} from '../../../src/storageManager'; -import {server} from 'test/mocks/xhr.js'; -import sinon from 'sinon'; -import {uspDataHandler} from '../../../src/adapterManager'; -import {parseUrl} from '../../../src/utils'; - -export const storage = getStorageManager({gvlid: 24}); -const TEST_COOKIE_VALUE = 'cookievalue'; -describe('PublinkIdSystem', () => { - describe('decode', () => { - it('decode', () => { - const result = publinkIdSubmodule.decode(TEST_COOKIE_VALUE); - expect(result).deep.equals({publinkId: TEST_COOKIE_VALUE}); - }); - }); - - describe('Fetch Local Cookies', () => { - const PUBLINK_COOKIE = '_publink'; - const PUBLINK_SRV_COOKIE = '_publink_srv'; - const EXP = Date.now() + 60 * 60 * 24 * 7 * 1000; - const COOKIE_VALUE = {publink: 'publinkCookieValue', exp: EXP}; - const LOCAL_VALUE = {publink: 'publinkLocalStorageValue', exp: EXP}; - const COOKIE_EXPIRATION = (new Date(Date.now() + 60 * 60 * 24 * 1000)).toUTCString(); - const DELETE_COOKIE = 'Thu, 01 Jan 1970 00:00:01 GMT'; - it('publink srv cookie', () => { - storage.setCookie(PUBLINK_SRV_COOKIE, JSON.stringify(COOKIE_VALUE), COOKIE_EXPIRATION); - const result = publinkIdSubmodule.getId(); - expect(result.id).to.equal(COOKIE_VALUE.publink); - storage.setCookie(PUBLINK_SRV_COOKIE, '', DELETE_COOKIE); - }); - it('publink srv local storage', () => { - storage.setDataInLocalStorage(PUBLINK_SRV_COOKIE, JSON.stringify(LOCAL_VALUE)); - const result = publinkIdSubmodule.getId(); - expect(result.id).to.equal(LOCAL_VALUE.publink); - storage.removeDataFromLocalStorage(PUBLINK_SRV_COOKIE); - }); - it('publink cookie', () => { - storage.setCookie(PUBLINK_COOKIE, JSON.stringify(COOKIE_VALUE), COOKIE_EXPIRATION); - const result = publinkIdSubmodule.getId(); - expect(result.id).to.equal(COOKIE_VALUE.publink); - storage.setCookie(PUBLINK_COOKIE, '', DELETE_COOKIE); - }); - it('publink local storage', () => { - storage.setDataInLocalStorage(PUBLINK_COOKIE, JSON.stringify(LOCAL_VALUE)); - const result = publinkIdSubmodule.getId(); - expect(result.id).to.equal(LOCAL_VALUE.publink); - storage.removeDataFromLocalStorage(PUBLINK_COOKIE); - }); - it('priority goes to publink_srv cookie', () => { - storage.setCookie(PUBLINK_SRV_COOKIE, JSON.stringify(COOKIE_VALUE), COOKIE_EXPIRATION); - storage.setDataInLocalStorage(PUBLINK_COOKIE, JSON.stringify(LOCAL_VALUE)); - const result = publinkIdSubmodule.getId(); - expect(result.id).to.equal(COOKIE_VALUE.publink); - storage.setCookie(PUBLINK_SRV_COOKIE, '', DELETE_COOKIE); - storage.removeDataFromLocalStorage(PUBLINK_COOKIE); - }); - it('publink non-json cookie', () => { - storage.setCookie(PUBLINK_COOKIE, COOKIE_VALUE.publink, COOKIE_EXPIRATION); - const result = publinkIdSubmodule.getId(); - expect(result.id).to.equal(COOKIE_VALUE.publink); - storage.setCookie(PUBLINK_COOKIE, '', DELETE_COOKIE); - }); - }); - - describe('getId', () => { - const serverResponse = {publink: 'ec0xHT3yfAOnykP64Qf0ORSi7LjNT1wju04ZSCsoPBekOJdBwK-0Zl_lXKDNnzhauC4iszBc-PvA1Be6IMlh1QocA'}; - it('no config', () => { - const result = publinkIdSubmodule.getId(); - expect(result).to.exist; - expect(result.callback).to.be.a('function'); - }); - - it('Use local copy', () => { - const result = publinkIdSubmodule.getId({}, undefined, TEST_COOKIE_VALUE); - expect(result).to.be.undefined; - }); - - describe('callout for id', () => { - let callbackSpy = sinon.spy(); - - beforeEach(() => { - callbackSpy.resetHistory(); - }); - - it('Fetch with consent data', () => { - const config = {storage: {type: 'cookie'}, params: {e: 'ca11c0ca7', site_id: '102030'}}; - const consentData = {gdprApplies: 1, consentString: 'myconsentstring'}; - let submoduleCallback = publinkIdSubmodule.getId(config, consentData).callback; - submoduleCallback(callbackSpy); - - const request = server.requests[0]; - const parsed = parseUrl(request.url); - - expect(parsed.hostname).to.equal('proc.ad.cpe.dotomi.com'); - expect(parsed.pathname).to.equal('/cvx/client/sync/publink'); - expect(parsed.search.mpn).to.equal('Prebid.js'); - expect(parsed.search.mpv).to.equal('$prebid.version$'); - expect(parsed.search.gdpr).to.equal('1'); - expect(parsed.search.gdpr_consent).to.equal('myconsentstring'); - expect(parsed.search.sid).to.equal('102030'); - expect(parsed.search.apikey).to.be.undefined; - - request.respond(200, {}, JSON.stringify(serverResponse)); - expect(callbackSpy.calledOnce).to.be.true; - expect(callbackSpy.lastCall.lastArg).to.equal(serverResponse.publink); - }); - - it('server doesnt respond', () => { - const config = {storage: {type: 'cookie'}, params: {e: 'ca11c0ca7'}}; - let submoduleCallback = publinkIdSubmodule.getId(config).callback; - submoduleCallback(callbackSpy); - - let request = server.requests[0]; - const parsed = parseUrl(request.url); - - expect(parsed.hostname).to.equal('proc.ad.cpe.dotomi.com'); - expect(parsed.pathname).to.equal('/cvx/client/sync/publink'); - expect(parsed.search.mpn).to.equal('Prebid.js'); - expect(parsed.search.mpv).to.equal('$prebid.version$'); - - request.respond(204, {}, JSON.stringify(serverResponse)); - expect(callbackSpy.called).to.be.false; - }); - - it('reject plain email address', () => { - const config = {storage: {type: 'cookie'}, params: {e: 'tester@test.com'}}; - const consentData = {gdprApplies: 1, consentString: 'myconsentstring'}; - let submoduleCallback = publinkIdSubmodule.getId(config, consentData).callback; - submoduleCallback(callbackSpy); - - expect(server.requests).to.have.lengthOf(0); - expect(callbackSpy.called).to.be.false; - }); - }); - - describe('usPrivacy', () => { - let callbackSpy = sinon.spy(); - const oldPrivacy = uspDataHandler.getConsentData(); - before(() => { - uspDataHandler.setConsentData('1YNN'); - }); - after(() => { - uspDataHandler.setConsentData(oldPrivacy); - callbackSpy.resetHistory(); - }); - - it('Fetch with usprivacy data', () => { - const config = {storage: {type: 'cookie'}, params: {e: 'ca11c0ca7', api_key: 'abcdefg'}}; - let submoduleCallback = publinkIdSubmodule.getId(config).callback; - submoduleCallback(callbackSpy); - - let request = server.requests[0]; - const parsed = parseUrl(request.url); - - expect(parsed.hostname).to.equal('proc.ad.cpe.dotomi.com'); - expect(parsed.pathname).to.equal('/cvx/client/sync/publink'); - expect(parsed.search.mpn).to.equal('Prebid.js'); - expect(parsed.search.mpv).to.equal('$prebid.version$'); - expect(parsed.search.us_privacy).to.equal('1YNN'); - expect(parsed.search.apikey).to.equal('abcdefg'); - - request.respond(200, {}, JSON.stringify(serverResponse)); - expect(callbackSpy.calledOnce).to.be.true; - expect(callbackSpy.lastCall.lastArg).to.equal(serverResponse.publink); - }); - }); - }); -}); diff --git a/test/spec/modules/pubmaticAnalyticsAdapter_spec.js b/test/spec/modules/pubmaticAnalyticsAdapter_spec.js index c60b08ae972..c6496ee7fe1 100755 --- a/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +++ b/test/spec/modules/pubmaticAnalyticsAdapter_spec.js @@ -7,6 +7,7 @@ import { addBidResponseHook, } from 'modules/currency.js'; +// using es6 "import * as events from 'src/events'" causes the events.getEvents stub not to work... let events = require('src/events'); let ajax = require('src/ajax'); let utils = require('src/utils'); @@ -94,9 +95,6 @@ const BID2 = Object.assign({}, BID, { 'hb_pb': '1.500', 'hb_size': '728x90', 'hb_source': 'server' - }, - meta: { - advertiserDomains: ['example.com'] } }); @@ -384,7 +382,6 @@ describe('pubmatic analytics adapter', function () { expect(data.s[1].ps[0].di).to.equal('the-deal-id'); expect(data.s[1].ps[0].dc).to.equal('PMP'); expect(data.s[1].ps[0].mi).to.equal('matched-impression'); - expect(data.s[1].ps[0].adv).to.equal('example.com'); expect(data.s[1].ps[0].l1).to.equal(3214); expect(data.s[1].ps[0].l2).to.equal(0); expect(data.s[1].ps[0].ss).to.equal(1); @@ -654,7 +651,6 @@ describe('pubmatic analytics adapter', function () { expect(data.s[1].ps[0].di).to.equal('the-deal-id'); expect(data.s[1].ps[0].dc).to.equal('PMP'); expect(data.s[1].ps[0].mi).to.equal('matched-impression'); - expect(data.s[1].ps[0].adv).to.equal('example.com'); expect(data.s[1].ps[0].l1).to.equal(3214); expect(data.s[1].ps[0].l2).to.equal(0); expect(data.s[1].ps[0].ss).to.equal(1); @@ -712,7 +708,6 @@ describe('pubmatic analytics adapter', function () { expect(data.s[1].ps[0].di).to.equal('the-deal-id'); expect(data.s[1].ps[0].dc).to.equal('PMP'); expect(data.s[1].ps[0].mi).to.equal('matched-impression'); - expect(data.s[1].ps[0].adv).to.equal('example.com'); expect(data.s[1].ps[0].l1).to.equal(3214); expect(data.s[1].ps[0].l2).to.equal(0); expect(data.s[1].ps[0].ss).to.equal(1); @@ -759,7 +754,6 @@ describe('pubmatic analytics adapter', function () { expect(data.s[1].ps[0].di).to.equal('the-deal-id'); expect(data.s[1].ps[0].dc).to.equal('PMP'); expect(data.s[1].ps[0].mi).to.equal('matched-impression'); - expect(data.s[1].ps[0].adv).to.equal('example.com'); expect(data.s[1].ps[0].l1).to.equal(3214); expect(data.s[1].ps[0].l2).to.equal(0); expect(data.s[1].ps[0].ss).to.equal(1); @@ -777,10 +771,9 @@ describe('pubmatic analytics adapter', function () { expect(data.kgpv).to.equal('*'); }); - it('Logger: regexPattern in bid.bidResponse and url in adomain', function() { + it('Logger: regexPattern in bid.bidResponse', function() { const BID2_COPY = utils.deepClone(BID2); BID2_COPY.regexPattern = '*'; - BID2_COPY.meta.advertiserDomains = ['https://www.example.com/abc/223'] events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); @@ -815,7 +808,6 @@ describe('pubmatic analytics adapter', function () { expect(data.s[1].ps[0].di).to.equal('the-deal-id'); expect(data.s[1].ps[0].dc).to.equal('PMP'); expect(data.s[1].ps[0].mi).to.equal('matched-impression'); - expect(data.s[1].ps[0].adv).to.equal('example.com'); expect(data.s[1].ps[0].l1).to.equal(3214); expect(data.s[1].ps[0].l2).to.equal(0); expect(data.s[1].ps[0].ss).to.equal(1); @@ -867,7 +859,6 @@ describe('pubmatic analytics adapter', function () { expect(data.s[1].ps[0].di).to.equal('the-deal-id'); expect(data.s[1].ps[0].dc).to.equal('PMP'); expect(data.s[1].ps[0].mi).to.equal('matched-impression'); - expect(data.s[1].ps[0].adv).to.equal('example.com'); expect(data.s[1].ps[0].l1).to.equal(3214); expect(data.s[1].ps[0].l2).to.equal(0); expect(data.s[1].ps[0].ss).to.equal(1); @@ -921,7 +912,6 @@ describe('pubmatic analytics adapter', function () { expect(data.s[1].ps[0].di).to.equal('the-deal-id'); expect(data.s[1].ps[0].dc).to.equal('PMP'); expect(data.s[1].ps[0].mi).to.equal('matched-impression'); - expect(data.s[1].ps[0].adv).to.equal('example.com'); expect(data.s[1].ps[0].l1).to.equal(3214); expect(data.s[1].ps[0].l2).to.equal(0); expect(data.s[1].ps[0].ss).to.equal(1); @@ -1021,7 +1011,6 @@ describe('pubmatic analytics adapter', function () { expect(data.s[1].ps[0].di).to.equal('the-deal-id'); expect(data.s[1].ps[0].dc).to.equal('PMP'); expect(data.s[1].ps[0].mi).to.equal('matched-impression'); - expect(data.s[1].ps[0].adv).to.equal('example.com'); expect(data.s[1].ps[0].l1).to.equal(3214); expect(data.s[1].ps[0].l2).to.equal(0); expect(data.s[1].ps[0].ss).to.equal(1); diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 7679b3cdf5a..23c5f01e520 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1,5 +1,5 @@ import {expect} from 'chai'; -import {spec, checkVideoPlacement} from 'modules/pubmaticBidAdapter.js'; +import {spec} from 'modules/pubmaticBidAdapter.js'; import * as utils from 'src/utils.js'; import {config} from 'src/config.js'; import { createEidsArray } from 'modules/userId/eids.js'; @@ -1565,69 +1565,6 @@ describe('PubMatic adapter', function () { expect(data2.regs).to.equal(undefined);// USP/CCPAs }); - it('Request params check with JW player params', function() { - let bidRequests = [ - { - bidder: 'pubmatic', - params: { - publisherId: '301', - adSlot: '/15671365/DMDemo@300x250:0', - dctr: 'key1=val1|key2=val2,val3' - }, - placementCode: '/19968336/header-bid-tag-1', - sizes: [[300, 250], [300, 600]], - bidId: '23acc48ad47af5', - requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', - bidderRequestId: '1c56ad30b9b8ca8', - transactionId: '92489f71-1bf2-49a0-adf9-000cea934729', - rtd: { - jwplayer: { - targeting: { - content: { id: 'jw_d9J2zcaA' }, - segments: ['80011026', '80011035'] - } - } - } - }]; - let key_val_output = 'key1=val1|key2=val2,val3|jw-id=jw_d9J2zcaA|jw-80011026=1|jw-80011035=1' - let request = spec.buildRequests(bidRequests, { - auctionId: 'new-auction-id' - }); - let data = JSON.parse(request.data); - expect(data.imp[0].ext).to.exist.and.to.be.an('object'); - expect(data.imp[0].ext.key_val).to.exist.and.to.equal(key_val_output); - - // jw player data not available. Only dctr sent. - delete bidRequests[0].rtd; - request = spec.buildRequests(bidRequests, { - auctionId: 'new-auction-id' - }); - data = JSON.parse(request.data); - - expect(data.imp[0].ext).to.exist.and.to.be.an('object'); // dctr parameter - expect(data.imp[0].ext.key_val).to.exist.and.to.equal(bidRequests[0].params.dctr); - - // jw player data is available, but dctr is not present - bidRequests[0].rtd = { - jwplayer: { - targeting: { - content: { id: 'jw_d9J2zcaA' }, - segments: ['80011026', '80011035'] - } - } - }; - - delete bidRequests[0].params.dctr; - key_val_output = 'jw-id=jw_d9J2zcaA|jw-80011026=1|jw-80011035=1'; - request = spec.buildRequests(bidRequests, { - auctionId: 'new-auction-id' - }); - data = JSON.parse(request.data); - - expect(data.imp[0].ext).to.exist.and.to.be.an('object'); - expect(data.imp[0].ext.key_val).to.exist.and.to.equal(key_val_output); - }); - describe('FPD', function() { let newRequest; @@ -1846,25 +1783,14 @@ describe('PubMatic adapter', function () { let newRequest; let floorModuleTestData; let getFloor = function(req) { - // actual getFloor module does not work like this :) - // special treatment for banner since for other mediaTypes we pass * - if (req.mediaType === 'banner') { - return floorModuleTestData[req.mediaType][ req.size[0] + 'x' + req.size[1] ] || {}; - } - return floorModuleTestData[req.mediaType] || {}; + return floorModuleTestData[req.mediaType]; }; beforeEach(() => { floorModuleTestData = { 'banner': { - '300x250': { - 'currency': 'USD', - 'floor': 1.50 - }, - '300x600': { - 'currency': 'USD', - 'floor': 2.0 - } + 'currency': 'USD', + 'floor': 1.50 }, 'video': { 'currency': 'USD', @@ -1880,7 +1806,7 @@ describe('PubMatic adapter', function () { }); it('bidfloor should be undefined if calculation is <= 0', function() { - floorModuleTestData.banner['300x250'].floor = 0; // lowest of them all + floorModuleTestData.banner.floor = 0; // lowest of them all newRequest[0].params.kadfloor = undefined; let request = spec.buildRequests(newRequest, { auctionId: 'new-auction-id' @@ -1891,8 +1817,7 @@ describe('PubMatic adapter', function () { }); it('ignore floormodule o/p if floor is not number', function() { - floorModuleTestData.banner['300x250'].floor = 'Not-a-Number'; - floorModuleTestData.banner['300x600'].floor = 'Not-a-Number'; + floorModuleTestData.banner.floor = 'INR'; newRequest[0].params.kadfloor = undefined; let request = spec.buildRequests(newRequest, { auctionId: 'new-auction-id' @@ -1903,8 +1828,7 @@ describe('PubMatic adapter', function () { }); it('ignore floormodule o/p if currency is not matched', function() { - floorModuleTestData.banner['300x250'].currency = 'INR'; - floorModuleTestData.banner['300x600'].currency = 'INR'; + floorModuleTestData.banner.currency = 'INR'; newRequest[0].params.kadfloor = undefined; let request = spec.buildRequests(newRequest, { auctionId: 'new-auction-id' @@ -1934,7 +1858,7 @@ describe('PubMatic adapter', function () { expect(data.bidfloor).to.equal(3); }); - it('kadfloor is passed as 1, use min of floorModule as it is highest', function() { + it('kadfloor is passed as 1, use min of fllorModule as it is highest', function() { newRequest[0].params.kadfloor = '1.0';// yes, we want it as a string let request = spec.buildRequests(newRequest, { auctionId: 'new-auction-id' @@ -3130,115 +3054,6 @@ describe('PubMatic adapter', function () { }); }); - describe('Request param acat checking', function() { - let multipleBidRequests = [ - { - bidder: 'pubmatic', - params: { - publisherId: '301', - adSlot: '/15671365/DMDemo@300x250:0', - kadfloor: '1.2', - pmzoneid: 'aabc, ddef', - kadpageurl: 'www.publisher.com', - yob: '1986', - gender: 'M', - lat: '12.3', - lon: '23.7', - wiid: '1234567890', - profId: '100', - verId: '200', - currency: 'AUD', - dctr: 'key1=val1|key2=val2,!val3' - }, - placementCode: '/19968336/header-bid-tag-1', - sizes: [[300, 250], [300, 600]], - bidId: '23acc48ad47af5', - requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', - bidderRequestId: '1c56ad30b9b8ca8', - transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' - }, - { - bidder: 'pubmatic', - params: { - publisherId: '301', - adSlot: '/15671365/DMDemo@300x250:0', - kadfloor: '1.2', - pmzoneid: 'aabc, ddef', - kadpageurl: 'www.publisher.com', - yob: '1986', - gender: 'M', - lat: '12.3', - lon: '23.7', - wiid: '1234567890', - profId: '100', - verId: '200', - currency: 'GBP', - dctr: 'key1=val3|key2=val1,!val3|key3=val123' - }, - placementCode: '/19968336/header-bid-tag-1', - sizes: [[300, 250], [300, 600]], - bidId: '23acc48ad47af5', - requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', - bidderRequestId: '1c56ad30b9b8ca8', - transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' - } - ]; - - it('acat: pass only strings', function() { - multipleBidRequests[0].params.acat = [1, 2, 3, 'IAB1', 'IAB2']; - let request = spec.buildRequests(multipleBidRequests, { - auctionId: 'new-auction-id' - }); - let data = JSON.parse(request.data); - expect(data.ext.acat).to.exist.and.to.deep.equal(['IAB1', 'IAB2']); - }); - - it('acat: trim the strings', function() { - multipleBidRequests[0].params.acat = [' IAB1 ', ' IAB2 ']; - let request = spec.buildRequests(multipleBidRequests, { - auctionId: 'new-auction-id' - }); - let data = JSON.parse(request.data); - expect(data.ext.acat).to.exist.and.to.deep.equal(['IAB1', 'IAB2']); - }); - - it('acat: pass only unique strings', function() { - multipleBidRequests[0].params.acat = ['IAB1', 'IAB2', 'IAB1', 'IAB2', 'IAB1', 'IAB2']; - multipleBidRequests[1].params.acat = ['IAB1', 'IAB2', 'IAB1', 'IAB2', 'IAB1', 'IAB3']; - let request = spec.buildRequests(multipleBidRequests, { - auctionId: 'new-auction-id' - }); - let data = JSON.parse(request.data); - expect(data.ext.acat).to.exist.and.to.deep.equal(['IAB1', 'IAB2', 'IAB3']); - }); - it('ortb2.ext.prebid.bidderparams.pubmatic.acat should be passed in request payload', function() { - let sandbox = sinon.sandbox.create(); - sandbox.stub(config, 'getConfig').callsFake(key => { - const config = { - 'ortb2': { - ext: { - prebid: { - bidderparams: { - pubmatic: { - acat: ['IAB1', 'IAB2', 'IAB1', 'IAB2', 'IAB1', 'IAB2'] - } - } - } - } - } - }; - return config[key]; - }); - const request = spec.buildRequests(bidRequests, { - auctionId: 'new-auction-id', - bidderCode: 'pubmatic' - }); - let data = JSON.parse(request.data); - expect(data.ext.acat).to.deep.equal(['IAB1', 'IAB2']); - sandbox.restore(); - }); - }); - describe('Request param bcat checking', function() { let multipleBidRequests = [ { @@ -3340,26 +3155,6 @@ describe('PubMatic adapter', function () { }); let data = JSON.parse(request.data); expect(data.bcat).to.deep.equal(undefined); - }); - - it('ortb2.bcat should merged with slot level bcat param', function() { - multipleBidRequests[0].params.bcat = ['IAB-1', 'IAB-2']; - let sandbox = sinon.sandbox.create(); - sandbox.stub(config, 'getConfig').callsFake(key => { - const config = { - 'ortb2': { - bcat: ['IAB-3', 'IAB-4'] - } - }; - return config[key]; - }); - const request = spec.buildRequests(multipleBidRequests, { - auctionId: 'new-auction-id', - bidderCode: 'pubmatic' - }); - let data = JSON.parse(request.data); - expect(data.bcat).to.deep.equal(['IAB-1', 'IAB-2', 'IAB-3', 'IAB-4']); - sandbox.restore(); }); }); @@ -3586,7 +3381,7 @@ describe('PubMatic adapter', function () { 'h': 0, 'dealId': 'ASEA-MS-KLY-TTD-DESKTOP-ID-VID-6S-030420', 'ext': { - 'bidtype': 1 + 'BidType': 1 } }], 'ext': { @@ -3773,297 +3568,5 @@ describe('PubMatic adapter', function () { }]); }); }); - - describe('JW player segment data for S2S', function() { - let sandbox = sinon.sandbox.create(); - beforeEach(function () { - sandbox = sinon.sandbox.create(); - }); - afterEach(function() { - sandbox.restore(); - }); - it('Should append JW player segment data to dctr values in auction endpoint', function() { - var videoAdUnit = { - 'bidderCode': 'pubmatic', - 'bids': [ - { - 'bidder': 'pubmatic', - 'params': { - 'publisherId': '156276', - 'adSlot': 'pubmatic_video2', - 'dctr': 'key1=123|key2=345', - 'pmzoneid': '1243', - 'video': { - 'mimes': ['video/mp4', 'video/x-flv'], - 'skippable': true, - 'minduration': 5, - 'maxduration': 30, - 'startdelay': 5, - 'playbackmethod': [1, 3], - 'api': [1, 2], - 'protocols': [2, 3], - 'battr': [13, 14], - 'linearity': 1, - 'placement': 2, - 'minbitrate': 10, - 'maxbitrate': 10 - } - }, - 'rtd': { - 'jwplayer': { - 'targeting': { - 'segments': ['80011026', '80011035'], - 'content': { - 'id': 'jw_d9J2zcaA' - } - } - } - }, - 'bid_id': '17a6771be26cc4', - 'ortb2Imp': { - 'ext': { - 'data': { - 'pbadslot': 'abcd', - 'jwTargeting': { - 'playerID': 'myElement1', - 'mediaID': 'd9J2zcaA' - } - } - } - } - } - ], - 'auctionStart': 1630923178417, - 'timeout': 1000, - 'src': 's2s' - } - - spec.transformBidParams(bidRequests[0].params, true, videoAdUnit); - expect(bidRequests[0].params.dctr).to.equal('key1:val1,val2|key2:val1|jw-id=jw_d9J2zcaA|jw-80011026=1|jw-80011035=1'); - }); - it('Should send only JW player segment data in auction endpoint, if dctr is missing', function() { - var videoAdUnit = { - 'bidderCode': 'pubmatic', - 'bids': [ - { - 'bidder': 'pubmatic', - 'params': { - 'publisherId': '156276', - 'adSlot': 'pubmatic_video2', - 'dctr': 'key1=123|key2=345', - 'pmzoneid': '1243', - 'video': { - 'mimes': ['video/mp4', 'video/x-flv'], - 'skippable': true, - 'minduration': 5, - 'maxduration': 30, - 'startdelay': 5, - 'playbackmethod': [1, 3], - 'api': [1, 2], - 'protocols': [2, 3], - 'battr': [13, 14], - 'linearity': 1, - 'placement': 2, - 'minbitrate': 10, - 'maxbitrate': 10 - } - }, - 'rtd': { - 'jwplayer': { - 'targeting': { - 'segments': ['80011026', '80011035'], - 'content': { - 'id': 'jw_d9J2zcaA' - } - } - } - }, - 'bid_id': '17a6771be26cc4', - 'ortb2Imp': { - 'ext': { - 'data': { - 'pbadslot': 'abcd', - 'jwTargeting': { - 'playerID': 'myElement1', - 'mediaID': 'd9J2zcaA' - } - } - } - } - } - ], - 'auctionStart': 1630923178417, - 'timeout': 1000, - 'src': 's2s' - } - - delete bidRequests[0].params.dctr; - spec.transformBidParams(bidRequests[0].params, true, videoAdUnit); - expect(bidRequests[0].params.dctr).to.equal('jw-id=jw_d9J2zcaA|jw-80011026=1|jw-80011035=1'); - }); - - it('Should not send any JW player segment data in auction endpoint, if it is not available', function() { - var videoAdUnit = { - 'bidderCode': 'pubmatic', - 'bids': [ - { - 'bidder': 'pubmatic', - 'params': { - 'publisherId': '156276', - 'adSlot': 'pubmatic_video2', - 'dctr': 'key1=123|key2=345', - 'pmzoneid': '1243', - 'video': { - 'mimes': ['video/mp4', 'video/x-flv'], - 'skippable': true, - 'minduration': 5, - 'maxduration': 30, - 'startdelay': 5, - 'playbackmethod': [1, 3], - 'api': [1, 2], - 'protocols': [2, 3], - 'battr': [13, 14], - 'linearity': 1, - 'placement': 2, - 'minbitrate': 10, - 'maxbitrate': 10 - } - }, - 'bid_id': '17a6771be26cc4', - 'ortb2Imp': { - 'ext': { - 'data': { - 'pbadslot': 'abcd', - 'jwTargeting': { - 'playerID': 'myElement1', - 'mediaID': 'd9J2zcaA' - } - } - } - } - } - ], - 'auctionStart': 1630923178417, - 'timeout': 1000, - 'src': 's2s' - } - spec.transformBidParams(bidRequests[0].params, true, videoAdUnit); - expect(bidRequests[0].params.dctr).to.equal('key1:val1,val2|key2:val1'); - }); - }) - - describe('Checking for Video.Placement property', function() { - let sandbox, utilsMock; - const adUnit = 'Div1'; - const msg_placement_missing = 'Video.Placement param missing for Div1'; - let videoData = { - battr: [6, 7], - skipafter: 15, - maxduration: 50, - context: 'instream', - playerSize: [640, 480], - skip: 0, - connectiontype: [1, 2, 6], - skipmin: 10, - minduration: 10, - mimes: ['video/mp4', 'video/x-flv'], - } - beforeEach(() => { - utilsMock = sinon.mock(utils); - sandbox = sinon.sandbox.create(); - sandbox.spy(utils, 'logWarn'); - }); - - afterEach(() => { - utilsMock.restore(); - sandbox.restore(); - }) - - it('should log Video.Placement param missing', function() { - checkVideoPlacement(videoData, adUnit); - sinon.assert.calledWith(utils.logWarn, msg_placement_missing); - }) - it('shoud not log Video.Placement param missing', function() { - videoData['placement'] = 1; - checkVideoPlacement(videoData, adUnit); - sinon.assert.neverCalledWith(utils.logWarn, msg_placement_missing); - }) - }); - }); - - describe('Video request params', function() { - let sandbox, utilsMock, newVideoRequest; - beforeEach(() => { - utilsMock = sinon.mock(utils); - sandbox = sinon.sandbox.create(); - sandbox.spy(utils, 'logWarn'); - newVideoRequest = utils.deepClone(videoBidRequests) - }); - - afterEach(() => { - utilsMock.restore(); - sandbox.restore(); - }) - - it('Should log warning if video params from mediaTypes and params obj of bid are not present', function () { - delete newVideoRequest[0].mediaTypes.video; - delete newVideoRequest[0].params.video; - - let request = spec.buildRequests(newVideoRequest, { - auctionId: 'new-auction-id' - }); - - sinon.assert.calledOnce(utils.logWarn); - expect(request).to.equal(undefined); - }); - - it('Should consider video params from mediaType object of bid', function () { - delete newVideoRequest[0].params.video; - - let request = spec.buildRequests(newVideoRequest, { - auctionId: 'new-auction-id' - }); - let data = JSON.parse(request.data); - expect(data.imp[0].video).to.exist; - expect(data.imp[0]['video']['w']).to.equal(videoBidRequests[0].mediaTypes.video.playerSize[0]); - expect(data.imp[0]['video']['h']).to.equal(videoBidRequests[0].mediaTypes.video.playerSize[1]); - expect(data.imp[0]['video']['battr']).to.equal(undefined); - }); - }); - - describe('GroupM params', function() { - let sandbox, utilsMock, newBidRequests, newBidResponses; - beforeEach(() => { - utilsMock = sinon.mock(utils); - sandbox = sinon.sandbox.create(); - sandbox.spy(utils, 'logInfo'); - newBidRequests = utils.deepClone(bidRequests) - newBidRequests[0].bidder = 'groupm'; - newBidResponses = utils.deepClone(bidResponses); - newBidResponses.body.seatbid[0].bid[0].ext.marketplace = 'groupm' - }); - - afterEach(() => { - utilsMock.restore(); - sandbox.restore(); - }) - - it('Should log info when bidder is groupm and return', function () { - let request = spec.buildRequests(newBidRequests, {bidderCode: 'groupm', - auctionId: 'new-auction-id' - }); - sinon.assert.calledOnce(utils.logInfo); - expect(request).to.equal(undefined); - }); - - it('Should add bidder code & bidder as groupm for marketplace groupm response', function () { - let request = spec.buildRequests(newBidRequests, { - auctionId: 'new-auction-id' - }); - let response = spec.interpretResponse(newBidResponses, request); - expect(response).to.be.an('array').with.length.above(0); - expect(response[0].bidderCode).to.equal('groupm'); - expect(response[0].bidder).to.equal('groupm'); - }); }); }); diff --git a/test/spec/modules/pubstackAnalyticsAdapter_spec.js b/test/spec/modules/pubstackAnalyticsAdapter_spec.js index 4df25f1665b..e3db334c888 100644 --- a/test/spec/modules/pubstackAnalyticsAdapter_spec.js +++ b/test/spec/modules/pubstackAnalyticsAdapter_spec.js @@ -1,7 +1,7 @@ import * as utils from 'src/utils.js'; import pubstackAnalytics from '../../../modules/pubstackAnalyticsAdapter.js'; import adapterManager from 'src/adapterManager'; -import * as events from 'src/events'; +import events from 'src/events'; import constants from 'src/constants.json' describe('Pubstack Analytics Adapter', () => { diff --git a/test/spec/modules/pubxaiAnalyticsAdapter_spec.js b/test/spec/modules/pubxaiAnalyticsAdapter_spec.js index 63364b867be..3d9be082be3 100644 --- a/test/spec/modules/pubxaiAnalyticsAdapter_spec.js +++ b/test/spec/modules/pubxaiAnalyticsAdapter_spec.js @@ -28,7 +28,6 @@ describe('pubxai analytics adapter', function() { }; let location = utils.getWindowLocation(); - let storage = window.top['sessionStorage']; let prebidEvent = { 'auctionInit': { @@ -515,11 +514,6 @@ describe('pubxai analytics adapter', function() { 'path': location.pathname, 'search': location.search }, - 'pmcDetail': { - 'bidDensity': storage.getItem('pbx:dpbid'), - 'maxBid': storage.getItem('pbx:mxbid'), - 'auctionId': storage.getItem('pbx:aucid') - } }; let expectedAfterBid = { @@ -583,11 +577,6 @@ describe('pubxai analytics adapter', function() { 'deviceOS': getOS(), 'browser': getBrowser() }, - 'pmcDetail': { - 'bidDensity': storage.getItem('pbx:dpbid'), - 'maxBid': storage.getItem('pbx:mxbid'), - 'auctionId': storage.getItem('pbx:aucid') - }, 'initOptions': initOptions }; @@ -636,11 +625,6 @@ describe('pubxai analytics adapter', function() { 'statusMessage': 'Bid available', 'timeToRespond': 267 }, - 'pageDetail': { - 'host': location.host, - 'path': location.pathname, - 'search': location.search - }, 'deviceDetail': { 'platform': navigator.platform, 'deviceType': getDeviceType(), diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index c8ec0493d54..6630cb0907c 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -2,7 +2,6 @@ import {expect} from 'chai'; import {spec} from 'modules/pulsepointBidAdapter.js'; import {deepClone} from 'src/utils.js'; -import { config } from 'src/config.js'; describe('PulsePoint Adapter Tests', function () { const slotConfigs = [{ @@ -616,21 +615,60 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify common id parameters', function () { const bidRequests = deepClone(slotConfigs); - bidRequests[0].userIdAsEids = [{ - source: 'pubcid.org', - uids: [{ - id: 'userid_pubcid' - }] - }, { - source: 'adserver.org', - uids: [{ - id: 'userid_ttd', - ext: { - rtiPartner: 'TDID' + bidRequests[0].userId = { + pubcid: 'userid_pubcid', + tdid: 'userid_ttd', + digitrustid: { + data: { + id: 'userid_digitrust', + keyv: 4, + privacy: {optout: false}, + producer: 'ABC', + version: 2 } - }] - } - ]; + } + }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request).to.be.not.null; + const ortbRequest = request.data; + expect(request.data).to.be.not.null; + // user object + expect(ortbRequest.user).to.not.be.undefined; + expect(ortbRequest.user.ext).to.not.be.undefined; + expect(ortbRequest.user.ext.eids).to.not.be.undefined; + expect(ortbRequest.user.ext.eids).to.have.lengthOf(2); + expect(ortbRequest.user.ext.eids[0].source).to.equal('pubcommon'); + expect(ortbRequest.user.ext.eids[0].uids).to.have.lengthOf(1); + expect(ortbRequest.user.ext.eids[0].uids[0].id).to.equal('userid_pubcid'); + expect(ortbRequest.user.ext.eids[1].source).to.equal('adserver.org'); + expect(ortbRequest.user.ext.eids[1].uids).to.have.lengthOf(1); + expect(ortbRequest.user.ext.eids[1].uids[0].id).to.equal('userid_ttd'); + expect(ortbRequest.user.ext.eids[1].uids[0].ext).to.not.be.null; + expect(ortbRequest.user.ext.eids[1].uids[0].ext.rtiPartner).to.equal('TDID'); + expect(ortbRequest.user.ext.digitrust).to.not.be.null; + expect(ortbRequest.user.ext.digitrust.id).to.equal('userid_digitrust'); + expect(ortbRequest.user.ext.digitrust.keyv).to.equal(4); + }); + it('Verify new external user id partners', function () { + const bidRequests = deepClone(slotConfigs); + bidRequests[0].userId = { + britepoolid: 'britepool_id123', + criteoId: 'criteo_id234', + idl_env: 'idl_id123', + id5id: { uid: 'id5id_234' }, + parrableId: { eid: 'parrable_id234' }, + lipb: { + lipbid: 'liveintent_id123' + } + }; + const userVerify = function(obj, source, id) { + expect(obj).to.deep.equal({ + source, + uids: [{ + id + }] + }); + }; const request = spec.buildRequests(bidRequests, bidderRequest); expect(request).to.be.not.null; const ortbRequest = request.data; @@ -639,7 +677,13 @@ describe('PulsePoint Adapter Tests', function () { expect(ortbRequest.user).to.not.be.undefined; expect(ortbRequest.user.ext).to.not.be.undefined; expect(ortbRequest.user.ext.eids).to.not.be.undefined; - expect(ortbRequest.user.ext.eids).to.deep.equal(bidRequests[0].userIdAsEids); + expect(ortbRequest.user.ext.eids).to.have.lengthOf(6); + userVerify(ortbRequest.user.ext.eids[0], 'britepool.com', 'britepool_id123'); + userVerify(ortbRequest.user.ext.eids[1], 'criteo', 'criteo_id234'); + userVerify(ortbRequest.user.ext.eids[2], 'identityLink', 'idl_id123'); + userVerify(ortbRequest.user.ext.eids[3], 'id5-sync.com', 'id5id_234'); + userVerify(ortbRequest.user.ext.eids[4], 'parrable.com', 'parrable_id234'); + userVerify(ortbRequest.user.ext.eids[5], 'liveintent.com', 'liveintent_id123'); }); it('Verify multiple adsizes', function () { const bidRequests = deepClone(slotConfigs); diff --git a/test/spec/modules/readpeakBidAdapter_spec.js b/test/spec/modules/readpeakBidAdapter_spec.js index 04358fad52b..eefd7792a7c 100644 --- a/test/spec/modules/readpeakBidAdapter_spec.js +++ b/test/spec/modules/readpeakBidAdapter_spec.js @@ -4,13 +4,9 @@ import { config } from 'src/config.js'; import { parseUrl } from 'src/utils.js'; describe('ReadPeakAdapter', function() { - let baseBidRequest; - let bannerBidRequest; - let nativeBidRequest; - let nativeServerResponse; - let nativeServerRequest; - let bannerServerResponse; - let bannerServerRequest; + let bidRequest; + let serverResponse; + let serverRequest; let bidderRequest; beforeEach(function() { @@ -20,8 +16,15 @@ describe('ReadPeakAdapter', function() { } }; - baseBidRequest = { + bidRequest = { bidder: 'readpeak', + nativeParams: { + title: { required: true, len: 200 }, + image: { wmin: 100 }, + sponsoredBy: {}, + body: { required: false }, + cta: { required: false } + }, params: { bidfloor: 5.0, publisherId: '11bc5dd5-7421-4dd8-c926-40fa653bec76', @@ -31,46 +34,17 @@ describe('ReadPeakAdapter', function() { bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', - transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', - }; - - nativeBidRequest = { - ...baseBidRequest, - nativeParams: { - title: { required: true, len: 200 }, - image: { wmin: 100 }, - sponsoredBy: {}, - body: { required: false }, - cta: { required: false } - }, - mediaTypes: { - native: { - title: { required: true, len: 200 }, - image: { wmin: 100 }, - sponsoredBy: {}, - body: { required: false }, - cta: { required: false } - }, - } + transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' }; - bannerBidRequest = { - ...baseBidRequest, - mediaTypes: { - banner: { - sizes: [[640, 320], [300, 600]], - } - }, - sizes: [[640, 320], [300, 600]], - } - nativeServerResponse = { - id: baseBidRequest.bidderRequestId, + serverResponse = { + id: bidRequest.bidderRequestId, cur: 'USD', seatbid: [ { bid: [ { - id: 'baseBidRequest.bidId', - impid: baseBidRequest.bidId, + id: 'bidRequest.bidId', + impid: bidRequest.bidId, price: 0.12, cid: '12', crid: '123', @@ -117,30 +91,7 @@ describe('ReadPeakAdapter', function() { } ] }; - bannerServerResponse = { - id: baseBidRequest.bidderRequestId, - cur: 'USD', - seatbid: [ - { - bid: [ - { - id: 'baseBidRequest.bidId', - impid: baseBidRequest.bidId, - price: 0.12, - cid: '12', - crid: '123', - adomain: ['readpeak.com'], - adm: '', - burl: 'https://localhost:8081/url/b?d=0O95O4326I528Ie4d39f94-533d-4577-a579-585fd4c02b0aI0I352e303232363639333139393939393939&c=USD&p=${AUCTION_PRICE}&bad=0-0-95O0O0OdO640360&gc=0', - nurl: 'https://localhost:8081/url/n?d=0O95O4326I528Ie4d39f94-533d-4577-a579-585fd4c02b0aI0I352e303232363639333139393939393939&gc=0', - w: 640, - h: 360, - } - ] - } - ] - }; - nativeServerRequest = { + serverRequest = { method: 'POST', url: 'http://localhost:60080/header/prebid', data: JSON.stringify({ @@ -150,7 +101,7 @@ describe('ReadPeakAdapter', function() { id: '2ffb201a808da7', native: { request: - '{\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":70}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":150,\"hmin\":150}},{\"id\":4,\"required\":1,\"data\":{\"type\":2,\"len\":120}}]}', + '{"assets":[{"id":1,"required":1,"title":{"len":200}},{"id":2,"required":0,"data":{"type":1,"len":50}},{"id":3,"required":0,"img":{"type":3,"wmin":100,"hmin":150}}]}', ver: '1.1' }, bidfloor: 5, @@ -176,362 +127,175 @@ describe('ReadPeakAdapter', function() { isPrebid: true }) }; - bannerServerRequest = { - method: 'POST', - url: 'http://localhost:60080/header/prebid', - data: JSON.stringify({ - id: '178e34bad3658f', - imp: [ - { - id: '2ffb201a808da7', - bidfloor: 5, - bidfloorcur: 'USD', - tagId: 'test-tag-1', - banner: { - w: 640, - h: 360, - format: [ - { w: 640, h: 360 }, - { w: 320, h: 320 }, - ] - } - } - ], - site: { - publisher: { - id: '11bc5dd5-7421-4dd8-c926-40fa653bec76' - }, - id: '11bc5dd5-7421-4dd8-c926-40fa653bec77', - ref: '', - page: 'http://localhost', - domain: 'localhost' - }, - app: null, - device: { - ua: - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/61.0.3163.100 Safari/537.36', - language: 'en-US' - }, - isPrebid: true - }) - }; }); - describe('Native', function() { - describe('spec.isBidRequestValid', function() { - it('should return true when the required params are passed', function() { - expect(spec.isBidRequestValid(nativeBidRequest)).to.equal(true); - }); - - it('should return false when the "publisherId" param is missing', function() { - nativeBidRequest.params = { - bidfloor: 5.0 - }; - expect(spec.isBidRequestValid(nativeBidRequest)).to.equal(false); - }); - - it('should return false when no bid params are passed', function() { - nativeBidRequest.params = {}; - expect(spec.isBidRequestValid(nativeBidRequest)).to.equal(false); - }); - - it('should return false when a bid request is not passed', function() { - expect(spec.isBidRequestValid()).to.equal(false); - expect(spec.isBidRequestValid({})).to.equal(false); - }); + describe('spec.isBidRequestValid', function() { + it('should return true when the required params are passed', function() { + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - describe('spec.buildRequests', function() { - it('should create a POST request for every bid', function() { - const request = spec.buildRequests([nativeBidRequest], bidderRequest); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENDPOINT); - }); - - it('should attach request data', function() { - config.setConfig({ - currency: { - adServerCurrency: 'EUR' - } - }); - - const request = spec.buildRequests([nativeBidRequest], bidderRequest); - - const data = JSON.parse(request.data); - - expect(data.source.ext.prebid).to.equal('$prebid.version$'); - expect(data.id).to.equal(nativeBidRequest.bidderRequestId); - expect(data.imp[0].bidfloor).to.equal(nativeBidRequest.params.bidfloor); - expect(data.imp[0].bidfloorcur).to.equal('USD'); - expect(data.imp[0].tagId).to.equal('test-tag-1'); - expect(data.site.publisher.id).to.equal(nativeBidRequest.params.publisherId); - expect(data.site.id).to.equal(nativeBidRequest.params.siteId); - expect(data.site.page).to.equal(bidderRequest.refererInfo.referer); - expect(data.site.domain).to.equal(parseUrl(bidderRequest.refererInfo.referer).hostname); - expect(data.device).to.deep.contain({ - ua: navigator.userAgent, - language: navigator.language - }); - expect(data.cur).to.deep.equal(['EUR']); - expect(data.user).to.be.undefined; - expect(data.regs).to.be.undefined; - }); - - it('should get bid floor from module', function() { - const floorModuleData = { - currency: 'USD', - floor: 3.2, - } - nativeBidRequest.getFloor = function () { - return floorModuleData - } - const request = spec.buildRequests([nativeBidRequest], bidderRequest); - - const data = JSON.parse(request.data); - - expect(data.source.ext.prebid).to.equal('$prebid.version$'); - expect(data.id).to.equal(nativeBidRequest.bidderRequestId); - expect(data.imp[0].bidfloor).to.equal(floorModuleData.floor); - expect(data.imp[0].bidfloorcur).to.equal(floorModuleData.currency); - }); - - it('should send gdpr data when gdpr does not apply', function() { - const gdprData = { - gdprConsent: { - gdprApplies: false, - consentString: undefined, - } - } - const request = spec.buildRequests([nativeBidRequest], {...bidderRequest, ...gdprData}); - - const data = JSON.parse(request.data); - - expect(data.user).to.deep.equal({ - ext: { - consent: '' - } - }); - expect(data.regs).to.deep.equal({ - ext: { - gdpr: false - } - }); - }); - - it('should send gdpr data when gdpr applies', function() { - const tcString = 'sometcstring'; - const gdprData = { - gdprConsent: { - gdprApplies: true, - consentString: tcString - } - } - const request = spec.buildRequests([nativeBidRequest], {...bidderRequest, ...gdprData}); - - const data = JSON.parse(request.data); - - expect(data.user).to.deep.equal({ - ext: { - consent: tcString - } - }); - expect(data.regs).to.deep.equal({ - ext: { - gdpr: true - } - }); - }); + it('should return false when the native params are missing', function() { + bidRequest.nativeParams = undefined; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - describe('spec.interpretResponse', function() { - it('should return no bids if the response is not valid', function() { - const bidResponse = spec.interpretResponse({ body: null }, nativeServerRequest); - expect(bidResponse.length).to.equal(0); - }); + it('should return false when the "publisherId" param is missing', function() { + bidRequest.params = { + bidfloor: 5.0 + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); - it('should return a valid bid response', function() { - const bidResponse = spec.interpretResponse( - { body: nativeServerResponse }, - nativeServerRequest - )[0]; - expect(bidResponse).to.contain({ - requestId: nativeBidRequest.bidId, - cpm: nativeServerResponse.seatbid[0].bid[0].price, - creativeId: nativeServerResponse.seatbid[0].bid[0].crid, - ttl: 300, - netRevenue: true, - mediaType: 'native', - currency: nativeServerResponse.cur - }); + it('should return false when no bid params are passed', function() { + bidRequest.params = {}; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); - expect(bidResponse.meta).to.deep.equal({ - advertiserDomains: ['readpeak.com'], - }) - expect(bidResponse.native.title).to.equal('Title'); - expect(bidResponse.native.body).to.equal('Description'); - expect(bidResponse.native.image).to.deep.equal({ - url: 'http://url.to/image', - width: 750, - height: 500 - }); - expect(bidResponse.native.clickUrl).to.equal( - 'http%3A%2F%2Furl.to%2Ftarget' - ); - expect(bidResponse.native.impressionTrackers).to.contain( - 'http://url.to/pixeltracker' - ); - }); + it('should return false when a bid request is not passed', function() { + expect(spec.isBidRequestValid()).to.equal(false); + expect(spec.isBidRequestValid({})).to.equal(false); }); }); - describe('Banner', function() { - describe('spec.isBidRequestValid', function() { - it('should return true when the required params are passed', function() { - expect(spec.isBidRequestValid(bannerBidRequest)).to.equal(true); - }); + describe('spec.buildRequests', function() { + it('should create a POST request for every bid', function() { + const request = spec.buildRequests([bidRequest], bidderRequest); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENDPOINT); + }); - it('should return false when the "publisherId" param is missing', function() { - bannerBidRequest.params = { - bidfloor: 5.0 - }; - expect(spec.isBidRequestValid(bannerBidRequest)).to.equal(false); + it('should attach request data', function() { + config.setConfig({ + currency: { + adServerCurrency: 'EUR' + } }); - it('should return false when no bid params are passed', function() { - bannerBidRequest.params = {}; - expect(spec.isBidRequestValid(bannerBidRequest)).to.equal(false); + const request = spec.buildRequests([bidRequest], bidderRequest); + + const data = JSON.parse(request.data); + + expect(data.source.ext.prebid).to.equal('$prebid.version$'); + expect(data.id).to.equal(bidRequest.bidderRequestId); + expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); + expect(data.imp[0].bidfloorcur).to.equal('USD'); + expect(data.imp[0].tagId).to.equal('test-tag-1'); + expect(data.site.publisher.id).to.equal(bidRequest.params.publisherId); + expect(data.site.id).to.equal(bidRequest.params.siteId); + expect(data.site.page).to.equal(bidderRequest.refererInfo.referer); + expect(data.site.domain).to.equal(parseUrl(bidderRequest.refererInfo.referer).hostname); + expect(data.device).to.deep.contain({ + ua: navigator.userAgent, + language: navigator.language }); + expect(data.cur).to.deep.equal(['EUR']); + expect(data.user).to.be.undefined; + expect(data.regs).to.be.undefined; }); - describe('spec.buildRequests', function() { - it('should create a POST request for every bid', function() { - const request = spec.buildRequests([bannerBidRequest], bidderRequest); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENDPOINT); - }); + it('should get bid floor from module', function() { + const floorModuleData = { + currency: 'USD', + floor: 3.2, + } + bidRequest.getFloor = function () { + return floorModuleData + } + const request = spec.buildRequests([bidRequest], bidderRequest); - it('should attach request data', function() { - config.setConfig({ - currency: { - adServerCurrency: 'EUR' - } - }); + const data = JSON.parse(request.data); - const request = spec.buildRequests([bannerBidRequest], bidderRequest); + expect(data.source.ext.prebid).to.equal('$prebid.version$'); + expect(data.id).to.equal(bidRequest.bidderRequestId); + expect(data.imp[0].bidfloor).to.equal(floorModuleData.floor); + expect(data.imp[0].bidfloorcur).to.equal(floorModuleData.currency); + }); - const data = JSON.parse(request.data); + it('should send gdpr data when gdpr does not apply', function() { + const gdprData = { + gdprConsent: { + gdprApplies: false, + consentString: undefined, + } + } + const request = spec.buildRequests([bidRequest], {...bidderRequest, ...gdprData}); - expect(data.source.ext.prebid).to.equal('$prebid.version$'); - expect(data.id).to.equal(bannerBidRequest.bidderRequestId); - expect(data.imp[0].bidfloor).to.equal(bannerBidRequest.params.bidfloor); - expect(data.imp[0].bidfloorcur).to.equal('USD'); - expect(data.imp[0].tagId).to.equal('test-tag-1'); - expect(data.site.publisher.id).to.equal(bannerBidRequest.params.publisherId); - expect(data.site.id).to.equal(bannerBidRequest.params.siteId); - expect(data.site.page).to.equal(bidderRequest.refererInfo.referer); - expect(data.site.domain).to.equal(parseUrl(bidderRequest.refererInfo.referer).hostname); - expect(data.device).to.deep.contain({ - ua: navigator.userAgent, - language: navigator.language - }); - expect(data.cur).to.deep.equal(['EUR']); - expect(data.user).to.be.undefined; - expect(data.regs).to.be.undefined; - }); + const data = JSON.parse(request.data); - it('should get bid floor from module', function() { - const floorModuleData = { - currency: 'USD', - floor: 3.2, + expect(data.user).to.deep.equal({ + ext: { + consent: '' } - bannerBidRequest.getFloor = function () { - return floorModuleData + }); + expect(data.regs).to.deep.equal({ + ext: { + gdpr: false } - const request = spec.buildRequests([bannerBidRequest], bidderRequest); - - const data = JSON.parse(request.data); - - expect(data.source.ext.prebid).to.equal('$prebid.version$'); - expect(data.id).to.equal(bannerBidRequest.bidderRequestId); - expect(data.imp[0].bidfloor).to.equal(floorModuleData.floor); - expect(data.imp[0].bidfloorcur).to.equal(floorModuleData.currency); }); + }); - it('should send gdpr data when gdpr does not apply', function() { - const gdprData = { - gdprConsent: { - gdprApplies: false, - consentString: undefined, - } + it('should send gdpr data when gdpr applies', function() { + const tcString = 'sometcstring'; + const gdprData = { + gdprConsent: { + gdprApplies: true, + consentString: tcString } - const request = spec.buildRequests([bannerBidRequest], {...bidderRequest, ...gdprData}); + } + const request = spec.buildRequests([bidRequest], {...bidderRequest, ...gdprData}); - const data = JSON.parse(request.data); + const data = JSON.parse(request.data); - expect(data.user).to.deep.equal({ - ext: { - consent: '' - } - }); - expect(data.regs).to.deep.equal({ - ext: { - gdpr: false - } - }); + expect(data.user).to.deep.equal({ + ext: { + consent: tcString + } }); - - it('should send gdpr data when gdpr applies', function() { - const tcString = 'sometcstring'; - const gdprData = { - gdprConsent: { - gdprApplies: true, - consentString: tcString - } + expect(data.regs).to.deep.equal({ + ext: { + gdpr: true } - const request = spec.buildRequests([bannerBidRequest], {...bidderRequest, ...gdprData}); - - const data = JSON.parse(request.data); - - expect(data.user).to.deep.equal({ - ext: { - consent: tcString - } - }); - expect(data.regs).to.deep.equal({ - ext: { - gdpr: true - } - }); }); }); + }); + + describe('spec.interpretResponse', function() { + it('should return no bids if the response is not valid', function() { + const bidResponse = spec.interpretResponse({ body: null }, serverRequest); + expect(bidResponse.length).to.equal(0); + }); - describe('spec.interpretResponse', function() { - it('should return no bids if the response is not valid', function() { - const bidResponse = spec.interpretResponse({ body: null }, bannerServerRequest); - expect(bidResponse.length).to.equal(0); + it('should return a valid bid response', function() { + const bidResponse = spec.interpretResponse( + { body: serverResponse }, + serverRequest + )[0]; + expect(bidResponse).to.contain({ + requestId: bidRequest.bidId, + cpm: serverResponse.seatbid[0].bid[0].price, + creativeId: serverResponse.seatbid[0].bid[0].crid, + ttl: 300, + netRevenue: true, + mediaType: 'native', + currency: serverResponse.cur }); - it('should return a valid bid response', function() { - const bidResponse = spec.interpretResponse( - { body: bannerServerResponse }, - bannerServerRequest - )[0]; - expect(bidResponse).to.contain({ - requestId: bannerBidRequest.bidId, - cpm: bannerServerResponse.seatbid[0].bid[0].price, - creativeId: bannerServerResponse.seatbid[0].bid[0].crid, - ttl: 300, - netRevenue: true, - mediaType: 'banner', - currency: bannerServerResponse.cur, - ad: bannerServerResponse.seatbid[0].bid[0].adm, - width: bannerServerResponse.seatbid[0].bid[0].w, - height: bannerServerResponse.seatbid[0].bid[0].h, - }); - expect(bidResponse.meta).to.deep.equal({ - advertiserDomains: ['readpeak.com'], - }); + expect(bidResponse.meta).to.deep.equal({ + advertiserDomains: ['readpeak.com'], + }) + expect(bidResponse.native.title).to.equal('Title'); + expect(bidResponse.native.body).to.equal('Description'); + expect(bidResponse.native.image).to.deep.equal({ + url: 'http://url.to/image', + width: 750, + height: 500 }); + expect(bidResponse.native.clickUrl).to.equal( + 'http%3A%2F%2Furl.to%2Ftarget' + ); + expect(bidResponse.native.impressionTrackers).to.contain( + 'http://url.to/pixeltracker' + ); }); }); }); diff --git a/test/spec/modules/realTimeDataModule_spec.js b/test/spec/modules/realTimeDataModule_spec.js index daeeb9bc47c..b84aef15feb 100644 --- a/test/spec/modules/realTimeDataModule_spec.js +++ b/test/spec/modules/realTimeDataModule_spec.js @@ -1,9 +1,6 @@ import * as rtdModule from 'modules/rtdModule/index.js'; -import {config} from 'src/config.js'; +import { config } from 'src/config.js'; import * as sinon from 'sinon'; -import {default as CONSTANTS} from '../../../src/constants.json'; -import * as events from '../../../src/events.js'; -import 'src/prebid.js'; const getBidRequestDataSpy = sinon.spy(); @@ -61,136 +58,33 @@ const conf = { }; describe('Real time module', function () { - let eventHandlers; - let sandbox; - - function mockEmitEvent(event, ...args) { - (eventHandlers[event] || []).forEach((h) => h(...args)); - } - - before(() => { - eventHandlers = {}; - sandbox = sinon.sandbox.create(); - sandbox.stub(events, 'on').callsFake((event, handler) => { - if (!eventHandlers.hasOwnProperty(event)) { - eventHandlers[event] = []; - } - eventHandlers[event].push(handler); - }); + before(function () { + rtdModule.attachRealTimeDataProvider(validSM); + rtdModule.attachRealTimeDataProvider(invalidSM); + rtdModule.attachRealTimeDataProvider(failureSM); + rtdModule.attachRealTimeDataProvider(nonConfSM); + rtdModule.attachRealTimeDataProvider(validSMWait); }); - after(() => { - sandbox.restore(); + after(function () { + config.resetConfig(); }); - describe('', () => { - const PROVIDERS = [validSM, invalidSM, failureSM, nonConfSM, validSMWait]; - let _detachers; - - beforeEach(function () { - _detachers = PROVIDERS.map(rtdModule.attachRealTimeDataProvider); - rtdModule.init(config); - config.setConfig(conf); - }); - - afterEach(function () { - _detachers.forEach((f) => f()); - config.resetConfig(); - }); - - it('should use only valid modules', function () { - expect(rtdModule.subModules).to.eql([validSMWait, validSM]); - }); - - it('should be able to modify bid request', function (done) { - rtdModule.setBidRequestsData(() => { - assert(getBidRequestDataSpy.calledTwice); - assert(getBidRequestDataSpy.calledWith({bidRequest: {}})); - done(); - }, {bidRequest: {}}) - }); - - it('sould place targeting on adUnits', function (done) { - const auction = { - adUnitCodes: ['ad1', 'ad2'], - adUnits: [ - { - code: 'ad1' - }, - { - code: 'ad2', - adserverTargeting: {preKey: 'preValue'} - } - ] - }; + beforeEach(function () { + config.setConfig(conf); + }); - const expectedAdUnits = [ - { - code: 'ad1', - adserverTargeting: {key: 'validSMWait'} - }, - { - code: 'ad2', - adserverTargeting: { - preKey: 'preValue', - key: 'validSM' - } - } - ]; + it('should use only valid modules', function () { + rtdModule.init(config); + expect(rtdModule.subModules).to.eql([validSMWait, validSM]); + }); - const adUnits = rtdModule.getAdUnitTargeting(auction); - assert.deepEqual(expectedAdUnits, adUnits) + it('should be able to modify bid request', function (done) { + rtdModule.setBidRequestsData(() => { + assert(getBidRequestDataSpy.calledTwice); + assert(getBidRequestDataSpy.calledWith({bidRequest: {}})); done(); - }); - - describe('setBidRequestData', () => { - let withWait, withoutWait; - - function runSetBidRequestData() { - return new Promise((resolve) => { - rtdModule.setBidRequestsData(resolve, {bidRequest: {}}); - }); - } - - beforeEach(() => { - withWait = { - submod: validSMWait, - cbTime: 0, - cbRan: false - }; - withoutWait = { - submod: validSM, - cbTime: 0, - cbRan: false - }; - - [withWait, withoutWait].forEach((c) => { - c.submod.getBidRequestData = sinon.stub().callsFake((_, cb) => { - setTimeout(() => { - c.cbRan = true; - cb(); - }, c.cbTime); - }); - }); - }); - - it('should allow non-priority submodules to run synchronously', () => { - withWait.cbTime = withoutWait.cbTime = 0; - return runSetBidRequestData().then(() => { - expect(withWait.cbRan).to.be.true; - expect(withoutWait.cbRan).to.be.true; - }) - }); - - it('should not wait for non-priority submodules if priority ones complete first', () => { - withWait.cbTime = 10; - withoutWait.cbTime = 100; - return runSetBidRequestData().then(() => { - expect(withWait.cbRan).to.be.true; - expect(withoutWait.cbRan).to.be.false; - }); - }); - }); + }, {bidRequest: {}}) }); it('deep merge object', function () { @@ -231,78 +125,36 @@ describe('Real time module', function () { assert.deepEqual(expected, merged); }); - describe('event', () => { - const EVENTS = { - [CONSTANTS.EVENTS.AUCTION_INIT]: 'onAuctionInitEvent', - [CONSTANTS.EVENTS.AUCTION_END]: 'onAuctionEndEvent', - [CONSTANTS.EVENTS.BID_RESPONSE]: 'onBidResponseEvent', - [CONSTANTS.EVENTS.BID_REQUESTED]: 'onBidRequestEvent' - } - const conf = { - 'realTimeData': { - dataProviders: [ - { - 'name': 'tp1', - }, - { - 'name': 'tp2', - } - ] - } + it('sould place targeting on adUnits', function (done) { + const auction = { + adUnitCodes: ['ad1', 'ad2'], + adUnits: [ + { + code: 'ad1' + }, + { + code: 'ad2', + adserverTargeting: {preKey: 'preValue'} + } + ] }; - let providers; - let _detachers; - function eventHandlingProvider(name) { - const provider = { - name: name, - init: () => true, + const expectedAdUnits = [ + { + code: 'ad1', + adserverTargeting: {key: 'validSMWait'} + }, + { + code: 'ad2', + adserverTargeting: { + preKey: 'preValue', + key: 'validSM' + } } - Object.values(EVENTS).forEach((ev) => provider[ev] = sinon.spy()); - return provider; - } - - beforeEach(() => { - providers = [eventHandlingProvider('tp1'), eventHandlingProvider('tp2')]; - _detachers = providers.map(rtdModule.attachRealTimeDataProvider); - rtdModule.init(config); - config.setConfig(conf); - }); + ]; - afterEach(() => { - _detachers.forEach((d) => d()) - config.resetConfig(); - }); - - it('should set targeting for auctionEnd', () => { - providers.forEach(p => p.getTargetingData = sinon.spy()); - const auction = { - adUnitCodes: ['a1'], - adUnits: [{code: 'a1'}] - }; - mockEmitEvent(CONSTANTS.EVENTS.AUCTION_END, auction); - providers.forEach(p => { - expect(p.getTargetingData.calledWith(auction.adUnitCodes)).to.be.true; - }); - }); - - Object.entries(EVENTS).forEach(([event, hook]) => { - it(`'${event}' should be propagated to providers through '${hook}'`, () => { - const eventArg = {}; - mockEmitEvent(event, eventArg); - providers.forEach((provider) => { - const providerConf = conf.realTimeData.dataProviders.find((cfg) => cfg.name === provider.name); - expect(provider[hook].called).to.be.true; - expect(provider[hook].args).to.have.length(1); - expect(provider[hook].args[0]).to.include.members([eventArg, providerConf]) - }) - }); - - it(`${event} should not fail to propagate elsewhere if a provider throws in its event handler`, () => { - providers[0][hook] = function () { throw new Error() }; - mockEmitEvent(event); - expect(providers[1][hook].called).to.be.true; - }); - }); - }); + const adUnits = rtdModule.getAdUnitTargeting(auction); + assert.deepEqual(expectedAdUnits, adUnits) + done(); + }) }); diff --git a/test/spec/modules/relaidoBidAdapter_spec.js b/test/spec/modules/relaidoBidAdapter_spec.js index f0d381ee3ed..e372c67bb4e 100644 --- a/test/spec/modules/relaidoBidAdapter_spec.js +++ b/test/spec/modules/relaidoBidAdapter_spec.js @@ -20,12 +20,8 @@ describe('RelaidoAdapter', function () { let bidderRequest; let serverResponse; let serverRequest; - let generateUUIDStub; - let triggerPixelStub; beforeEach(function () { - generateUUIDStub = sinon.stub(utils, 'generateUUID').returns(relaido_uuid); - triggerPixelStub = sinon.stub(utils, 'triggerPixel'); bidRequest = { bidder: 'relaido', params: { @@ -57,42 +53,26 @@ describe('RelaidoAdapter', function () { serverResponse = { body: { status: 'ok', - ads: [{ - placementId: 100000, - width: 640, - height: 360, - bidId: '2ed93003f7bb99', - price: 500, - model: 'vcpm', - currency: 'JPY', - creativeId: 1000, - vast: '', - syncUrl: 'https://relaido/sync.html', - adomain: ['relaido.co.jp', 'www.cmertv.co.jp'], - mediaType: 'video' - }], - playerUrl: 'https://relaido/player.js', - syncUrl: 'https://api-dev.ulizaex.com/tr/v1/prebid/sync.html', + price: 500, + model: 'vcpm', + currency: 'JPY', + creativeId: 1000, uuid: relaido_uuid, + vast: '', + playerUrl: 'https://relaido/player.js', + syncUrl: 'https://relaido/sync.html', + adomain: ['relaido.co.jp', 'www.cmertv.co.jp'] } }; serverRequest = { - method: 'POST', - data: { - bids: [{ - bidId: bidRequest.bidId, - width: bidRequest.mediaTypes.video.playerSize[0][0], - height: bidRequest.mediaTypes.video.playerSize[0][1], - mediaType: 'video'}] - } + method: 'GET', + bidId: bidRequest.bidId, + width: bidRequest.mediaTypes.video.playerSize[0][0], + height: bidRequest.mediaTypes.video.playerSize[0][1], + mediaType: 'video', }; }); - afterEach(() => { - generateUUIDStub.restore(); - triggerPixelStub.restore(); - }); - describe('spec.isBidRequestValid', function () { it('should return true when the required params are passed by video', function () { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); @@ -206,23 +186,27 @@ describe('RelaidoAdapter', function () { describe('spec.buildRequests', function () { it('should build bid requests by video', function () { const bidRequests = spec.buildRequests([bidRequest], bidderRequest); - const data = JSON.parse(bidRequests.data); - expect(data.bids).to.have.lengthOf(1); - const request = data.bids[0]; - expect(bidRequests.method).to.equal('POST'); - expect(bidRequests.url).to.equal('https://api.relaido.jp/bid/v1/sprebid'); - expect(data.ref).to.equal(bidderRequest.refererInfo.referer); - expect(data.timeout_ms).to.equal(bidderRequest.timeout); - expect(request.ad_unit_code).to.equal(bidRequest.adUnitCode); - expect(request.auction_id).to.equal(bidRequest.auctionId); - expect(data.bidder).to.equal(bidRequest.bidder); - expect(request.bidder_request_id).to.equal(bidRequest.bidderRequestId); - expect(data.bid_requests_count).to.equal(bidRequest.bidRequestsCount); - expect(request.bid_id).to.equal(bidRequest.bidId); - expect(request.transaction_id).to.equal(bidRequest.transactionId); - expect(request.media_type).to.equal('video'); - expect(data.uuid).to.equal(relaido_uuid); - expect(data.pv).to.equal('$prebid.version$'); + expect(bidRequests).to.have.lengthOf(1); + const request = bidRequests[0]; + expect(request.method).to.equal('GET'); + expect(request.url).to.equal('https://api.relaido.jp/bid/v1/prebid/100000'); + expect(request.bidId).to.equal(bidRequest.bidId); + expect(request.width).to.equal(bidRequest.mediaTypes.video.playerSize[0][0]); + expect(request.height).to.equal(bidRequest.mediaTypes.video.playerSize[0][1]); + expect(request.mediaType).to.equal('video'); + expect(request.data.ref).to.equal(bidderRequest.refererInfo.referer); + expect(request.data.timeout_ms).to.equal(bidderRequest.timeout); + expect(request.data.ad_unit_code).to.equal(bidRequest.adUnitCode); + expect(request.data.auction_id).to.equal(bidRequest.auctionId); + expect(request.data.bidder).to.equal(bidRequest.bidder); + expect(request.data.bidder_request_id).to.equal(bidRequest.bidderRequestId); + expect(request.data.bid_requests_count).to.equal(bidRequest.bidRequestsCount); + expect(request.data.bid_id).to.equal(bidRequest.bidId); + expect(request.data.transaction_id).to.equal(bidRequest.transactionId); + expect(request.data.media_type).to.equal('video'); + expect(request.data.uuid).to.equal(relaido_uuid); + expect(request.data.width).to.equal(bidRequest.mediaTypes.video.playerSize[0][0]); + expect(request.data.height).to.equal(bidRequest.mediaTypes.video.playerSize[0][1]); }); it('should build bid requests by banner', function () { @@ -242,10 +226,9 @@ describe('RelaidoAdapter', function () { } }; const bidRequests = spec.buildRequests([bidRequest], bidderRequest); - const data = JSON.parse(bidRequests.data); - expect(data.bids).to.have.lengthOf(1); - const request = data.bids[0]; - expect(request.media_type).to.equal('banner'); + expect(bidRequests).to.have.lengthOf(1); + const request = bidRequests[0]; + expect(request.mediaType).to.equal('banner'); }); it('should take 1x1 size', function () { @@ -265,30 +248,22 @@ describe('RelaidoAdapter', function () { } }; const bidRequests = spec.buildRequests([bidRequest], bidderRequest); - const data = JSON.parse(bidRequests.data); - expect(data.bids).to.have.lengthOf(1); - const request = data.bids[0]; + expect(bidRequests).to.have.lengthOf(1); + const request = bidRequests[0]; + // eslint-disable-next-line no-console + console.log(bidRequests); expect(request.width).to.equal(1); }); it('The referrer should be the last', function () { const bidRequests = spec.buildRequests([bidRequest], bidderRequest); - const data = JSON.parse(bidRequests.data); - expect(data.bids).to.have.lengthOf(1); - const keys = Object.keys(data); + expect(bidRequests).to.have.lengthOf(1); + const request = bidRequests[0]; + const keys = Object.keys(request.data); expect(keys[0]).to.equal('version'); expect(keys[keys.length - 1]).to.equal('ref'); }); - - it('should get imuid', function () { - bidRequest.userId = {} - bidRequest.userId.imuid = 'i.tjHcK_7fTcqnbrS_YA2vaw'; - const bidRequests = spec.buildRequests([bidRequest], bidderRequest); - const data = JSON.parse(bidRequests.data); - expect(data.bids).to.have.lengthOf(1); - expect(data.imuid).to.equal('i.tjHcK_7fTcqnbrS_YA2vaw'); - }); }); describe('spec.interpretResponse', function () { @@ -296,54 +271,35 @@ describe('RelaidoAdapter', function () { const bidResponses = spec.interpretResponse(serverResponse, serverRequest); expect(bidResponses).to.have.lengthOf(1); const response = bidResponses[0]; - expect(response.requestId).to.equal(serverRequest.data.bids[0].bidId); - expect(response.width).to.equal(serverRequest.data.bids[0].width); - expect(response.height).to.equal(serverRequest.data.bids[0].height); - expect(response.cpm).to.equal(serverResponse.body.ads[0].price); - expect(response.currency).to.equal(serverResponse.body.ads[0].currency); - expect(response.creativeId).to.equal(serverResponse.body.ads[0].creativeId); - expect(response.vastXml).to.equal(serverResponse.body.ads[0].vast); - expect(response.playerUrl).to.equal(serverResponse.body.playerUrl); - expect(response.meta.advertiserDomains).to.equal(serverResponse.body.ads[0].adomain); + expect(response.requestId).to.equal(serverRequest.bidId); + expect(response.width).to.equal(serverRequest.width); + expect(response.height).to.equal(serverRequest.height); + expect(response.cpm).to.equal(serverResponse.body.price); + expect(response.currency).to.equal(serverResponse.body.currency); + expect(response.creativeId).to.equal(serverResponse.body.creativeId); + expect(response.vastXml).to.equal(serverResponse.body.vast); + expect(response.meta.advertiserDomains).to.equal(serverResponse.body.adomain); expect(response.meta.mediaType).to.equal(VIDEO); expect(response.ad).to.be.undefined; }); it('should build bid response by banner', function () { - serverResponse.body.ads[0].mediaType = 'banner'; + serverRequest.mediaType = 'banner'; const bidResponses = spec.interpretResponse(serverResponse, serverRequest); expect(bidResponses).to.have.lengthOf(1); const response = bidResponses[0]; - expect(response.requestId).to.equal(serverRequest.data.bids[0].bidId); - expect(response.width).to.equal(serverRequest.data.bids[0].width); - expect(response.height).to.equal(serverRequest.data.bids[0].height); - expect(response.cpm).to.equal(serverResponse.body.ads[0].price); - expect(response.currency).to.equal(serverResponse.body.ads[0].currency); - expect(response.creativeId).to.equal(serverResponse.body.ads[0].creativeId); + expect(response.requestId).to.equal(serverRequest.bidId); + expect(response.width).to.equal(serverRequest.width); + expect(response.height).to.equal(serverRequest.height); + expect(response.cpm).to.equal(serverResponse.body.price); + expect(response.currency).to.equal(serverResponse.body.currency); + expect(response.creativeId).to.equal(serverResponse.body.creativeId); expect(response.vastXml).to.be.undefined; - expect(response.playerUrl).to.equal(serverResponse.body.playerUrl); expect(response.ad).to.include(`
`); expect(response.ad).to.include(``); expect(response.ad).to.include(`window.RelaidoPlayer.renderAd`); }); - it('should build bid response by video and playerUrl in ads', function () { - serverResponse.body.ads[0].playerUrl = 'https://relaido/player-customized.js'; - const bidResponses = spec.interpretResponse(serverResponse, serverRequest); - expect(bidResponses).to.have.lengthOf(1); - const response = bidResponses[0]; - expect(response.playerUrl).to.equal(serverResponse.body.ads[0].playerUrl); - }); - - it('should build bid response by banner and playerUrl in ads', function () { - serverResponse.body.ads[0].playerUrl = 'https://relaido/player-customized.js'; - serverResponse.body.ads[0].mediaType = 'banner'; - const bidResponses = spec.interpretResponse(serverResponse, serverRequest); - expect(bidResponses).to.have.lengthOf(1); - const response = bidResponses[0]; - expect(response.playerUrl).to.equal(serverResponse.body.ads[0].playerUrl); - }); - it('should not build bid response', function () { serverResponse = {}; const bidResponses = spec.interpretResponse(serverResponse, serverRequest); @@ -394,11 +350,19 @@ describe('RelaidoAdapter', function () { }); describe('spec.onBidWon', function () { + let stub; + beforeEach(() => { + stub = sinon.stub(utils, 'triggerPixel'); + }); + afterEach(() => { + stub.restore(); + }); + it('Should create nurl pixel if bid nurl', function () { let bid = { bidder: bidRequest.bidder, - creativeId: serverResponse.body.ads[0].creativeId, - cpm: serverResponse.body.ads[0].price, + creativeId: serverResponse.body.creativeId, + cpm: serverResponse.body.price, params: [bidRequest.params], auctionId: bidRequest.auctionId, requestId: bidRequest.bidId, @@ -407,7 +371,7 @@ describe('RelaidoAdapter', function () { ref: window.location.href, } spec.onBidWon(bid); - const parser = utils.parseUrl(triggerPixelStub.getCall(0).args[0]); + const parser = utils.parseUrl(stub.getCall(0).args[0]); const query = parser.search; expect(parser.hostname).to.equal('api.relaido.jp'); expect(parser.pathname).to.equal('/tr/v1/prebid/win.gif'); @@ -423,6 +387,14 @@ describe('RelaidoAdapter', function () { }); describe('spec.onTimeout', function () { + let stub; + beforeEach(() => { + stub = sinon.stub(utils, 'triggerPixel'); + }); + afterEach(() => { + stub.restore(); + }); + it('Should create nurl pixel if bid nurl', function () { const data = [{ bidder: bidRequest.bidder, @@ -433,7 +405,7 @@ describe('RelaidoAdapter', function () { timeout: bidderRequest.timeout, }]; spec.onTimeout(data); - const parser = utils.parseUrl(triggerPixelStub.getCall(0).args[0]); + const parser = utils.parseUrl(stub.getCall(0).args[0]); const query = parser.search; expect(parser.hostname).to.equal('api.relaido.jp'); expect(parser.pathname).to.equal('/tr/v1/prebid/timeout.gif'); diff --git a/test/spec/modules/relevantAnalyticsAdapter_spec.js b/test/spec/modules/relevantAnalyticsAdapter_spec.js index 5c818fe01d4..3e31db2d7dc 100644 --- a/test/spec/modules/relevantAnalyticsAdapter_spec.js +++ b/test/spec/modules/relevantAnalyticsAdapter_spec.js @@ -1,6 +1,6 @@ import relevantAnalytics from '../../../modules/relevantAnalyticsAdapter.js'; import adapterManager from 'src/adapterManager'; -import * as events from 'src/events'; +import events from 'src/events'; import constants from 'src/constants.json' import { expect } from 'chai'; diff --git a/test/spec/modules/richaudienceBidAdapter_spec.js b/test/spec/modules/richaudienceBidAdapter_spec.js index 9e9366072be..00ae55823b0 100644 --- a/test/spec/modules/richaudienceBidAdapter_spec.js +++ b/test/spec/modules/richaudienceBidAdapter_spec.js @@ -791,46 +791,6 @@ describe('Richaudience adapter tests', function () { })).to.equal(true); }); - it('should pass schain', function() { - let schain = { - 'ver': '1.0', - 'complete': 1, - 'nodes': [{ - 'asi': 'richaudience.com', - 'sid': '00001', - 'hp': 1 - }, { - 'asi': 'richaudience-2.com', - 'sid': '00002', - 'hp': 1 - }] - } - - DEFAULT_PARAMS_NEW_SIZES[0].schain = { - 'ver': '1.0', - 'complete': 1, - 'nodes': [{ - 'asi': 'richaudience.com', - 'sid': '00001', - 'hp': 1 - }, { - 'asi': 'richaudience-2.com', - 'sid': '00002', - 'hp': 1 - }] - } - - const request = spec.buildRequests(DEFAULT_PARAMS_NEW_SIZES, { - gdprConsent: { - consentString: 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA', - gdprApplies: true - }, - refererInfo: {} - }) - const requestContent = JSON.parse(request[0].data); - expect(requestContent).to.have.property('schain').to.deep.equal(schain); - }) - describe('userSync', function () { it('Verifies user syncs iframe include', function () { config.setConfig({ @@ -945,7 +905,7 @@ describe('Richaudience adapter tests', function () { }, [], { consentString: null, referer: 'http://domain.com', - gdprApplies: false + gdprApplies: true }) expect(syncs).to.have.lengthOf(1); expect(syncs[0].type).to.equal('image'); @@ -982,7 +942,7 @@ describe('Richaudience adapter tests', function () { }, [], { consentString: null, referer: 'http://domain.com', - gdprApplies: false + gdprApplies: true }) expect(syncs).to.have.lengthOf(0); }); diff --git a/test/spec/modules/riseBidAdapter_spec.js b/test/spec/modules/riseBidAdapter_spec.js index 596c4d0f58c..61b307eef21 100644 --- a/test/spec/modules/riseBidAdapter_spec.js +++ b/test/spec/modules/riseBidAdapter_spec.js @@ -2,13 +2,12 @@ import { expect } from 'chai'; import { spec } from 'modules/riseBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import { config } from 'src/config.js'; -import { BANNER, VIDEO } from '../../../src/mediaTypes.js'; -import * as utils from 'src/utils.js'; +import { VIDEO } from '../../../src/mediaTypes.js'; +import { deepClone } from 'src/utils.js'; -const ENDPOINT = 'https://hb.yellowblue.io/hb-multi'; -const TEST_ENDPOINT = 'https://hb.yellowblue.io/hb-multi-test'; +const ENDPOINT = 'https://hb.yellowblue.io/hb'; +const TEST_ENDPOINT = 'https://hb.yellowblue.io/hb-test'; const TTL = 360; -/* eslint no-console: ["error", { allow: ["log", "warn", "error"] }] */ describe('riseAdapter', function () { const adapter = newBidder(spec); @@ -55,29 +54,6 @@ describe('riseAdapter', function () { 'bidId': '299ffc8cca0b87', 'bidderRequestId': '1144f487e563f9', 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d', - 'mediaTypes': { - 'video': { - 'playerSize': [[640, 480]], - 'context': 'instream' - } - }, - 'vastXml': '"..."' - }, - { - 'bidder': spec.code, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250]], - 'params': { - 'org': 'jdye8weeyirk00000001' - }, - 'bidId': '299ffc8cca0b87', - 'bidderRequestId': '1144f487e563f9', - 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d', - 'mediaTypes': { - 'banner': { - } - }, - 'ad': '""' } ]; @@ -101,41 +77,44 @@ describe('riseAdapter', function () { } const placementId = '12345678'; - it('sends the placementId to ENDPOINT via POST', function () { + it('sends the placementId as a query param', function () { bidRequests[0].params.placementId = placementId; - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[0].placementId).to.equal(placementId); + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.data.placement_id).to.equal(placementId); + } }); - it('sends bid request to ENDPOINT via POST', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.equal(ENDPOINT); - expect(request.method).to.equal('POST'); + it('sends bid request to ENDPOINT via GET', function () { + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('GET'); + } }); - it('sends bid request to TEST ENDPOINT via POST', function () { - const request = spec.buildRequests(testModeBidRequests, bidderRequest); - expect(request.url).to.equal(TEST_ENDPOINT); - expect(request.method).to.equal('POST'); + it('sends bid request to test ENDPOINT via GET', function () { + const requests = spec.buildRequests(testModeBidRequests, bidderRequest); + for (const request of requests) { + expect(request.url).to.equal(TEST_ENDPOINT); + expect(request.method).to.equal('GET'); + } }); it('should send the correct bid Id', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[0].bidId).to.equal('299ffc8cca0b87'); - }); - - it('should send the correct sizes array', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[0].sizes).to.be.an('array'); - expect(request.data.bids[0].sizes).to.equal(bidRequests[0].sizes) - expect(request.data.bids[1].sizes).to.be.an('array'); - expect(request.data.bids[1].sizes).to.equal(bidRequests[1].sizes) + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.data.bid_id).to.equal('299ffc8cca0b87'); + } }); - it('should send the correct media type', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[0].mediaType).to.equal(VIDEO) - expect(request.data.bids[1].mediaType).to.equal(BANNER) + it('should send the correct width and height', function () { + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.have.property('width', 640); + expect(request.data).to.have.property('height', 480); + } }); it('should respect syncEnabled option', function() { @@ -150,9 +129,11 @@ describe('riseAdapter', function () { } } }); - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.not.have.property('cs_method'); + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.not.have.property('cs_method'); + } }); it('should respect "iframe" filter settings', function () { @@ -167,9 +148,11 @@ describe('riseAdapter', function () { } } }); - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('cs_method', 'iframe'); + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.have.property('cs_method', 'iframe'); + } }); it('should respect "all" filter settings', function () { @@ -184,21 +167,24 @@ describe('riseAdapter', function () { } } }); - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('cs_method', 'iframe'); + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.have.property('cs_method', 'iframe'); + } }); it('should send the pixel user sync param if userSync is enabled and no "iframe" or "all" configs are present', function () { - config.resetConfig(); config.setConfig({ userSync: { - syncEnabled: true, + syncEnabled: true } }); - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('cs_method', 'pixel'); + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.have.property('cs_method', 'pixel'); + } }); it('should respect total exclusion', function() { @@ -217,38 +203,48 @@ describe('riseAdapter', function () { } } }); - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.not.have.property('cs_method'); + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.not.have.property('cs_method'); + } }); it('should have us_privacy param if usPrivacy is available in the bidRequest', function () { const bidderRequestWithUSP = Object.assign({uspConsent: '1YNN'}, bidderRequest); - const request = spec.buildRequests(bidRequests, bidderRequestWithUSP); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('us_privacy', '1YNN'); + const requests = spec.buildRequests(bidRequests, bidderRequestWithUSP); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.have.property('us_privacy', '1YNN'); + } }); it('should have an empty us_privacy param if usPrivacy is missing in the bidRequest', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.not.have.property('us_privacy'); + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.not.have.property('us_privacy'); + } }); it('should not send the gdpr param if gdprApplies is false in the bidRequest', function () { const bidderRequestWithGDPR = Object.assign({gdprConsent: {gdprApplies: false}}, bidderRequest); - const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.not.have.property('gdpr'); - expect(request.data.params).to.not.have.property('gdpr_consent'); + const requests = spec.buildRequests(bidRequests, bidderRequestWithGDPR); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.not.have.property('gdpr'); + expect(request.data).to.not.have.property('gdpr_consent'); + } }); it('should send the gdpr param if gdprApplies is true in the bidRequest', function () { const bidderRequestWithGDPR = Object.assign({gdprConsent: {gdprApplies: true, consentString: 'test-consent-string'}}, bidderRequest); - const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('gdpr', true); - expect(request.data.params).to.have.property('gdpr_consent', 'test-consent-string'); + const requests = spec.buildRequests(bidRequests, bidderRequestWithGDPR); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.have.property('gdpr', true); + expect(request.data).to.have.property('gdpr_consent', 'test-consent-string'); + } }); it('should have schain param if it is available in the bidRequest', () => { @@ -258,13 +254,15 @@ describe('riseAdapter', function () { nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], }; bidRequests[0].schain = schain; - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.params).to.be.an('object'); - expect(request.data.params).to.have.property('schain', '1.0,1!indirectseller.com,00001,1,,,'); + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (const request of requests) { + expect(request.data).to.be.an('object'); + expect(request.data).to.have.property('schain', '1.0,1!indirectseller.com,00001,,,,'); + } }); - it('should set flooPrice to getFloor.floor value if it is greater than params.floorPrice', function() { - const bid = utils.deepClone(bidRequests[0]); + it('should set floor_price to getFloor.floor value if it is greater than params.floorPrice', function() { + const bid = deepClone(bidRequests[0]); bid.getFloor = () => { return { currency: 'USD', @@ -272,13 +270,13 @@ describe('riseAdapter', function () { } } bid.params.floorPrice = 0.64; - const request = spec.buildRequests([bid], bidderRequest); - expect(request.data.bids[0]).to.be.an('object'); - expect(request.data.bids[0]).to.have.property('floorPrice', 3.32); + const request = spec.buildRequests([bid], bidderRequest)[0]; + expect(request.data).to.be.an('object'); + expect(request.data).to.have.property('floor_price', 3.32); }); - it('should set floorPrice to params.floorPrice value if it is greater than getFloor.floor', function() { - const bid = utils.deepClone(bidRequests[0]); + it('should set floor_price to params.floorPrice value if it is greater than getFloor.floor', function() { + const bid = deepClone(bidRequests[0]); bid.getFloor = () => { return { currency: 'USD', @@ -286,109 +284,61 @@ describe('riseAdapter', function () { } } bid.params.floorPrice = 1.5; - const request = spec.buildRequests([bid], bidderRequest); - expect(request.data.bids[0]).to.be.an('object'); - expect(request.data.bids[0]).to.have.property('floorPrice', 1.5); + const request = spec.buildRequests([bid], bidderRequest)[0]; + expect(request.data).to.be.an('object'); + expect(request.data).to.have.property('floor_price', 1.5); }); }); describe('interpretResponse', function () { const response = { - params: { - currency: 'USD', - netRevenue: true, - }, - bids: [{ - cpm: 12.5, - vastXml: '', - width: 640, - height: 480, - requestId: '21e12606d47ba7', - adomain: ['abc.com'], - mediaType: VIDEO - }, - { - cpm: 12.5, - ad: '""', - width: 300, - height: 250, - requestId: '21e12606d47ba7', - adomain: ['abc.com'], - mediaType: BANNER - }] - }; - - const expectedVideoResponse = { - requestId: '21e12606d47ba7', cpm: 12.5, - currency: 'USD', - width: 640, - height: 480, - ttl: TTL, - creativeId: '21e12606d47ba7', - netRevenue: true, - nurl: 'http://example.com/win/1234', - mediaType: VIDEO, - meta: { - mediaType: VIDEO, - advertiserDomains: ['abc.com'] - }, vastXml: '', - }; - - const expectedBannerResponse = { - requestId: '21e12606d47ba7', - cpm: 12.5, - currency: 'USD', width: 640, height: 480, - ttl: TTL, - creativeId: '21e12606d47ba7', + requestId: '21e12606d47ba7', netRevenue: true, - nurl: 'http://example.com/win/1234', - mediaType: BANNER, - meta: { - mediaType: BANNER, - advertiserDomains: ['abc.com'] - }, - ad: '""' + currency: 'USD', + adomain: ['abc.com'] }; it('should get correct bid response', function () { + let expectedResponse = [ + { + requestId: '21e12606d47ba7', + cpm: 12.5, + width: 640, + height: 480, + creativeId: '21e12606d47ba7', + currency: 'USD', + netRevenue: true, + ttl: TTL, + vastXml: '', + mediaType: VIDEO, + meta: { + advertiserDomains: ['abc.com'] + } + } + ]; const result = spec.interpretResponse({ body: response }); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedVideoResponse)); - expect(Object.keys(result[1])).to.deep.equal(Object.keys(expectedBannerResponse)); - }); - - it('video type should have vastXml key', function () { - const result = spec.interpretResponse({ body: response }); - expect(result[0].vastXml).to.equal(expectedVideoResponse.vastXml) - }); - - it('banner type should have ad key', function () { - const result = spec.interpretResponse({ body: response }); - expect(result[1].ad).to.equal(expectedBannerResponse.ad) + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); }) describe('getUserSyncs', function() { const imageSyncResponse = { body: { - params: { - userSyncPixels: [ - 'https://image-sync-url.test/1', - 'https://image-sync-url.test/2', - 'https://image-sync-url.test/3' - ] - } + userSyncPixels: [ + 'https://image-sync-url.test/1', + 'https://image-sync-url.test/2', + 'https://image-sync-url.test/3' + ] } }; const iframeSyncResponse = { body: { - params: { - userSyncURL: 'https://iframe-sync-url.test' - } + userSyncURL: 'https://iframe-sync-url.test' } }; @@ -452,28 +402,4 @@ describe('riseAdapter', function () { expect(syncs).to.deep.equal([]); }); }) - - describe('onBidWon', function() { - beforeEach(function() { - sinon.stub(utils, 'triggerPixel'); - }); - afterEach(function() { - utils.triggerPixel.restore(); - }); - - it('Should trigger pixel if bid nurl', function() { - const bid = { - 'bidder': spec.code, - 'adUnitCode': 'adunit-code', - 'sizes': [['640', '480']], - 'nurl': 'http://example.com/win/1234', - 'params': { - 'org': 'jdye8weeyirk00000001' - } - }; - - spec.onBidWon(bid); - expect(utils.triggerPixel.callCount).to.equal(1) - }) - }) }); diff --git a/test/spec/modules/rtbhouseBidAdapter_spec.js b/test/spec/modules/rtbhouseBidAdapter_spec.js index f4bcb48474a..d6bee26d73b 100644 --- a/test/spec/modules/rtbhouseBidAdapter_spec.js +++ b/test/spec/modules/rtbhouseBidAdapter_spec.js @@ -68,7 +68,6 @@ describe('RTBHouseAdapter', () => { 'params': { 'publisherId': 'PREBID_TEST', 'region': 'prebid-eu', - 'channel': 'Partner_Site - news', 'test': 1 }, 'adUnitCode': 'adunit-code', @@ -102,25 +101,6 @@ describe('RTBHouseAdapter', () => { expect(JSON.parse(builtTestRequest).test).to.equal(1); }); - it('should build channel param into request.site', () => { - let builtTestRequest = spec.buildRequests(bidRequests, bidderRequest).data; - expect(JSON.parse(builtTestRequest).site.channel).to.equal('Partner_Site - news'); - }) - - it('should not build channel param into request.site if no value is passed', () => { - let bidRequest = Object.assign([], bidRequests); - bidRequest[0].params.channel = undefined; - let builtTestRequest = spec.buildRequests(bidRequest, bidderRequest).data; - expect(JSON.parse(builtTestRequest).site.channel).to.be.undefined - }) - - it('should cap the request.site.channel length to 50', () => { - let bidRequest = Object.assign([], bidRequests); - bidRequest[0].params.channel = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent scelerisque ipsum eu purus lobortis iaculis.'; - let builtTestRequest = spec.buildRequests(bidRequest, bidderRequest).data; - expect(JSON.parse(builtTestRequest).site.channel.length).to.equal(50) - }) - it('should build valid OpenRTB banner object', () => { const request = JSON.parse(spec.buildRequests(bidRequests, bidderRequest).data); const imp = request.imp[0]; diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index 1f52e83dab9..ea8a25ee27d 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -13,7 +13,6 @@ import { setConfig, addBidResponseHook, } from 'modules/currency.js'; - let Ajv = require('ajv'); let schema = require('./rubiconAnalyticsSchema.json'); let ajv = new Ajv({ @@ -27,6 +26,7 @@ function validate(message) { expect(validator.errors).to.deep.equal(null); } +// using es6 "import * as events from 'src/events.js'" causes the events.getEvents stub not to work... let events = require('src/events.js'); let utils = require('src/utils.js'); @@ -39,8 +39,7 @@ const { BIDDER_DONE, BID_WON, BID_TIMEOUT, - SET_TARGETING, - BILLABLE_EVENT + SET_TARGETING } } = CONSTANTS; @@ -169,8 +168,8 @@ const floorMinRequest = { 'zoneId': '335918', 'userId': '12346', 'keywords': ['a', 'b', 'c'], - 'inventory': { 'rating': '4-star', 'prodtype': 'tech' }, - 'visitor': { 'ucat': 'new', 'lastsearch': 'iphone' }, + 'inventory': {'rating': '4-star', 'prodtype': 'tech'}, + 'visitor': {'ucat': 'new', 'lastsearch': 'iphone'}, 'position': 'atf' }, 'mediaTypes': { @@ -196,24 +195,24 @@ const MOCK = { 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', 'timestamp': 1519767010567, 'auctionStatus': 'inProgress', - 'adUnits': [{ + 'adUnits': [ { 'code': '/19968336/header-bid-tag1', 'sizes': [[640, 480]], - 'bids': [{ + 'bids': [ { 'bidder': 'rubicon', 'params': { 'accountId': 1001, 'siteId': 113932, 'zoneId': 535512 } - }], + } ], 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014' } ], 'adUnitCodes': ['/19968336/header-bid-tag1'], - 'bidderRequests': [{ + 'bidderRequests': [ { 'bidderCode': 'rubicon', 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', 'bidderRequestId': '1be65d7958826a', - 'bids': [{ + 'bids': [ { 'bidder': 'rubicon', 'params': { 'accountId': 1001, 'siteId': 113932, 'zoneId': 535512 @@ -247,7 +246,7 @@ const MOCK = { } }, BID_REQUESTED: { - 'bidderCode': 'rubicon', + 'bidder': 'rubicon', 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', 'bidderRequestId': '1be65d7958826a', 'bids': [ @@ -260,7 +259,7 @@ const MOCK = { 'userId': '12346', 'keywords': ['a', 'b', 'c'], 'inventory': 'test', - 'visitor': { 'ucat': 'new', 'lastsearch': 'iphone' }, + 'visitor': {'ucat': 'new', 'lastsearch': 'iphone'}, 'position': 'btf', 'video': { 'language': 'en', @@ -297,8 +296,8 @@ const MOCK = { 'zoneId': '335918', 'userId': '12346', 'keywords': ['a', 'b', 'c'], - 'inventory': { 'rating': '4-star', 'prodtype': 'tech' }, - 'visitor': { 'ucat': 'new', 'lastsearch': 'iphone' }, + 'inventory': {'rating': '4-star', 'prodtype': 'tech'}, + 'visitor': {'ucat': 'new', 'lastsearch': 'iphone'}, 'position': 'atf' }, 'mediaTypes': { @@ -385,10 +384,6 @@ const ANALYTICS_MESSAGE = { 'referrerHostname': 'www.test.com', 'auctions': [ { - - 'auctionEnd': 1519767013781, - 'auctionStart': 1519767010567, - 'bidderOrder': ['rubicon'], 'requestId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', 'clientTimeoutMillis': 3000, 'serverTimeoutMillis': 1000, @@ -578,21 +573,21 @@ const ANALYTICS_MESSAGE = { } }; -function performStandardAuction(gptEvents, auctionId = MOCK.AUCTION_INIT.auctionId) { - events.emit(AUCTION_INIT, { ...MOCK.AUCTION_INIT, auctionId }); - events.emit(BID_REQUESTED, { ...MOCK.BID_REQUESTED, auctionId }); - events.emit(BID_RESPONSE, { ...MOCK.BID_RESPONSE[0], auctionId }); - events.emit(BID_RESPONSE, { ...MOCK.BID_RESPONSE[1], auctionId }); - events.emit(BIDDER_DONE, { ...MOCK.BIDDER_DONE, auctionId }); - events.emit(AUCTION_END, { ...MOCK.AUCTION_END, auctionId }); +function performStandardAuction(gptEvents) { + events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); + events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); + events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); + events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]); + events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); + events.emit(AUCTION_END, MOCK.AUCTION_END); if (gptEvents && gptEvents.length) { gptEvents.forEach(gptEvent => mockGpt.emitEvent(gptEvent.eventName, gptEvent.params)); } - events.emit(SET_TARGETING, { ...MOCK.SET_TARGETING, auctionId }); - events.emit(BID_WON, { ...MOCK.BID_WON[0], auctionId }); - events.emit(BID_WON, { ...MOCK.BID_WON[1], auctionId }); + events.emit(SET_TARGETING, MOCK.SET_TARGETING); + events.emit(BID_WON, MOCK.BID_WON[0]); + events.emit(BID_WON, MOCK.BID_WON[1]); } describe('rubicon analytics adapter', function () { @@ -660,10 +655,10 @@ describe('rubicon analytics adapter', function () { expect(utils.logError.called).to.equal(true); }); - describe('config subscribe', function () { + describe('config subscribe', function() { it('should update the pvid if user asks', function () { expect(utils.generateUUID.called).to.equal(false); - config.setConfig({ rubicon: { updatePageView: true } }); + config.setConfig({rubicon: {updatePageView: true}}); expect(utils.generateUUID.called).to.equal(true); }); it('should merge in and preserve older set configs', function () { @@ -678,11 +673,6 @@ describe('rubicon analytics adapter', function () { }); expect(rubiConf).to.deep.equal({ analyticsEventDelay: 0, - dmBilling: { - enabled: false, - vendors: [], - waitForAuction: true - }, pvid: '12345678', wrapperName: '1001_general', int_type: 'dmpbjs', @@ -702,11 +692,6 @@ describe('rubicon analytics adapter', function () { }); expect(rubiConf).to.deep.equal({ analyticsEventDelay: 0, - dmBilling: { - enabled: false, - vendors: [], - waitForAuction: true - }, pvid: '12345678', wrapperName: '1001_general', int_type: 'dmpbjs', @@ -728,11 +713,6 @@ describe('rubicon analytics adapter', function () { }); expect(rubiConf).to.deep.equal({ analyticsEventDelay: 0, - dmBilling: { - enabled: false, - vendors: [], - waitForAuction: true - }, pvid: '12345678', wrapperName: '1001_general', int_type: 'dmpbjs', @@ -873,39 +853,13 @@ describe('rubicon analytics adapter', function () { expect(message).to.deep.equal(ANALYTICS_MESSAGE); }); - it('should pass along bidderOrder correctly', function () { - const appnexusBid = utils.deepClone(MOCK.BID_REQUESTED); - appnexusBid.bidderCode = 'appnexus'; - const pubmaticBid = utils.deepClone(MOCK.BID_REQUESTED); - pubmaticBid.bidderCode = 'pubmatic'; - const indexBid = utils.deepClone(MOCK.BID_REQUESTED); - indexBid.bidderCode = 'ix'; - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, pubmaticBid); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - events.emit(BID_REQUESTED, indexBid); - events.emit(BID_REQUESTED, appnexusBid); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - clock.tick(SEND_TIMEOUT + 1000); - - let message = JSON.parse(server.requests[0].requestBody); - expect(message.auctions[0].bidderOrder).to.deep.equal([ - 'pubmatic', - 'rubicon', - 'ix', - 'appnexus' - ]); - }); - it('should pass along user ids', function () { let auctionInit = utils.deepClone(MOCK.AUCTION_INIT); auctionInit.bidderRequests[0].bids[0].userId = { criteoId: 'sadfe4334', lotamePanoramaId: 'asdf3gf4eg', pubcid: 'dsfa4545-svgdfs5', - sharedId: { id1: 'asdf', id2: 'sadf4344' } + sharedId: {id1: 'asdf', id2: 'sadf4344'} }; events.emit(AUCTION_INIT, auctionInit); @@ -927,10 +881,10 @@ describe('rubicon analytics adapter', function () { expect(message.auctions[0].user).to.deep.equal({ ids: [ - { provider: 'criteoId', 'hasId': true }, - { provider: 'lotamePanoramaId', 'hasId': true }, - { provider: 'pubcid', 'hasId': true }, - { provider: 'sharedId', 'hasId': true }, + {provider: 'criteoId', 'hasId': true}, + {provider: 'lotamePanoramaId', 'hasId': true}, + {provider: 'pubcid', 'hasId': true}, + {provider: 'sharedId', 'hasId': true}, ] }); }); @@ -1033,58 +987,6 @@ describe('rubicon analytics adapter', function () { expect(message.auctions[0].adUnits[1].bids[0].bidResponse.adomains).to.be.undefined; }); - it('should NOT pass along adomians with other edge cases', function () { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - - // should filter out non string values and pass valid ones - let bidResponse1 = utils.deepClone(MOCK.BID_RESPONSE[0]); - bidResponse1.meta = { - advertiserDomains: [123, 'prebid.org', false, true, [], 'magnite.com', {}] - } - - // array of arrays (as seen when passed by kargo bid adapter) - let bidResponse2 = utils.deepClone(MOCK.BID_RESPONSE[1]); - bidResponse2.meta = { - advertiserDomains: [['prebid.org']] - } - - events.emit(BID_RESPONSE, bidResponse1); - events.emit(BID_RESPONSE, bidResponse2); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[0]); - events.emit(BID_WON, MOCK.BID_WON[1]); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].bids[0].bidResponse.adomains).to.deep.equal(['prebid.org', 'magnite.com']); - expect(message.auctions[0].adUnits[1].bids[0].bidResponse.adomains).to.be.undefined; - }); - - it('should not pass empty adServerTargeting values', function () { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - - const mockTargeting = utils.deepClone(MOCK.SET_TARGETING); - mockTargeting['/19968336/header-bid-tag-0'].hb_test = ''; - mockTargeting['/19968336/header-bid-tag1'].hb_test = 'NOT_EMPTY'; - events.emit(SET_TARGETING, mockTargeting); - - events.emit(BID_WON, MOCK.BID_WON[0]); - events.emit(BID_WON, MOCK.BID_WON[1]); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].adserverTargeting.hb_test).to.be.undefined; - expect(message.auctions[0].adUnits[1].adserverTargeting.hb_test).to.equal('NOT_EMPTY'); - }); - function performFloorAuction(provider) { let auctionInit = utils.deepClone(MOCK.AUCTION_INIT); auctionInit.bidderRequests[0].bids[0].floorData = { @@ -1282,7 +1184,7 @@ describe('rubicon analytics adapter', function () { describe('with session handling', function () { const expectedPvid = STUBBED_UUID.slice(0, 8); beforeEach(function () { - config.setConfig({ rubicon: { updatePageView: true } }); + config.setConfig({rubicon: {updatePageView: true}}); }); it('should not log any session data if local storage is not enabled', function () { @@ -1306,14 +1208,12 @@ describe('rubicon analytics adapter', function () { }); it('should should pass along custom rubicon kv and pvid when defined', function () { - config.setConfig({ - rubicon: { - fpkvs: { - source: 'fb', - link: 'email' - } + config.setConfig({rubicon: { + fpkvs: { + source: 'fb', + link: 'email' } - }); + }}); performStandardAuction(); expect(server.requests.length).to.equal(1); let request = server.requests[0]; @@ -1323,24 +1223,22 @@ describe('rubicon analytics adapter', function () { let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); expectedMessage.session.pvid = STUBBED_UUID.slice(0, 8); expectedMessage.fpkvs = [ - { key: 'source', value: 'fb' }, - { key: 'link', value: 'email' } + {key: 'source', value: 'fb'}, + {key: 'link', value: 'email'} ] expect(message).to.deep.equal(expectedMessage); }); it('should convert kvs to strings before sending', function () { - config.setConfig({ - rubicon: { - fpkvs: { - number: 24, - boolean: false, - string: 'hello', - array: ['one', 2, 'three'], - object: { one: 'two' } - } + config.setConfig({rubicon: { + fpkvs: { + number: 24, + boolean: false, + string: 'hello', + array: ['one', 2, 'three'], + object: {one: 'two'} } - }); + }}); performStandardAuction(); expect(server.requests.length).to.equal(1); let request = server.requests[0]; @@ -1350,26 +1248,24 @@ describe('rubicon analytics adapter', function () { let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); expectedMessage.session.pvid = STUBBED_UUID.slice(0, 8); expectedMessage.fpkvs = [ - { key: 'number', value: '24' }, - { key: 'boolean', value: 'false' }, - { key: 'string', value: 'hello' }, - { key: 'array', value: 'one,2,three' }, - { key: 'object', value: '[object Object]' } + {key: 'number', value: '24'}, + {key: 'boolean', value: 'false'}, + {key: 'string', value: 'hello'}, + {key: 'array', value: 'one,2,three'}, + {key: 'object', value: '[object Object]'} ] expect(message).to.deep.equal(expectedMessage); }); it('should use the query utm param rubicon kv value and pass updated kv and pvid when defined', function () { - sandbox.stub(utils, 'getWindowLocation').returns({ 'search': '?utm_source=other', 'pbjs_debug': 'true' }); + sandbox.stub(utils, 'getWindowLocation').returns({'search': '?utm_source=other', 'pbjs_debug': 'true'}); - config.setConfig({ - rubicon: { - fpkvs: { - source: 'fb', - link: 'email' - } + config.setConfig({rubicon: { + fpkvs: { + source: 'fb', + link: 'email' } - }); + }}); performStandardAuction(); expect(server.requests.length).to.equal(1); let request = server.requests[0]; @@ -1379,8 +1275,8 @@ describe('rubicon analytics adapter', function () { let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); expectedMessage.session.pvid = STUBBED_UUID.slice(0, 8); expectedMessage.fpkvs = [ - { key: 'source', value: 'other' }, - { key: 'link', value: 'email' } + {key: 'source', value: 'other'}, + {key: 'link', value: 'email'} ] message.fpkvs.sort((left, right) => left.key < right.key); @@ -1400,13 +1296,11 @@ describe('rubicon analytics adapter', function () { }; getDataFromLocalStorageStub.withArgs('rpaSession').returns(btoa(JSON.stringify(inputlocalStorage))); - config.setConfig({ - rubicon: { - fpkvs: { - link: 'email' // should merge this with what is in the localStorage! - } + config.setConfig({rubicon: { + fpkvs: { + link: 'email' // should merge this with what is in the localStorage! } - }); + }}); performStandardAuction(); expect(server.requests.length).to.equal(1); let request = server.requests[0]; @@ -1421,8 +1315,8 @@ describe('rubicon analytics adapter', function () { pvid: expectedPvid } expectedMessage.fpkvs = [ - { key: 'source', value: 'tw' }, - { key: 'link', value: 'email' } + {key: 'source', value: 'tw'}, + {key: 'link', value: 'email'} ] expect(message).to.deep.equal(expectedMessage); @@ -1444,7 +1338,7 @@ describe('rubicon analytics adapter', function () { }); it('should overwrite matching localstorge value and use its remaining values', function () { - sandbox.stub(utils, 'getWindowLocation').returns({ 'search': '?utm_source=fb&utm_click=dog' }); + sandbox.stub(utils, 'getWindowLocation').returns({'search': '?utm_source=fb&utm_click=dog'}); // set some localStorage let inputlocalStorage = { @@ -1456,13 +1350,11 @@ describe('rubicon analytics adapter', function () { }; getDataFromLocalStorageStub.withArgs('rpaSession').returns(btoa(JSON.stringify(inputlocalStorage))); - config.setConfig({ - rubicon: { - fpkvs: { - link: 'email' // should merge this with what is in the localStorage! - } + config.setConfig({rubicon: { + fpkvs: { + link: 'email' // should merge this with what is in the localStorage! } - }); + }}); performStandardAuction(); expect(server.requests.length).to.equal(1); let request = server.requests[0]; @@ -1477,9 +1369,9 @@ describe('rubicon analytics adapter', function () { pvid: expectedPvid } expectedMessage.fpkvs = [ - { key: 'source', value: 'fb' }, - { key: 'link', value: 'email' }, - { key: 'click', value: 'dog' } + {key: 'source', value: 'fb'}, + {key: 'link', value: 'email'}, + {key: 'click', value: 'dog'} ] message.fpkvs.sort((left, right) => left.key < right.key); @@ -1515,13 +1407,11 @@ describe('rubicon analytics adapter', function () { }; getDataFromLocalStorageStub.withArgs('rpaSession').returns(btoa(JSON.stringify(inputlocalStorage))); - config.setConfig({ - rubicon: { - fpkvs: { - link: 'email' // should merge this with what is in the localStorage! - } + config.setConfig({rubicon: { + fpkvs: { + link: 'email' // should merge this with what is in the localStorage! } - }); + }}); performStandardAuction(); expect(server.requests.length).to.equal(1); @@ -1535,7 +1425,7 @@ describe('rubicon analytics adapter', function () { // the saved fpkvs should have been thrown out since session expired expectedMessage.fpkvs = [ - { key: 'link', value: 'email' } + {key: 'link', value: 'email'} ] expect(message).to.deep.equal(expectedMessage); @@ -1567,13 +1457,11 @@ describe('rubicon analytics adapter', function () { }; getDataFromLocalStorageStub.withArgs('rpaSession').returns(btoa(JSON.stringify(inputlocalStorage))); - config.setConfig({ - rubicon: { - fpkvs: { - link: 'email' // should merge this with what is in the localStorage! - } + config.setConfig({rubicon: { + fpkvs: { + link: 'email' // should merge this with what is in the localStorage! } - }); + }}); performStandardAuction(); expect(server.requests.length).to.equal(1); @@ -1587,7 +1475,7 @@ describe('rubicon analytics adapter', function () { // the saved fpkvs should have been thrown out since session expired expectedMessage.fpkvs = [ - { key: 'link', value: 'email' } + {key: 'link', value: 'email'} ] expect(message).to.deep.equal(expectedMessage); @@ -1613,7 +1501,7 @@ describe('rubicon analytics adapter', function () { let gptSlotRenderEnded0, gptSlotRenderEnded1; beforeEach(function () { mockGpt.enable(); - gptSlot0 = mockGpt.makeSlot({ code: '/19968336/header-bid-tag-0' }); + gptSlot0 = mockGpt.makeSlot({code: '/19968336/header-bid-tag-0'}); gptSlotRenderEnded0 = { eventName: 'slotRenderEnded', params: { @@ -1625,7 +1513,7 @@ describe('rubicon analytics adapter', function () { } }; - gptSlot1 = mockGpt.makeSlot({ code: '/19968336/header-bid-tag1' }); + gptSlot1 = mockGpt.makeSlot({code: '/19968336/header-bid-tag1'}); gptSlotRenderEnded1 = { eventName: 'slotRenderEnded', params: { @@ -1779,50 +1667,6 @@ describe('rubicon analytics adapter', function () { expect(message).to.deep.equal(expectedMessage); }); - it('should only mark the first gam data not all matches', function () { - config.setConfig({ - rubicon: { - waitForGamSlots: true - } - }); - performStandardAuction(); - performStandardAuction([gptSlotRenderEnded0, gptSlotRenderEnded1], '32d332de-123a-32dg-2345-cefef3423324'); - - // tick the clock and both should fire - clock.tick(3000); - - expect(server.requests.length).to.equal(2); - - // first one should have GAM data - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - - // trigger should be gam since all adunits had associated gam render - expect(message.trigger).to.be.equal('gam'); - expect(message.auctions[0].adUnits[0].gam).to.deep.equal({ - advertiserId: 1111, - creativeId: 2222, - lineItemId: 3333, - adSlot: '/19968336/header-bid-tag-0' - }); - expect(message.auctions[0].adUnits[1].gam).to.deep.equal({ - advertiserId: 4444, - creativeId: 5555, - lineItemId: 6666, - adSlot: '/19968336/header-bid-tag1' - }); - - // second one should NOT have gam data - request = server.requests[1]; - message = JSON.parse(request.requestBody); - validate(message); - - // trigger should be auctionEnd - expect(message.trigger).to.be.equal('auctionEnd'); - expect(message.auctions[0].adUnits[0].gam).to.be.undefined; - expect(message.auctions[0].adUnits[1].gam).to.be.undefined; - }); - it('should send request when waitForGamSlots is present but no bidWons are sent', function () { config.setConfig({ rubicon: { @@ -2105,7 +1949,6 @@ describe('rubicon analytics adapter', function () { let timedOutBid = message.auctions[0].adUnits[0].bids[0]; expect(timedOutBid.status).to.equal('error'); expect(timedOutBid.error.code).to.equal('timeout-error'); - expect(timedOutBid.error.description).to.equal('prebid.js timeout'); expect(timedOutBid).to.not.have.property('bidResponse'); }); @@ -2142,35 +1985,6 @@ describe('rubicon analytics adapter', function () { expect(message.auctions[0].adUnits[1].pattern).to.equal('1234/mycoolsite/*&gpt_skyscraper&deviceType=mobile'); }); - it('should pass gpid if defined', function () { - let bidRequest = utils.deepClone(MOCK.BID_REQUESTED); - bidRequest.bids[0].ortb2Imp = { - ext: { - gpid: '1234/mycoolsite/lowerbox' - } - }; - bidRequest.bids[1].ortb2Imp = { - ext: { - gpid: '1234/mycoolsite/leaderboard' - } - }; - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, bidRequest); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - - clock.tick(SEND_TIMEOUT + 1000); - - expect(server.requests.length).to.equal(1); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].gpid).to.equal('1234/mycoolsite/lowerbox'); - expect(message.auctions[0].adUnits[1].gpid).to.equal('1234/mycoolsite/leaderboard'); - }); - it('should pass bidderDetail for multibid auctions', function () { let bidResponse = utils.deepClone(MOCK.BID_RESPONSE[1]); bidResponse.targetingBidder = 'rubi2'; @@ -2215,7 +2029,7 @@ describe('rubicon analytics adapter', function () { // Now add the bidResponse hook which hooks on the currenct conversion function onto the bid response let innerBid; - addBidResponseHook(function (adCodeId, bid) { + addBidResponseHook(function(adCodeId, bid) { innerBid = bid; }, 'elementId', bidCopy); @@ -2228,11 +2042,9 @@ describe('rubicon analytics adapter', function () { describe('config with integration type', () => { it('should use the integration type provided in the config instead of the default', () => { - config.setConfig({ - rubicon: { - int_type: 'testType' - } - }) + config.setConfig({rubicon: { + int_type: 'testType' + }}) rubiconAnalyticsAdapter.enableAnalytics({ options: { @@ -2252,255 +2064,13 @@ describe('rubicon analytics adapter', function () { }); }); - describe('billing events integration', () => { - beforeEach(function () { - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001 - } - }); - // default dmBilling - config.setConfig({ - rubicon: { - dmBilling: { - enabled: false, - vendors: [], - waitForAuction: true - } - } - }) - }); - afterEach(function () { - rubiconAnalyticsAdapter.disableAnalytics(); - }); - const basicBillingAuction = (billingEvents = []) => { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - - // emit billing events - billingEvents.forEach(ev => events.emit(BILLABLE_EVENT, ev)); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[0]); - events.emit(BID_WON, MOCK.BID_WON[1]); - } - it('should ignore billing events when not enabled', () => { - basicBillingAuction([{ - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }]); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message.billableEvents).to.be.undefined; - }); - it('should ignore billing events when enabled but vendor is not whitelisted', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true - } - } - }); - basicBillingAuction([{ - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }]); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message.billableEvents).to.be.undefined; - }); - it('should ignore billing events if billingId is not defined or billingId is not a string', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true, - vendors: ['vendorName'] - } - } - }); - basicBillingAuction([ - { - vendor: 'vendorName', - type: 'auction', - }, - { - vendor: 'vendorName', - type: 'auction', - billingId: true - }, - { - vendor: 'vendorName', - type: 'auction', - billingId: 1233434 - }, - { - vendor: 'vendorName', - type: 'auction', - billingId: null - } - ]); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message.billableEvents).to.be.undefined; - }); - it('should pass along billing event in same payload', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true, - vendors: ['vendorName'] - } - } - }); - basicBillingAuction([{ - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }]); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message).to.haveOwnProperty('auctions'); - expect(message.billableEvents).to.deep.equal([{ - accountId: 1001, - vendor: 'vendorName', - type: 'general', // mapping all events to endpoint as 'general' for now - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }]); - }); - it('should pass along multiple billing events but filter out duplicates', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true, - vendors: ['vendorName'] - } - } - }); - basicBillingAuction([ - { - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }, - { - vendor: 'vendorName', - type: 'auction', - billingId: '743db6e3-21f2-44d4-917f-cb3488c6076f' - }, - { - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - } - ]); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message).to.haveOwnProperty('auctions'); - expect(message.billableEvents).to.deep.equal([ - { - accountId: 1001, - vendor: 'vendorName', - type: 'general', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }, - { - accountId: 1001, - vendor: 'vendorName', - type: 'general', - billingId: '743db6e3-21f2-44d4-917f-cb3488c6076f' - } - ]); - }); - it('should pass along event right away if no pending auction', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true, - vendors: ['vendorName'] - } - } - }); - - events.emit(BILLABLE_EVENT, { - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message).to.not.haveOwnProperty('auctions'); - expect(message.billableEvents).to.deep.equal([ - { - accountId: 1001, - vendor: 'vendorName', - type: 'general', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - } - ]); - }); - it('should pass along event right away if pending auction but not waiting', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true, - vendors: ['vendorName'], - waitForAuction: false - } - } - }); - // should fire right away, and then auction later - basicBillingAuction([{ - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }]); - expect(server.requests.length).to.equal(2); - const billingRequest = server.requests[0]; - const billingMessage = JSON.parse(billingRequest.requestBody); - expect(billingMessage).to.not.haveOwnProperty('auctions'); - expect(billingMessage.billableEvents).to.deep.equal([ - { - accountId: 1001, - vendor: 'vendorName', - type: 'general', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - } - ]); - // auction event after - const auctionRequest = server.requests[1]; - const auctionMessage = JSON.parse(auctionRequest.requestBody); - // should not double pass events! - expect(auctionMessage).to.not.haveOwnProperty('billableEvents'); - }); - }); - describe('wrapper details passed in', () => { it('should correctly pass in the wrapper details if provided', () => { - config.setConfig({ - rubicon: { - wrapperName: '1001_wrapperName_exp.4', - wrapperFamily: '1001_wrapperName', - rule_name: 'na-mobile' - } - }); + config.setConfig({rubicon: { + wrapperName: '1001_wrapperName_exp.4', + wrapperFamily: '1001_wrapperName', + rule_name: 'na-mobile' + }}); rubiconAnalyticsAdapter.enableAnalytics({ options: { diff --git a/test/spec/modules/rubiconAnalyticsSchema.json b/test/spec/modules/rubiconAnalyticsSchema.json index 2d0dca42d23..a8fdeae5268 100644 --- a/test/spec/modules/rubiconAnalyticsSchema.json +++ b/test/spec/modules/rubiconAnalyticsSchema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", + "$schema": "http://json-schema.org/draft-06/schema#", "title": "Prebid Auctions", "description": "A batched data object describing the lifecycle of an auction or multiple auction across a single page view.", "type": "object", @@ -17,11 +17,6 @@ "required": [ "bidsWon" ] - }, - { - "required": [ - "billableEvents" - ] } ], "properties": { @@ -242,44 +237,9 @@ ] } }, - "billableEvents":{ - "type":"array", - "minItems":1, - "items":{ - "type":"object", - "required":[ - "accountId", - "vendor", - "type", - "billingId" - ], - "properties":{ - "vendor":{ - "type":"string", - "description":"The name of the vendor who emitted the billable event" - }, - "type":{ - "type":"string", - "description":"The type of billable event", - "enum":[ - "impression", - "pageLoad", - "auction", - "request", - "general" - ] - }, - "billingId":{ - "type":"string", - "description":"A UUID which is responsible more mapping this event to" - }, - "accountId": { - "type": "number", - "description": "The account id for the rubicon publisher" - } - } - } - } + "wrapperName": { + "type": "string" + } }, "definitions": { "gam": { @@ -303,9 +263,7 @@ }, "isSlotEmpty": { "type": "boolean", - "enum": [ - true - ] + "enum": [true] } } }, @@ -411,7 +369,6 @@ }, "error": { "type": "object", - "additionalProperties": false, "required": [ "code" ], diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index c281c195dd2..6210640f79f 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -10,7 +10,7 @@ import { import {parse as parseQuery} from 'querystring'; import {config} from 'src/config.js'; import * as utils from 'src/utils.js'; -import {find} from 'src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; import {createEidsArray} from 'modules/userId/eids.js'; const INTEGRATION = `pbjs_lite_v$prebid.version$`; // $prebid.version$ will be substituted in by gulp in built prebid @@ -597,7 +597,7 @@ describe('the rubicon adapter', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - const referenceOrdering = ['account_id', 'site_id', 'zone_id', 'size_id', 'alt_size_ids', 'p_pos', 'rf', 'p_geo.latitude', 'p_geo.longitude', 'kw', 'tg_v.ucat', 'tg_v.lastsearch', 'tg_v.likes', 'tg_i.rating', 'tg_i.prodtype', 'tk_flint', 'x_source.tid', 'l_pb_bid_id', 'x_source.pchain', 'p_screen_res', 'rp_secure', 'tk_user_key', 'tg_fl.eid', 'rp_maxbids', 'slots', 'rand']; + const referenceOrdering = ['account_id', 'site_id', 'zone_id', 'size_id', 'alt_size_ids', 'p_pos', 'rf', 'p_geo.latitude', 'p_geo.longitude', 'kw', 'tg_v.ucat', 'tg_v.lastsearch', 'tg_v.likes', 'tg_i.rating', 'tg_i.prodtype', 'tk_flint', 'x_source.tid', 'x_source.pchain', 'p_screen_res', 'rp_secure', 'tk_user_key', 'tg_fl.eid', 'rp_maxbids', 'slots', 'rand']; request.data.split('&').forEach((item, i) => { expect(item.split('=')[0]).to.equal(referenceOrdering[i]); @@ -1408,7 +1408,7 @@ describe('the rubicon adapter', function () { expect(data['tg_i.pbadslot']).to.equal('abc'); }); - it('should send \"tg_i.pbadslot\" if \"ortb2Imp.ext.data.pbadslot\" value is a valid string', function () { + it('should send \"tg_i.pbadslot\" if \"ortb2Imp.ext.data.pbadslot\" value is a valid string, but all leading slash characters should be removed', function () { bidderRequest.bids[0].ortb2Imp = { ext: { data: { @@ -1422,45 +1422,7 @@ describe('the rubicon adapter', function () { expect(data).to.be.an('Object'); expect(data).to.have.property('tg_i.pbadslot'); - expect(data['tg_i.pbadslot']).to.equal('/a/b/c'); - }); - - it('should send gpid as p_gpid if valid', function () { - bidderRequest.bids[0].ortb2Imp = { - ext: { - gpid: '/1233/sports&div1' - } - } - - const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - const data = parseQuery(request.data); - - expect(data).to.be.an('Object'); - expect(data).to.have.property('p_gpid'); - expect(data['p_gpid']).to.equal('/1233/sports&div1'); - }); - - it('should send gpid and pbadslot since it is prefered over dfp code', function () { - bidderRequest.bids[0].ortb2Imp = { - ext: { - gpid: '/1233/sports&div1', - data: { - pbadslot: 'pb_slot', - adserver: { - adslot: '/1234/sports', - name: 'gam' - } - } - } - } - - const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - const data = parseQuery(request.data); - - expect(data).to.be.an('Object'); - expect(data['p_gpid']).to.equal('/1233/sports&div1'); - expect(data).to.not.have.property('tg_i.dfp_ad_unit_code'); - expect(data['tg_i.pbadslot']).to.equal('pb_slot'); + expect(data['tg_i.pbadslot']).to.equal('a/b/c'); }); }); @@ -1508,13 +1470,12 @@ describe('the rubicon adapter', function () { expect(data).to.not.have.property('tg_i.dfp_ad_unit_code'); }); - it('should send NOT \"tg_i.dfp_ad_unit_code\" if \"ortb2Imp.ext.data.adServer.adslot\" value is a valid string but not gam', function () { + it('should send \"tg_i.dfp_ad_unit_code\" if \"ortb2Imp.ext.data.adServer.adslot\" value is a valid string', function () { bidderRequest.bids[0].ortb2Imp = { ext: { data: { adserver: { - adslot: '/a/b/c', - name: 'not gam' + adslot: 'abc' } } } @@ -1524,16 +1485,16 @@ describe('the rubicon adapter', function () { const data = parseQuery(request.data); expect(data).to.be.an('Object'); - expect(data).to.not.have.property('tg_i.dfp_ad_unit_code'); + expect(data).to.have.property('tg_i.dfp_ad_unit_code'); + expect(data['tg_i.dfp_ad_unit_code']).to.equal('abc'); }); - it('should send \"tg_i.dfp_ad_unit_code\" if \"ortb2Imp.ext.data.adServer.adslot\" value is a valid string and name is gam', function () { + it('should send \"tg_i.dfp_ad_unit_code\" if \"ortb2Imp.ext.data.adServer.adslot\" value is a valid string, but all leading slash characters should be removed', function () { bidderRequest.bids[0].ortb2Imp = { ext: { data: { adserver: { - name: 'gam', - adslot: '/a/b/c' + adslot: 'a/b/c' } } } @@ -1544,7 +1505,7 @@ describe('the rubicon adapter', function () { expect(data).to.be.an('Object'); expect(data).to.have.property('tg_i.dfp_ad_unit_code'); - expect(data['tg_i.dfp_ad_unit_code']).to.equal('/a/b/c'); + expect(data['tg_i.dfp_ad_unit_code']).to.equal('a/b/c'); }); }); }); @@ -3262,7 +3223,7 @@ describe('the rubicon adapter', function () { label: undefined, placement: { align: 'left', - attachTo: adUnit, + attachTo: '#outstream_video1_placement', position: 'append', }, vastUrl: 'https://test.com/vast.xml', @@ -3382,23 +3343,6 @@ describe('the rubicon adapter', function () { type: 'iframe', url: `${emilyUrl}?gdpr_consent=foo&us_privacy=1NYN` }); }); - - it('should pass gdprApplies', function () { - expect(spec.getUserSyncs({iframeEnabled: true}, {}, { - gdprApplies: true - }, '1NYN')).to.deep.equal({ - type: 'iframe', url: `${emilyUrl}?gdpr=1&us_privacy=1NYN` - }); - }); - - it('should pass all correctly', function () { - expect(spec.getUserSyncs({iframeEnabled: true}, {}, { - gdprApplies: true, - consentString: 'foo' - }, '1NYN')).to.deep.equal({ - type: 'iframe', url: `${emilyUrl}?gdpr=1&gdpr_consent=foo&us_privacy=1NYN` - }); - }); }); describe('get price granularity', function () { diff --git a/test/spec/modules/scaleableAnalyticsAdapter_spec.js b/test/spec/modules/scaleableAnalyticsAdapter_spec.js index c65740252d2..70b94a2b807 100644 --- a/test/spec/modules/scaleableAnalyticsAdapter_spec.js +++ b/test/spec/modules/scaleableAnalyticsAdapter_spec.js @@ -1,6 +1,6 @@ import scaleableAnalytics from 'modules/scaleableAnalyticsAdapter.js'; import { expect } from 'chai'; -import * as events from 'src/events.js'; +import events from 'src/events.js'; import CONSTANTS from 'src/constants.json'; import { server } from 'test/mocks/xhr.js'; diff --git a/test/spec/modules/seedingAllianceAdapter_spec.js b/test/spec/modules/seedingAllianceAdapter_spec.js deleted file mode 100755 index 81af9546ff0..00000000000 --- a/test/spec/modules/seedingAllianceAdapter_spec.js +++ /dev/null @@ -1,186 +0,0 @@ -// jshint esversion: 6, es3: false, node: true -import {assert, expect} from 'chai'; -import {spec} from 'modules/seedingAllianceBidAdapter.js'; -import { NATIVE } from 'src/mediaTypes.js'; -import { config } from 'src/config.js'; - -describe('SeedingAlliance adapter', function () { - let serverResponse, bidRequest, bidResponses; - let bid = { - 'bidder': 'seedingAlliance', - 'params': { - 'adUnitId': '1hq8' - } - }; - - describe('isBidRequestValid', function () { - it('should return true when required params found', function () { - assert(spec.isBidRequestValid(bid)); - }); - - it('should return false when AdUnitId is not set', function () { - delete bid.params.adUnitId; - assert.isFalse(spec.isBidRequestValid(bid)); - }); - }); - - describe('buildRequests', function () { - it('should send request with correct structure', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {} - }]; - - let request = spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }); - - assert.equal(request.method, 'POST'); - assert.ok(request.data); - }); - - it('should have default request structure', function () { - let keys = 'site,device,cur,imp,user,regs'.split(','); - let validBidRequests = [{ - bidId: 'bidId', - params: {} - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data); - let data = Object.keys(request); - - assert.deepEqual(keys, data); - }); - - it('Verify the auction ID', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {}, - auctionId: 'auctionId' - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' }, auctionId: validBidRequests[0].auctionId }).data); - - assert.equal(request.id, validBidRequests[0].auctionId); - }); - - it('Verify the device', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {} - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data); - - assert.equal(request.device.ua, navigator.userAgent); - }); - - it('Verify native asset ids', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {}, - nativeParams: { - body: { - required: true, - len: 350 - }, - image: { - required: true - }, - title: { - required: true - }, - sponsoredBy: { - required: true - }, - cta: { - required: true - }, - icon: { - required: true - } - } - }]; - - let assets = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp[0].native.request.assets; - - assert.equal(assets[0].id, 1); - assert.equal(assets[1].id, 3); - assert.equal(assets[2].id, 0); - assert.equal(assets[3].id, 2); - assert.equal(assets[4].id, 4); - assert.equal(assets[5].id, 5); - }); - }); - - describe('interpretResponse', function () { - const goodResponse = { - body: { - cur: 'EUR', - id: '4b516b80-886e-4ec0-82ae-9209e6d625fb', - seatbid: [ - { - seat: 'seedingAlliance', - bid: [{ - adm: { - native: { - assets: [ - {id: 0, title: {text: 'this is a title'}} - ], - imptrackers: ['https://domain.for/imp/tracker?price=${AUCTION_PRICE}'], - link: { - clicktrackers: ['https://domain.for/imp/tracker?price=${AUCTION_PRICE}'], - url: 'https://domain.for/ad/' - } - } - }, - impid: 1, - price: 0.55 - }] - } - ] - } - }; - const badResponse = { body: { - cur: 'EUR', - id: '4b516b80-886e-4ec0-82ae-9209e6d625fb', - seatbid: [] - }}; - - const bidRequest = { - data: {}, - bids: [{ bidId: 'bidId1' }] - }; - - it('should return null if body is missing or empty', function () { - const result = spec.interpretResponse(badResponse, bidRequest); - assert.equal(result.length, 0); - - delete badResponse.body - - const result1 = spec.interpretResponse(badResponse, bidRequest); - assert.equal(result.length, 0); - }); - - it('should return the correct params', function () { - const result = spec.interpretResponse(goodResponse, bidRequest); - const bid = goodResponse.body.seatbid[0].bid[0]; - - assert.deepEqual(result[0].currency, goodResponse.body.cur); - assert.deepEqual(result[0].requestId, bidRequest.bids[0].bidId); - assert.deepEqual(result[0].cpm, bid.price); - assert.deepEqual(result[0].creativeId, bid.crid); - assert.deepEqual(result[0].mediaType, 'native'); - assert.deepEqual(result[0].bidderCode, 'seedingAlliance'); - }); - - it('should return the correct tracking links', function () { - const result = spec.interpretResponse(goodResponse, bidRequest); - const bid = goodResponse.body.seatbid[0].bid[0]; - const regExpPrice = new RegExp('price=' + bid.price); - - result[0].native.clickTrackers.forEach(function (clickTracker) { - assert.ok(clickTracker.search(regExpPrice) > -1); - }); - - result[0].native.impressionTrackers.forEach(function (impTracker) { - assert.ok(impTracker.search(regExpPrice) > -1); - }); - }); - }); -}); diff --git a/test/spec/modules/seedtagBidAdapter_spec.js b/test/spec/modules/seedtagBidAdapter_spec.js index 1e0dca68d00..3aa378379dd 100644 --- a/test/spec/modules/seedtagBidAdapter_spec.js +++ b/test/spec/modules/seedtagBidAdapter_spec.js @@ -1,17 +1,14 @@ -import { expect } from 'chai'; -import { spec, getTimeoutUrl } from 'modules/seedtagBidAdapter.js'; -import * as utils from 'src/utils.js'; +import { expect } from 'chai' +import { spec, getTimeoutUrl } from 'modules/seedtagBidAdapter.js' +import * as utils from 'src/utils.js' -const PUBLISHER_ID = '0000-0000-01'; -const ADUNIT_ID = '000000'; +const PUBLISHER_ID = '0000-0000-01' +const ADUNIT_ID = '000000' function getSlotConfigs(mediaTypes, params) { return { params: params, - sizes: [ - [300, 250], - [300, 600], - ], + sizes: [[300, 250], [300, 600]], bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', @@ -20,336 +17,325 @@ function getSlotConfigs(mediaTypes, params) { mediaTypes: mediaTypes, src: 'client', transactionId: 'd704d006-0d6e-4a09-ad6c-179e7e758096', - adUnitCode: 'adunit-code', - }; + adUnitCode: 'adunit-code' + } } function createVideoSlotConfig(mediaType) { return getSlotConfigs(mediaType, { publisherId: PUBLISHER_ID, adUnitId: ADUNIT_ID, - placement: 'video', - }); + placement: 'video' + }) } -describe('Seedtag Adapter', function () { - describe('isBidRequestValid method', function () { - describe('returns true', function () { +describe('Seedtag Adapter', function() { + describe('isBidRequestValid method', function() { + describe('returns true', function() { describe('when banner slot config has all mandatory params', () => { - describe('and placement has the correct value', function () { - const createBannerSlotConfig = (placement) => { + describe('and placement has the correct value', function() { + const createBannerSlotConfig = placement => { return getSlotConfigs( { banner: {} }, { publisherId: PUBLISHER_ID, adUnitId: ADUNIT_ID, - placement, + placement } - ); - }; - const placements = [ - 'banner', - 'video', - 'inImage', - 'inScreen', - 'inArticle', - ]; - placements.forEach((placement) => { - it('should be ' + placement, function () { + ) + } + const placements = ['banner', 'video', 'inImage', 'inScreen', 'inArticle'] + placements.forEach(placement => { + it('should be ' + placement, function() { const isBidRequestValid = spec.isBidRequestValid( createBannerSlotConfig(placement) - ); - expect(isBidRequestValid).to.equal(true); - }); - }); - }); - }); - describe('when video slot has all mandatory params', function () { + ) + expect(isBidRequestValid).to.equal(true) + }) + }) + }) + }) + describe('when video slot has all mandatory params', function() { it('should return true, when video context is instream', function () { const slotConfig = getSlotConfigs( { video: { context: 'instream', - playerSize: [[600, 200]], - }, + playerSize: [[600, 200]] + } }, { publisherId: PUBLISHER_ID, adUnitId: ADUNIT_ID, - placement: 'video', + placement: 'video' } - ); - const isBidRequestValid = spec.isBidRequestValid(slotConfig); - expect(isBidRequestValid).to.equal(true); - }); + ) + const isBidRequestValid = spec.isBidRequestValid(slotConfig) + expect(isBidRequestValid).to.equal(true) + }) it('should return true, when video context is outstream', function () { const slotConfig = getSlotConfigs( { video: { context: 'outstream', - playerSize: [[600, 200]], - }, + playerSize: [[600, 200]] + } }, { publisherId: PUBLISHER_ID, adUnitId: ADUNIT_ID, - placement: 'video', + placement: 'video' } - ); - const isBidRequestValid = spec.isBidRequestValid(slotConfig); - expect(isBidRequestValid).to.equal(true); - }); - }); - }); - describe('returns false', function () { - describe('when params are not correct', function () { + ) + const isBidRequestValid = spec.isBidRequestValid(slotConfig) + expect(isBidRequestValid).to.equal(true) + }) + }) + }) + describe('returns false', function() { + describe('when params are not correct', function() { function createSlotConfig(params) { - return getSlotConfigs({ banner: {} }, params); + return getSlotConfigs({ banner: {} }, params) } - it('does not have the PublisherToken.', function () { + it('does not have the PublisherToken.', function() { const isBidRequestValid = spec.isBidRequestValid( createSlotConfig({ adUnitId: ADUNIT_ID, - placement: 'banner', + placement: 'banner' }) - ); - expect(isBidRequestValid).to.equal(false); - }); - it('does not have the AdUnitId.', function () { + ) + expect(isBidRequestValid).to.equal(false) + }) + it('does not have the AdUnitId.', function() { const isBidRequestValid = spec.isBidRequestValid( createSlotConfig({ publisherId: PUBLISHER_ID, - placement: 'banner', + placement: 'banner' }) - ); - expect(isBidRequestValid).to.equal(false); - }); - it('does not have the placement.', function () { + ) + expect(isBidRequestValid).to.equal(false) + }) + it('does not have the placement.', function() { const isBidRequestValid = spec.isBidRequestValid( createSlotConfig({ publisherId: PUBLISHER_ID, - adUnitId: ADUNIT_ID, + adUnitId: ADUNIT_ID }) - ); - expect(isBidRequestValid).to.equal(false); - }); - it('does not have a the correct placement.', function () { + ) + expect(isBidRequestValid).to.equal(false) + }) + it('does not have a the correct placement.', function() { const isBidRequestValid = spec.isBidRequestValid( createSlotConfig({ publisherId: PUBLISHER_ID, adUnitId: ADUNIT_ID, - placement: 'another_thing', + placement: 'another_thing' }) - ); - expect(isBidRequestValid).to.equal(false); - }); - }); - describe('when video mediaType object is not correct', function () { + ) + expect(isBidRequestValid).to.equal(false) + }) + }) + describe('when video mediaType object is not correct', function() { function createVideoSlotconfig(mediaType) { return getSlotConfigs(mediaType, { publisherId: PUBLISHER_ID, adUnitId: ADUNIT_ID, - placement: 'video', - }); + placement: 'video' + }) } - it('is a void object', function () { + it('is a void object', function() { const isBidRequestValid = spec.isBidRequestValid( createVideoSlotConfig({ video: {} }) - ); - expect(isBidRequestValid).to.equal(false); - }); - it('does not have playerSize.', function () { + ) + expect(isBidRequestValid).to.equal(false) + }) + it('does not have playerSize.', function() { const isBidRequestValid = spec.isBidRequestValid( createVideoSlotConfig({ video: { context: 'instream' } }) - ); - expect(isBidRequestValid).to.equal(false); - }); + ) + expect(isBidRequestValid).to.equal(false) + }) it('is outstream ', function () { const isBidRequestValid = spec.isBidRequestValid( createVideoSlotConfig({ video: { context: 'outstream', - playerSize: [[600, 200]], - }, + playerSize: [[600, 200]] + } }) - ); - expect(isBidRequestValid).to.equal(true); - }); - describe('order does not matter', function () { - it('when video is not the first slot', function () { + ) + expect(isBidRequestValid).to.equal(true) + }) + describe('order does not matter', function() { + it('when video is not the first slot', function() { const isBidRequestValid = spec.isBidRequestValid( createVideoSlotConfig({ banner: {}, video: {} }) - ); - expect(isBidRequestValid).to.equal(false); - }); - it('when video is the first slot', function () { + ) + expect(isBidRequestValid).to.equal(false) + }) + it('when video is the first slot', function() { const isBidRequestValid = spec.isBidRequestValid( createVideoSlotConfig({ video: {}, banner: {} }) - ); - expect(isBidRequestValid).to.equal(false); - }); - }); - }); - }); - }); + ) + expect(isBidRequestValid).to.equal(false) + }) + }) + }) + }) + }) - describe('buildRequests method', function () { + describe('buildRequests method', function() { const bidderRequest = { refererInfo: { referer: 'referer' }, - timeout: 1000, - }; + timeout: 1000 + } const mandatoryParams = { publisherId: PUBLISHER_ID, adUnitId: ADUNIT_ID, - placement: 'banner', - }; + placement: 'banner' + } const inStreamParams = Object.assign({}, mandatoryParams, { video: { - mimes: 'mp4', - }, - }); + mimes: 'mp4' + } + }) const validBidRequests = [ getSlotConfigs({ banner: {} }, mandatoryParams), getSlotConfigs( { video: { context: 'instream', playerSize: [[300, 200]] } }, inStreamParams - ), - ]; - it('Url params should be correct ', function () { - const request = spec.buildRequests(validBidRequests, bidderRequest); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal('https://s.seedtag.com/c/hb/bid'); - }); + ) + ] + it('Url params should be correct ', function() { + const request = spec.buildRequests(validBidRequests, bidderRequest) + expect(request.method).to.equal('POST') + expect(request.url).to.equal('https://s.seedtag.com/c/hb/bid') + }) - it('Common data request should be correct', function () { - const request = spec.buildRequests(validBidRequests, bidderRequest); - const data = JSON.parse(request.data); - expect(data.url).to.equal('referer'); - expect(data.publisherToken).to.equal('0000-0000-01'); - expect(typeof data.version).to.equal('string'); - expect( - ['fixed', 'mobile', 'unknown'].indexOf(data.connectionType) - ).to.be.above(-1); - expect(data.bidRequests[0].adUnitCode).to.equal('adunit-code'); - }); + it('Common data request should be correct', function() { + const request = spec.buildRequests(validBidRequests, bidderRequest) + const data = JSON.parse(request.data) + expect(data.url).to.equal('referer') + expect(data.publisherToken).to.equal('0000-0000-01') + expect(typeof data.version).to.equal('string') + expect(['fixed', 'mobile', 'unknown'].indexOf(data.connectionType)).to.be.above(-1) + expect(data.bidRequests[0].adUnitCode).to.equal('adunit-code') + }) - describe('adPosition param', function () { - it('should sended when publisher set adPosition param', function () { + describe('adPosition param', function() { + it('should sended when publisher set adPosition param', function() { const params = Object.assign({}, mandatoryParams, { - adPosition: 1, - }); - const validBidRequests = [getSlotConfigs({ banner: {} }, params)]; - const request = spec.buildRequests(validBidRequests, bidderRequest); - const data = JSON.parse(request.data); - expect(data.bidRequests[0].adPosition).to.equal(1); - }); - it('should not sended when publisher has not set adPosition param', function () { + adPosition: 1 + }) + const validBidRequests = [getSlotConfigs({ banner: {} }, params)] + const request = spec.buildRequests(validBidRequests, bidderRequest) + const data = JSON.parse(request.data) + expect(data.bidRequests[0].adPosition).to.equal(1) + }) + it('should not sended when publisher has not set adPosition param', function() { const validBidRequests = [ - getSlotConfigs({ banner: {} }, mandatoryParams), - ]; - const request = spec.buildRequests(validBidRequests, bidderRequest); - const data = JSON.parse(request.data); - expect(data.bidRequests[0].adPosition).to.equal(undefined); - }); - }); + getSlotConfigs({ banner: {} }, mandatoryParams) + ] + const request = spec.buildRequests(validBidRequests, bidderRequest) + const data = JSON.parse(request.data) + expect(data.bidRequests[0].adPosition).to.equal(undefined) + }) + }) - describe('GDPR params', function () { - describe('when there arent consent management platform', function () { - it('cmp should be false', function () { - const request = spec.buildRequests(validBidRequests, bidderRequest); - const data = JSON.parse(request.data); - expect(data.cmp).to.equal(false); - }); - }); - describe('when there are consent management platform', function () { - it('cmps should be true and ga should not sended, when gdprApplies is undefined', function () { + describe('GDPR params', function() { + describe('when there arent consent management platform', function() { + it('cmp should be false', function() { + const request = spec.buildRequests(validBidRequests, bidderRequest) + const data = JSON.parse(request.data) + expect(data.cmp).to.equal(false) + }) + }) + describe('when there are consent management platform', function() { + it('cmps should be true and ga should not sended, when gdprApplies is undefined', function() { bidderRequest['gdprConsent'] = { gdprApplies: undefined, - consentString: 'consentString', - }; - const request = spec.buildRequests(validBidRequests, bidderRequest); - const data = JSON.parse(request.data); - expect(data.cmp).to.equal(true); - expect(Object.keys(data).indexOf('data')).to.equal(-1); - expect(data.cd).to.equal('consentString'); - }); - it('cmps should be true and all gdpr parameters should be sended, when there are gdprApplies', function () { + consentString: 'consentString' + } + const request = spec.buildRequests(validBidRequests, bidderRequest) + const data = JSON.parse(request.data) + expect(data.cmp).to.equal(true) + expect(Object.keys(data).indexOf('data')).to.equal(-1) + expect(data.cd).to.equal('consentString') + }) + it('cmps should be true and all gdpr parameters should be sended, when there are gdprApplies', function() { bidderRequest['gdprConsent'] = { gdprApplies: true, - consentString: 'consentString', - }; - const request = spec.buildRequests(validBidRequests, bidderRequest); - const data = JSON.parse(request.data); - expect(data.cmp).to.equal(true); - expect(data.ga).to.equal(true); - expect(data.cd).to.equal('consentString'); - }); - it('should expose gvlid', function () { - expect(spec.gvlid).to.equal(157); - }); - }); - }); + consentString: 'consentString' + } + const request = spec.buildRequests(validBidRequests, bidderRequest) + const data = JSON.parse(request.data) + expect(data.cmp).to.equal(true) + expect(data.ga).to.equal(true) + expect(data.cd).to.equal('consentString') + }) + }) + }) - describe('BidRequests params', function () { - const request = spec.buildRequests(validBidRequests, bidderRequest); - const data = JSON.parse(request.data); - const bidRequests = data.bidRequests; - it('should request a Banner', function () { - const bannerBid = bidRequests[0]; - expect(bannerBid.id).to.equal('30b31c1838de1e'); + describe('BidRequests params', function() { + const request = spec.buildRequests(validBidRequests, bidderRequest) + const data = JSON.parse(request.data) + const bidRequests = data.bidRequests + it('should request a Banner', function() { + const bannerBid = bidRequests[0] + expect(bannerBid.id).to.equal('30b31c1838de1e') expect(bannerBid.transactionId).to.equal( 'd704d006-0d6e-4a09-ad6c-179e7e758096' - ); - expect(bannerBid.supplyTypes[0]).to.equal('display'); - expect(bannerBid.adUnitId).to.equal('000000'); - expect(bannerBid.sizes[0][0]).to.equal(300); - expect(bannerBid.sizes[0][1]).to.equal(250); - expect(bannerBid.sizes[1][0]).to.equal(300); - expect(bannerBid.sizes[1][1]).to.equal(600); - expect(bannerBid.requestCount).to.equal(1); - }); - it('should request an InStream Video', function () { - const videoBid = bidRequests[1]; - expect(videoBid.id).to.equal('30b31c1838de1e'); + ) + expect(bannerBid.supplyTypes[0]).to.equal('display') + expect(bannerBid.adUnitId).to.equal('000000') + expect(bannerBid.sizes[0][0]).to.equal(300) + expect(bannerBid.sizes[0][1]).to.equal(250) + expect(bannerBid.sizes[1][0]).to.equal(300) + expect(bannerBid.sizes[1][1]).to.equal(600) + expect(bannerBid.requestCount).to.equal(1) + }) + it('should request an InStream Video', function() { + const videoBid = bidRequests[1] + expect(videoBid.id).to.equal('30b31c1838de1e') expect(videoBid.transactionId).to.equal( 'd704d006-0d6e-4a09-ad6c-179e7e758096' - ); - expect(videoBid.supplyTypes[0]).to.equal('video'); - expect(videoBid.adUnitId).to.equal('000000'); - expect(videoBid.videoParams.mimes).to.equal('mp4'); - expect(videoBid.videoParams.w).to.equal(300); - expect(videoBid.videoParams.h).to.equal(200); - expect(videoBid.sizes[0][0]).to.equal(300); - expect(videoBid.sizes[0][1]).to.equal(250); - expect(videoBid.sizes[1][0]).to.equal(300); - expect(videoBid.sizes[1][1]).to.equal(600); - expect(videoBid.requestCount).to.equal(1); - }); - }); - }); + ) + expect(videoBid.supplyTypes[0]).to.equal('video') + expect(videoBid.adUnitId).to.equal('000000') + expect(videoBid.videoParams.mimes).to.equal('mp4') + expect(videoBid.videoParams.w).to.equal(300) + expect(videoBid.videoParams.h).to.equal(200) + expect(videoBid.sizes[0][0]).to.equal(300) + expect(videoBid.sizes[0][1]).to.equal(250) + expect(videoBid.sizes[1][0]).to.equal(300) + expect(videoBid.sizes[1][1]).to.equal(600) + expect(videoBid.requestCount).to.equal(1) + }) + }) + }) - describe('interpret response method', function () { - it('should return a void array, when the server response are not correct.', function () { - const request = { data: JSON.stringify({}) }; + describe('interpret response method', function() { + it('should return a void array, when the server response are not correct.', function() { + const request = { data: JSON.stringify({}) } const serverResponse = { - body: {}, - }; - const bids = spec.interpretResponse(serverResponse, request); - expect(typeof bids).to.equal('object'); - expect(bids.length).to.equal(0); - }); - it('should return a void array, when the server response have no bids.', function () { - const request = { data: JSON.stringify({}) }; - const serverResponse = { body: { bids: [] } }; - const bids = spec.interpretResponse(serverResponse, request); - expect(typeof bids).to.equal('object'); - expect(bids.length).to.equal(0); - }); - describe('when the server response return a bid', function () { - describe('the bid is a banner', function () { - it('should return a banner bid', function () { - const request = { data: JSON.stringify({}) }; + body: {} + } + const bids = spec.interpretResponse(serverResponse, request) + expect(typeof bids).to.equal('object') + expect(bids.length).to.equal(0) + }) + it('should return a void array, when the server response have no bids.', function() { + const request = { data: JSON.stringify({}) } + const serverResponse = { body: { bids: [] } } + const bids = spec.interpretResponse(serverResponse, request) + expect(typeof bids).to.equal('object') + expect(bids.length).to.equal(0) + }) + describe('when the server response return a bid', function() { + describe('the bid is a banner', function() { + it('should return a banner bid', function() { + const request = { data: JSON.stringify({}) } const serverResponse = { body: { bids: [ @@ -363,30 +349,28 @@ describe('Seedtag Adapter', function () { mediaType: 'display', ttl: 360, nurl: 'testurl.com/nurl', - adomain: ['advertiserdomain.com'], - }, + adomain: ['advertiserdomain.com'] + } ], - cookieSync: { url: '' }, - }, - }; - const bids = spec.interpretResponse(serverResponse, request); - expect(bids.length).to.equal(1); - expect(bids[0].requestId).to.equal('2159a54dc2566f'); - expect(bids[0].cpm).to.equal(0.5); - expect(bids[0].width).to.equal(728); - expect(bids[0].height).to.equal(90); - expect(bids[0].currency).to.equal('USD'); - expect(bids[0].netRevenue).to.equal(true); - expect(bids[0].ad).to.equal('content'); - expect(bids[0].nurl).to.equal('testurl.com/nurl'); - expect(bids[0].meta.advertiserDomains).to.deep.equal([ - 'advertiserdomain.com', - ]); - }); - }); - describe('the bid is a video', function () { - it('should return a instream bid', function () { - const request = { data: JSON.stringify({}) }; + cookieSync: { url: '' } + } + } + const bids = spec.interpretResponse(serverResponse, request) + expect(bids.length).to.equal(1) + expect(bids[0].requestId).to.equal('2159a54dc2566f') + expect(bids[0].cpm).to.equal(0.5) + expect(bids[0].width).to.equal(728) + expect(bids[0].height).to.equal(90) + expect(bids[0].currency).to.equal('USD') + expect(bids[0].netRevenue).to.equal(true) + expect(bids[0].ad).to.equal('content') + expect(bids[0].nurl).to.equal('testurl.com/nurl') + expect(bids[0].meta.advertiserDomains).to.deep.equal(['advertiserdomain.com']) + }) + }) + describe('the bid is a video', function() { + it('should return a instream bid', function() { + const request = { data: JSON.stringify({}) } const serverResponse = { body: { bids: [ @@ -399,124 +383,114 @@ describe('Seedtag Adapter', function () { height: 90, mediaType: 'video', ttl: 360, - nurl: undefined, - }, + nurl: undefined + } ], - cookieSync: { url: '' }, - }, - }; - const bids = spec.interpretResponse(serverResponse, request); - expect(bids.length).to.equal(1); - expect(bids[0].requestId).to.equal('2159a54dc2566f'); - expect(bids[0].cpm).to.equal(0.5); - expect(bids[0].width).to.equal(728); - expect(bids[0].height).to.equal(90); - expect(bids[0].currency).to.equal('USD'); - expect(bids[0].netRevenue).to.equal(true); - expect(bids[0].vastXml).to.equal('content'); - expect(bids[0].meta.advertiserDomains).to.deep.equal([]); - }); - }); - }); - }); + cookieSync: { url: '' } + } + } + const bids = spec.interpretResponse(serverResponse, request) + expect(bids.length).to.equal(1) + expect(bids[0].requestId).to.equal('2159a54dc2566f') + expect(bids[0].cpm).to.equal(0.5) + expect(bids[0].width).to.equal(728) + expect(bids[0].height).to.equal(90) + expect(bids[0].currency).to.equal('USD') + expect(bids[0].netRevenue).to.equal(true) + expect(bids[0].vastXml).to.equal('content') + expect(bids[0].meta.advertiserDomains).to.deep.equal([]) + }) + }) + }) + }) - describe('user syncs method', function () { - it('should return empty array, when iframe sync option are disabled.', function () { - const syncOption = { iframeEnabled: false }; - const serverResponses = [{ body: { cookieSync: 'someUrl' } }]; - const cookieSyncArray = spec.getUserSyncs(syncOption, serverResponses); - expect(cookieSyncArray.length).to.equal(0); - }); - it('should return empty array, when the server response are wrong.', function () { - const syncOption = { iframeEnabled: true }; - const serverResponses = [{ body: {} }]; - const cookieSyncArray = spec.getUserSyncs(syncOption, serverResponses); - expect(cookieSyncArray.length).to.equal(0); - }); - it('should return empty array, when the server response are void.', function () { - const syncOption = { iframeEnabled: true }; - const serverResponses = [{ body: { cookieSync: '' } }]; - const cookieSyncArray = spec.getUserSyncs(syncOption, serverResponses); - expect(cookieSyncArray.length).to.equal(0); - }); - it('should return a array with the cookie sync, when the server response with a cookie sync.', function () { - const syncOption = { iframeEnabled: true }; - const serverResponses = [{ body: { cookieSync: 'someUrl' } }]; - const cookieSyncArray = spec.getUserSyncs(syncOption, serverResponses); - expect(cookieSyncArray.length).to.equal(1); - expect(cookieSyncArray[0].type).to.equal('iframe'); - expect(cookieSyncArray[0].url).to.equal('someUrl'); - }); - }); + describe('user syncs method', function() { + it('should return empty array, when iframe sync option are disabled.', function() { + const syncOption = { iframeEnabled: false } + const serverResponses = [{ body: { cookieSync: 'someUrl' } }] + const cookieSyncArray = spec.getUserSyncs(syncOption, serverResponses) + expect(cookieSyncArray.length).to.equal(0) + }) + it('should return empty array, when the server response are wrong.', function() { + const syncOption = { iframeEnabled: true } + const serverResponses = [{ body: {} }] + const cookieSyncArray = spec.getUserSyncs(syncOption, serverResponses) + expect(cookieSyncArray.length).to.equal(0) + }) + it('should return empty array, when the server response are void.', function() { + const syncOption = { iframeEnabled: true } + const serverResponses = [{ body: { cookieSync: '' } }] + const cookieSyncArray = spec.getUserSyncs(syncOption, serverResponses) + expect(cookieSyncArray.length).to.equal(0) + }) + it('should return a array with the cookie sync, when the server response with a cookie sync.', function() { + const syncOption = { iframeEnabled: true } + const serverResponses = [{ body: { cookieSync: 'someUrl' } }] + const cookieSyncArray = spec.getUserSyncs(syncOption, serverResponses) + expect(cookieSyncArray.length).to.equal(1) + expect(cookieSyncArray[0].type).to.equal('iframe') + expect(cookieSyncArray[0].url).to.equal('someUrl') + }) + }) describe('onTimeout', function () { - beforeEach(function () { - sinon.stub(utils, 'triggerPixel'); - }); + beforeEach(function() { + sinon.stub(utils, 'triggerPixel') + }) - afterEach(function () { - utils.triggerPixel.restore(); - }); + afterEach(function() { + utils.triggerPixel.restore() + }) it('should return the correct endpoint', function () { - const params = { publisherId: '0000', adUnitId: '11111' }; - const timeout = 3000; - const timeoutData = [{ params: [params], timeout }]; + const params = { publisherId: '0000', adUnitId: '11111' } + const timeoutData = [{ params: [ params ] }]; const timeoutUrl = getTimeoutUrl(timeoutData); expect(timeoutUrl).to.equal( 'https://s.seedtag.com/se/hb/timeout?publisherToken=' + - params.publisherId + - '&adUnitId=' + - params.adUnitId + - '&timeout=' + - timeout - ); - }); + params.publisherId + + '&adUnitId=' + + params.adUnitId + ) + }) - it('should set the timeout pixel', function () { - const params = { publisherId: '0000', adUnitId: '11111' }; - const timeout = 3000; - const timeoutData = [{ params: [params], timeout }]; - spec.onTimeout(timeoutData); - expect( - utils.triggerPixel.calledWith( - 'https://s.seedtag.com/se/hb/timeout?publisherToken=' + - params.publisherId + - '&adUnitId=' + - params.adUnitId + - '&timeout=' + - timeout - ) - ).to.equal(true); - }); - }); + it('should set the timeout pixel', function() { + const params = { publisherId: '0000', adUnitId: '11111' } + const timeoutData = [{ params: [ params ] }]; + spec.onTimeout(timeoutData) + expect(utils.triggerPixel.calledWith('https://s.seedtag.com/se/hb/timeout?publisherToken=' + + params.publisherId + + '&adUnitId=' + + params.adUnitId)).to.equal(true); + }) + }) describe('onBidWon', function () { - beforeEach(function () { - sinon.stub(utils, 'triggerPixel'); - }); + beforeEach(function() { + sinon.stub(utils, 'triggerPixel') + }) - afterEach(function () { - utils.triggerPixel.restore(); - }); + afterEach(function() { + utils.triggerPixel.restore() + }) - describe('without nurl', function () { - const bid = {}; + describe('without nurl', function() { + const bid = {} - it('does not create pixel ', function () { - spec.onBidWon(bid); + it('does not create pixel ', function() { + spec.onBidWon(bid) expect(utils.triggerPixel.called).to.equal(false); - }); - }); + }) + }) describe('with nurl', function () { - const nurl = 'http://seedtag_domain/won'; - const bid = { nurl }; + const nurl = 'http://seedtag_domain/won' + const bid = { nurl } - it('creates nurl pixel if bid nurl', function () { - spec.onBidWon({ nurl }); + it('creates nurl pixel if bid nurl', function() { + spec.onBidWon({ nurl }) expect(utils.triggerPixel.calledWith(nurl)).to.equal(true); - }); - }); - }); -}); + }) + }) + }) +}) diff --git a/test/spec/modules/sharedIdSystem_spec.js b/test/spec/modules/sharedIdSystem_spec.js index 8ef34a1599e..534d0b3f381 100644 --- a/test/spec/modules/sharedIdSystem_spec.js +++ b/test/spec/modules/sharedIdSystem_spec.js @@ -50,10 +50,10 @@ describe('SharedId System', function () { expect(callbackSpy.calledOnce).to.be.true; expect(callbackSpy.lastCall.lastArg).to.equal(UUID); }); - it('should abort if coppa is set', function () { + it('should log message if coppa is set', function () { coppaDataHandlerDataStub.returns('true'); - const result = sharedIdSystemSubmodule.getId({}); - expect(result).to.be.undefined; + sharedIdSystemSubmodule.getId({}); + expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('PubCommonId: IDs not provided for coppa requests, exiting PubCommonId'); }); }); describe('SharedId System extendId()', function () { @@ -85,56 +85,10 @@ describe('SharedId System', function () { let pubcommId = sharedIdSystemSubmodule.extendId(config, undefined, 'TestId').id; expect(pubcommId).to.equal('TestId'); }); - it('should abort if coppa is set', function () { + it('should log message if coppa is set', function () { coppaDataHandlerDataStub.returns('true'); - const result = sharedIdSystemSubmodule.extendId({params: {extend: true}}, undefined, 'TestId'); - expect(result).to.be.undefined; - }); - }); - - describe('SharedID System domainOverride', () => { - let sandbox, domain, cookies, rejectCookiesFor; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - sandbox.stub(document, 'domain').get(() => domain); - cookies = {}; - sandbox.stub(storage, 'getCookie').callsFake((key) => cookies[key]); - rejectCookiesFor = null; - sandbox.stub(storage, 'setCookie').callsFake((key, value, expires, sameSite, domain) => { - if (domain !== rejectCookiesFor) { - if (expires != null) { - expires = new Date(expires); - } - if (expires == null || expires > Date.now()) { - cookies[key] = value; - } else { - delete cookies[key]; - } - } - }); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('should return TLD if cookies can be set there', () => { - domain = 'sub.domain.com'; - rejectCookiesFor = 'com'; - expect(sharedIdSystemSubmodule.domainOverride()).to.equal('domain.com'); - }); - - it('should return undefined when cookies cannot be set', () => { - domain = 'sub.domain.com'; - rejectCookiesFor = 'sub.domain.com'; - expect(sharedIdSystemSubmodule.domainOverride()).to.be.undefined; - }); - - it('should return half-way domain if parent domain rejects cookies', () => { - domain = 'inner.outer.domain.com'; - rejectCookiesFor = 'domain.com'; - expect(sharedIdSystemSubmodule.domainOverride()).to.equal('outer.domain.com'); + sharedIdSystemSubmodule.extendId({}, undefined, 'TestId'); + expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('PubCommonId: IDs not provided for coppa requests, exiting PubCommonId'); }); }); }); diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index 39238cc877f..3e406e1af44 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -1,649 +1,632 @@ import { expect } from 'chai'; -import * as sinon from 'sinon'; import { sharethroughAdapterSpec, sharethroughInternal } from 'modules/sharethroughBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; +import * as utils from '../../../src/utils.js'; import { config } from 'src/config'; -import * as utils from 'src/utils'; const spec = newBidder(sharethroughAdapterSpec).getSpec(); +const bidRequests = [ + { + bidder: 'sharethrough', + bidId: 'bidId1', + sizes: [[600, 300]], + placementCode: 'foo', + params: { + pkey: 'aaaa1111' + }, + ortb2Imp: { + ext: { + data: { + pbadslot: 'adslot-id-1' + } + } + }, + userId: { + tdid: 'fake-tdid', + pubcid: 'fake-pubcid', + idl_env: 'fake-identity-link', + id5id: { + uid: 'fake-id5id', + ext: { + linkType: 2 + } + }, + lipb: { + lipbid: 'fake-lipbid' + } + }, + crumbs: { + pubcid: 'fake-pubcid-in-crumbs-obj' + } + }, + { + bidder: 'sharethrough', + bidId: 'bidId2', + sizes: [[700, 400]], + placementCode: 'bar', + params: { + pkey: 'bbbb2222', + iframe: true + } + }, + { + bidder: 'sharethrough', + bidId: 'bidId3', + sizes: [[700, 400]], + placementCode: 'coconut', + params: { + pkey: 'cccc3333', + iframe: true, + iframeSize: [500, 500] + } + }, + { + bidder: 'sharethrough', + bidId: 'bidId4', + sizes: [[700, 400]], + placementCode: 'bar', + params: { + pkey: 'dddd4444', + badv: ['domain1.com', 'domain2.com'] + } + }, + { + bidder: 'sharethrough', + bidId: 'bidId5', + sizes: [[700, 400]], + placementCode: 'bar', + params: { + pkey: 'eeee5555', + bcat: ['IAB1-1', 'IAB1-2'] + } + }, +]; + +const prebidRequests = [ + { + method: 'POST', + url: 'https://btlr.sharethrough.com/WYu2BXv1/v1', + data: { + bidId: 'bidId', + placement_key: 'pKey' + }, + strData: { + skipIframeBusting: false, + sizes: [] + } + }, + { + method: 'POST', + url: 'https://btlr.sharethrough.com/WYu2BXv1/v1', + data: { + bidId: 'bidId', + placement_key: 'pKey' + }, + strData: { + skipIframeBusting: true, + sizes: [[300, 250], [300, 300], [250, 250], [600, 50]] + } + }, + { + method: 'POST', + url: 'https://btlr.sharethrough.com/WYu2BXv1/v1', + data: { + bidId: 'bidId', + placement_key: 'pKey' + }, + strData: { + skipIframeBusting: true, + iframeSize: [500, 500], + sizes: [[300, 250], [300, 300], [250, 250], [600, 50]] + } + }, + { + method: 'POST', + url: 'https://btlr.sharethrough.com/WYu2BXv1/v1', + data: { + bidId: 'bidId', + placement_key: 'pKey' + }, + strData: { + skipIframeBusting: false, + sizes: [[0, 0]] + } + }, + { + method: 'POST', + url: 'https://btlr.sharethrough.com/WYu2BXv1/v1', + data: { + bidId: 'bidId', + placement_key: 'pKey' + }, + strData: { + skipIframeBusting: false, + sizes: [[300, 250], [300, 300], [250, 250], [600, 50]] + } + } +]; + +const bidderResponse = { + body: { + 'adserverRequestId': '40b6afd5-6134-4fbb-850a-bb8972a46994', + 'bidId': 'bidId1', + 'version': 1, + 'creatives': [{ + 'auctionWinId': 'b2882d5e-bf8b-44da-a91c-0c11287b8051', + 'cpm': 12.34, + 'creative': { + 'deal_id': 'aDealId', + 'creative_key': 'aCreativeId', + 'title': '✓ à la mode' + } + }], + 'stxUserId': '' + }, + header: { get: (header) => header } +}; + +const setUserAgent = (uaString) => { + window.navigator['__defineGetter__']('userAgent', function() { + return uaString; + }); +}; + +describe('sharethrough internal spec', function() { + let windowStub, windowTopStub; + let stubbedReturn = [{ + appendChild: () => undefined + }] + beforeEach(function() { + windowStub = sinon.stub(window.document, 'getElementsByTagName'); + windowTopStub = sinon.stub(window.top.document, 'getElementsByTagName'); + windowStub.withArgs('body').returns(stubbedReturn); + windowTopStub.withArgs('body').returns(stubbedReturn); + }); + + afterEach(function() { + windowStub.restore(); + windowTopStub.restore(); + window.STR = undefined; + window.top.STR = undefined; + }); + + describe('we cannot access top level document', function() { + beforeEach(function() { + window.lockedInFrame = true; + }); + + afterEach(function() { + window.lockedInFrame = false; + }); -describe('sharethrough adapter spec', function () { - let protocolStub; - let inIframeStub; + it('appends sfp.js to the safeframe', function() { + sharethroughInternal.handleIframe(); + expect(windowStub.calledOnce).to.be.true; + }); - beforeEach(() => { - protocolStub = sinon.stub(sharethroughInternal, 'getProtocol').returns('https'); - inIframeStub = sinon.stub(utils, 'inIframe').returns(false); + it('does not append anything if sfp.js is already loaded in the safeframe', function() { + window.STR = { Tag: true }; + sharethroughInternal.handleIframe(); + expect(windowStub.notCalled).to.be.true; + expect(windowTopStub.notCalled).to.be.true; + }); }); - afterEach(() => { - protocolStub.restore(); - inIframeStub.restore(); + describe('we are able to bust out of the iframe', function() { + it('appends sfp.js to window.top', function() { + sharethroughInternal.handleIframe(); + expect(windowStub.calledOnce).to.be.true; + expect(windowTopStub.calledOnce).to.be.true; + }); + + it('only appends sfp-set-targeting.js if sfp.js is already loaded on the page', function() { + window.top.STR = { Tag: true }; + sharethroughInternal.handleIframe(); + expect(windowStub.calledOnce).to.be.true; + expect(windowTopStub.notCalled).to.be.true; + }); }); +}); - describe('code', function () { - it('should return a bidder code of sharethrough', function () { +describe('sharethrough adapter spec', function() { + describe('.code', function() { + it('should return a bidder code of sharethrough', function() { expect(spec.code).to.eql('sharethrough'); }); }); - describe('isBidRequestValid', function () { - it('should return false if req has no pkey', function () { + describe('.isBidRequestValid', function() { + it('should return false if req has no pkey', function() { const invalidBidRequest = { bidder: 'sharethrough', params: { - notPKey: 'abc123', - }, + notPKey: 'abc123' + } }; expect(spec.isBidRequestValid(invalidBidRequest)).to.eql(false); }); - it('should return false if req has wrong bidder code', function () { + it('should return false if req has wrong bidder code', function() { const invalidBidRequest = { bidder: 'notSharethrough', params: { - pkey: 'abc123', - }, + notPKey: 'abc123' + } }; expect(spec.isBidRequestValid(invalidBidRequest)).to.eql(false); }); - it('should return true if req is correct', function () { - const validBidRequest = { - bidder: 'sharethrough', - params: { - pkey: 'abc123', - }, - }; - expect(spec.isBidRequestValid(validBidRequest)).to.eq(true); + it('should return true if req is correct', function() { + expect(spec.isBidRequestValid(bidRequests[0])).to.eq(true); + expect(spec.isBidRequestValid(bidRequests[1])).to.eq(true); }); }); - describe('open rtb', () => { - let bidRequests, bidderRequest; + describe('.buildRequests', function() { + it('should return an array of requests', function() { + const builtBidRequests = spec.buildRequests(bidRequests); - beforeEach(() => { - config.setConfig({ - bidderTimeout: 242, - coppa: true, - }); - - bidRequests = [ - { - bidder: 'sharethrough', - bidId: 'bidId1', - sizes: [[300, 250], [300, 600]], - params: { - pkey: 'aaaa1111', - bcat: ['cat1', 'cat2'], - badv: ['adv1', 'adv2'], - }, - mediaTypes: { - banner: { - pos: 1, - }, - }, - ortb2Imp: { - ext: { - data: { - pbadslot: 'universal-id', - }, - }, - }, - userId: { - tdid: 'fake-tdid', - pubcid: 'fake-pubcid', - idl_env: 'fake-identity-link', - id5id: { - uid: 'fake-id5id', - ext: { - linkType: 2, - }, - }, - lipb: { - lipbid: 'fake-lipbid', - }, - criteoId: 'fake-criteo', - britepoolid: 'fake-britepool', - intentIqId: 'fake-intentiq', - lotamePanoramaId: 'fake-lotame', - parrableId: { - eid: 'fake-parrable', - }, - netId: 'fake-netid', - sharedid: { - id: 'fake-sharedid', - }, - flocId: { - id: 'fake-flocid', - version: '42', - }, - }, - crumbs: { - pubcid: 'fake-pubcid-in-crumbs-obj', - }, - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'directseller.com', - sid: '00001', - rid: 'BidRequest1', - hp: 1, - }, - ], - }, - getFloor: () => ({ currency: 'USD', floor: 42 }), - }, - { - bidder: 'sharethrough', - bidId: 'bidId2', - sizes: [[600, 300]], - params: { - pkey: 'bbbb2222', - }, - mediaTypes: { - video: { - pos: 3, - skip: 1, - linearity: 0, - minduration: 10, - maxduration: 30, - playbackmethod: [1], - api: [3], - mimes: ['video/3gpp'], - protocols: [2, 3], - playerSize: [640, 480], - startdelay: 42, - skipmin: 10, - skipafter: 20, - delivery: 1, - companiontype: 'companion type', - companionad: 'companion ad', - context: 'instream', - }, - }, - getFloor: () => ({ currency: 'USD', floor: 42 }), - }, - ]; - - bidderRequest = { - refererInfo: { - referer: 'https://referer.com', - }, - }; + expect(builtBidRequests[0].url).to.eq('https://btlr.sharethrough.com/WYu2BXv1/v1'); + expect(builtBidRequests[1].url).to.eq('https://btlr.sharethrough.com/WYu2BXv1/v1'); + expect(builtBidRequests[0].method).to.eq('POST'); }); - describe('buildRequests', function () { - describe('top level object', () => { - it('should build openRTB request', () => { - const builtRequests = spec.buildRequests(bidRequests, bidderRequest); - - const expectedImpValues = [ - { - id: 'bidId1', - tagid: 'aaaa1111', - secure: 1, - bidfloor: 42, - }, - { - id: 'bidId2', - tagid: 'bbbb2222', - secure: 1, - bidfloor: 42, - }, - ]; - - builtRequests.map((builtRequest, rIndex) => { - expect(builtRequest.method).to.equal('POST'); - expect(builtRequest.url).not.to.be.undefined; - expect(builtRequest.options).to.be.undefined; - - const openRtbReq = builtRequest.data; - expect(openRtbReq.id).not.to.be.undefined; - expect(openRtbReq.cur).to.deep.equal(['USD']); - expect(openRtbReq.tmax).to.equal(242); - - expect(Object.keys(openRtbReq.site)).to.have.length(3); - expect(openRtbReq.site.domain).not.to.be.undefined; - expect(openRtbReq.site.page).not.to.be.undefined; - expect(openRtbReq.site.ref).to.equal('https://referer.com'); - - const expectedEids = { - 'liveramp.com': { id: 'fake-identity-link' }, - 'id5-sync.com': { id: 'fake-id5id' }, - 'pubcid.org': { id: 'fake-pubcid' }, - 'adserver.org': { id: 'fake-tdid' }, - 'criteo.com': { id: 'fake-criteo' }, - 'britepool.com': { id: 'fake-britepool' }, - 'liveintent.com': { id: 'fake-lipbid' }, - 'intentiq.com': { id: 'fake-intentiq' }, - 'crwdcntrl.net': { id: 'fake-lotame' }, - 'parrable.com': { id: 'fake-parrable' }, - 'netid.de': { id: 'fake-netid' }, - 'chrome.com': { id: 'fake-flocid' }, - }; - expect(openRtbReq.user.ext.eids).to.be.an('array').that.have.length(Object.keys(expectedEids).length); - for (const eid of openRtbReq.user.ext.eids) { - expect(Object.keys(expectedEids)).to.include(eid.source); - expect(eid.uids[0].id).to.equal(expectedEids[eid.source].id); - expect(eid.uids[0].atype).to.be.ok; - } - - expect(openRtbReq.device.ua).to.equal(navigator.userAgent); - expect(openRtbReq.regs.coppa).to.equal(1); - - expect(openRtbReq.source.ext.version).not.to.be.undefined; - expect(openRtbReq.source.ext.str).not.to.be.undefined; - expect(openRtbReq.source.ext.schain).to.deep.equal(bidRequests[0].schain); - - expect(openRtbReq.bcat).to.deep.equal(bidRequests[0].params.bcat); - expect(openRtbReq.badv).to.deep.equal(bidRequests[0].params.badv); - - expect(openRtbReq.imp).to.have.length(1); - - expect(openRtbReq.imp[0].id).to.equal(expectedImpValues[rIndex].id); - expect(openRtbReq.imp[0].tagid).to.equal(expectedImpValues[rIndex].tagid); - expect(openRtbReq.imp[0].secure).to.equal(expectedImpValues[rIndex].secure); - expect(openRtbReq.imp[0].bidfloor).to.equal(expectedImpValues[rIndex].bidfloor); - }); - }); + it('should set the instant_play_capable parameter correctly based on browser userAgent string', function() { + setUserAgent('Android Chrome/60'); + let builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.true; - it('should have empty eid array if no id is provided', () => { - const openRtbReq = spec.buildRequests([bidRequests[1]], bidderRequest)[0].data; + setUserAgent('iPhone Version/11'); + builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.true; - expect(openRtbReq.user.ext.eids).to.deep.equal([]); - }); - }); + setUserAgent('iPhone CriOS/60'); + builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.true; - describe('no referer provided', () => { - beforeEach(() => { - bidderRequest = {}; - }); + setUserAgent('Android Chrome/50'); + builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.false; - it('should set referer to undefined', () => { - const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data; - expect(openRtbReq.site.ref).to.be.undefined; - }); - }); - - describe('regulation', () => { - describe('gdpr', () => { - it('should populate request accordingly when gdpr applies', () => { - bidderRequest.gdprConsent = { - gdprApplies: true, - consentString: 'consent', - }; + setUserAgent('Android Chrome'); + builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.false; - const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data; + setUserAgent(undefined); + builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.false; + }); - expect(openRtbReq.regs.ext.gdpr).to.equal(1); - expect(openRtbReq.user.ext.consent).to.equal('consent'); - }); + it('should set the secure parameter to false when the protocol is http', function() { + const stub = sinon.stub(sharethroughInternal, 'getProtocol').returns('http:'); + const bidRequest = spec.buildRequests(bidRequests, null)[0]; + expect(bidRequest.data.secure).to.be.false; + stub.restore(); + }); - it('should populate request accordingly when gdpr explicitly does not apply', () => { - bidderRequest.gdprConsent = { - gdprApplies: false, - }; + it('should set the secure parameter to true when the protocol is https', function() { + const stub = sinon.stub(sharethroughInternal, 'getProtocol').returns('https:'); + const bidRequest = spec.buildRequests(bidRequests, null)[0]; + expect(bidRequest.data.secure).to.be.true; + stub.restore(); + }); - const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data; + it('should set the secure parameter to true when the protocol is neither http or https', function() { + const stub = sinon.stub(sharethroughInternal, 'getProtocol').returns('about:'); + const bidRequest = spec.buildRequests(bidRequests, null)[0]; + expect(bidRequest.data.secure).to.be.true; + stub.restore(); + }); - expect(openRtbReq.regs.ext.gdpr).to.equal(0); - expect(openRtbReq.user.ext.consent).to.be.undefined; - }); - }); + it('should add ccpa parameter if uspConsent is present', function() { + const uspConsent = '1YNN'; + const bidderRequest = { uspConsent: uspConsent }; + const bidRequest = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(bidRequest.data.us_privacy).to.eq(uspConsent); + }); - describe('US privacy', () => { - it('should populate request accordingly when us privacy applies', () => { - bidderRequest.uspConsent = 'consent'; + it('should add consent parameters if gdprConsent is present', function() { + const gdprConsent = { consentString: 'consent_string123', gdprApplies: true }; + const bidderRequest = { gdprConsent: gdprConsent }; + const bidRequest = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(bidRequest.data.consent_required).to.eq(true); + expect(bidRequest.data.consent_string).to.eq('consent_string123'); + }); - const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data; + it('should handle gdprConsent is present but values are undefined case', function() { + const gdprConsent = { consent_string: undefined, gdprApplies: undefined }; + const bidderRequest = { gdprConsent: gdprConsent }; + const bidRequest = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(bidRequest.data).to.not.include.any.keys('consent_string'); + }); - expect(openRtbReq.regs.ext.us_privacy).to.equal('consent'); - }); - }); + it('should add the ttduid parameter if a bid request contains a value for Unified ID from The Trade Desk', function() { + const bidRequest = spec.buildRequests(bidRequests)[0]; + expect(bidRequest.data.ttduid).to.eq('fake-tdid'); + }); - describe('coppa', () => { - it('should populate request accordingly when coppa does not apply', () => { - config.setConfig({ coppa: false }); + it('should add the pubcid parameter if a bid request contains a value for the Publisher Common ID Module in the' + + ' userId object of the bidrequest', function() { + const bidRequest = spec.buildRequests(bidRequests)[0]; + expect(bidRequest.data.pubcid).to.eq('fake-pubcid'); + }); - const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data; + it('should add the pubcid parameter if a bid request contains a value for the Publisher Common ID Module in the' + + ' crumbs object of the bidrequest', function() { + const bidData = utils.deepClone(bidRequests); + delete bidData[0].userId.pubcid; - expect(openRtbReq.regs.coppa).to.equal(0); - }); - }); - }); + const bidRequest = spec.buildRequests(bidData)[0]; + expect(bidRequest.data.pubcid).to.eq('fake-pubcid-in-crumbs-obj'); + }); - describe('universal id', () => { - it('should include gpid when universal id is provided', () => { - const requests = spec.buildRequests(bidRequests, bidderRequest); + it('should add the pubcid parameter if a bid request contains a value for the Publisher Common ID Module in the' + + ' crumbs object of the bidrequest', function() { + const bidRequest = spec.buildRequests(bidRequests)[0]; + delete bidRequest.userId; + expect(bidRequest.data.pubcid).to.eq('fake-pubcid'); + }); - expect(requests[0].data.imp[0].ext.gpid).to.equal('universal-id'); - expect(requests[1].data.imp[0].ext).to.be.undefined; - }); - }); + it('should add the idluid parameter if a bid request contains a value for Identity Link from Live Ramp', function() { + const bidRequest = spec.buildRequests(bidRequests)[0]; + expect(bidRequest.data.idluid).to.eq('fake-identity-link'); + }); - describe('secure flag', () => { - it('should be positive when protocol is https', () => { - protocolStub.returns('https'); - const requests = spec.buildRequests(bidRequests, bidderRequest); + it('should add the id5uid parameter if a bid request contains a value for ID5', function() { + const bidRequest = spec.buildRequests(bidRequests)[0]; + expect(bidRequest.data.id5uid.id).to.eq('fake-id5id'); + expect(bidRequest.data.id5uid.linkType).to.eq(2); + }); - expect(requests[0].data.imp[0].secure).to.equal(1); - expect(requests[1].data.imp[0].secure).to.equal(1); - }); + it('should add the liuid parameter if a bid request contains a value for LiveIntent ID', function() { + const bidRequest = spec.buildRequests(bidRequests)[0]; + expect(bidRequest.data.liuid).to.eq('fake-lipbid'); + }); - it('should be negative when protocol is http', () => { - protocolStub.returns('http'); - const requests = spec.buildRequests(bidRequests, bidderRequest); + it('should add Sharethrough specific parameters', function() { + const builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0]).to.deep.include({ + strData: { + skipIframeBusting: undefined, + iframeSize: undefined, + sizes: [[600, 300]] + } + }); + }); - expect(requests[0].data.imp[0].secure).to.equal(0); - expect(requests[1].data.imp[0].secure).to.equal(0); - }); + it('should add a supply chain parameter if schain is present', function() { + // shallow copy of the first bidRequest obj, so we don't mutate + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest['schain'] = { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'directseller.com', + sid: '00001', + rid: 'BidRequest1', + hp: 1 + } + ] + }; - it('should be positive when protocol is neither http nor https', () => { - protocolStub.returns('about'); - const requests = spec.buildRequests(bidRequests, bidderRequest); + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data.schain).to.eq(JSON.stringify(bidRequest.schain)); + }); - expect(requests[0].data.imp[0].secure).to.equal(1); - expect(requests[1].data.imp[0].secure).to.equal(1); - }); + describe('gpid', () => { + it('should include the gpid param if pbadslot is found in ortb2Imp in the bid request', () => { + const bidRequest = spec.buildRequests(bidRequests)[0]; + expect(bidRequest.data.gpid).to.eq('adslot-id-1') }); - describe('banner imp', () => { - it('should generate open rtb banner imp', () => { - const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[0]; + it('should not include the gpid param if pbadslot is not found in ortb2Imp in the bid request', () => { + const bidRequest = spec.buildRequests(bidRequests)[1]; + expect(bidRequest.data).to.not.include.any.keys('gpid'); + }); + }); - const bannerImp = builtRequest.data.imp[0].banner; - expect(bannerImp.pos).to.equal(1); - expect(bannerImp.topframe).to.equal(1); - expect(bannerImp.format).to.deep.equal([{ w: 300, h: 250 }, { w: 300, h: 600 }]); - }); + it('should add badv if provided', () => { + const builtBidRequest = spec.buildRequests([bidRequests[3]])[0]; - it('should default to pos 0 if not provided', () => { - delete bidRequests[0].mediaTypes; - const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(builtBidRequest.data.badv).to.have.members(['domain1.com', 'domain2.com']) + }); - const bannerImp = builtRequest.data.imp[0].banner; - expect(bannerImp.pos).to.equal(0); - }); - }); + it('should add bcat if provided', () => { + const builtBidRequest = spec.buildRequests([bidRequests[4]])[0]; - describe('video imp', () => { - it('should generate open rtb video imp', () => { - const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[1]; - - const videoImp = builtRequest.data.imp[0].video; - expect(videoImp.pos).to.equal(3); - expect(videoImp.topframe).to.equal(1); - expect(videoImp.skip).to.equal(1); - expect(videoImp.linearity).to.equal(0); - expect(videoImp.minduration).to.equal(10); - expect(videoImp.maxduration).to.equal(30); - expect(videoImp.playbackmethod).to.deep.equal([1]); - expect(videoImp.api).to.deep.equal([3]); - expect(videoImp.mimes).to.deep.equal(['video/3gpp']); - expect(videoImp.protocols).to.deep.equal([2, 3]); - expect(videoImp.w).to.equal(640); - expect(videoImp.h).to.equal(480); - expect(videoImp.startdelay).to.equal(42); - expect(videoImp.skipmin).to.equal(10); - expect(videoImp.skipafter).to.equal(20); - expect(videoImp.placement).to.equal(1); - expect(videoImp.delivery).to.equal(1); - expect(videoImp.companiontype).to.equal('companion type'); - expect(videoImp.companionad).to.equal('companion ad'); - }); + expect(builtBidRequest.data.bcat).to.have.members(['IAB1-1', 'IAB1-2']) + }); - it('should set defaults if no value provided', () => { - delete bidRequests[1].mediaTypes.video.pos; - delete bidRequests[1].mediaTypes.video.skip; - delete bidRequests[1].mediaTypes.video.linearity; - delete bidRequests[1].mediaTypes.video.minduration; - delete bidRequests[1].mediaTypes.video.maxduration; - delete bidRequests[1].mediaTypes.video.playbackmethod; - delete bidRequests[1].mediaTypes.video.api; - delete bidRequests[1].mediaTypes.video.mimes; - delete bidRequests[1].mediaTypes.video.protocols; - delete bidRequests[1].mediaTypes.video.playerSize; - delete bidRequests[1].mediaTypes.video.startdelay; - delete bidRequests[1].mediaTypes.video.skipmin; - delete bidRequests[1].mediaTypes.video.skipafter; - delete bidRequests[1].mediaTypes.video.placement; - delete bidRequests[1].mediaTypes.video.delivery; - delete bidRequests[1].mediaTypes.video.companiontype; - delete bidRequests[1].mediaTypes.video.companionad; - - const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[1]; - - const videoImp = builtRequest.data.imp[0].video; - expect(videoImp.pos).to.equal(0); - expect(videoImp.skip).to.equal(0); - expect(videoImp.linearity).to.equal(1); - expect(videoImp.minduration).to.equal(5); - expect(videoImp.maxduration).to.equal(60); - expect(videoImp.playbackmethod).to.deep.equal([2]); - expect(videoImp.api).to.deep.equal([2]); - expect(videoImp.mimes).to.deep.equal(['video/mp4']); - expect(videoImp.protocols).to.deep.equal([2, 3, 5, 6, 7, 8]); - expect(videoImp.w).to.equal(640); - expect(videoImp.h).to.equal(360); - expect(videoImp.startdelay).to.equal(0); - expect(videoImp.skipmin).to.equal(0); - expect(videoImp.skipafter).to.equal(0); - expect(videoImp.placement).to.equal(1); - expect(videoImp.delivery).to.be.undefined; - expect(videoImp.companiontype).to.be.undefined; - expect(videoImp.companionad).to.be.undefined; - }); + it('should not add a supply chain parameter if schain is missing', function() { + const bidRequest = spec.buildRequests(bidRequests)[0]; + expect(bidRequest.data).to.not.include.any.keys('schain'); + }); - describe('outstream', () => { - it('should use placement value if provided', () => { - bidRequests[1].mediaTypes.video.context = 'outstream'; - bidRequests[1].mediaTypes.video.placement = 3; + it('should include the bidfloor parameter if it is present in the bid request', function() { + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest['getFloor'] = () => ({ currency: 'USD', floor: 0.5 }); + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data.bidfloor).to.eq(0.5); + }); - const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[1]; - const videoImp = builtRequest.data.imp[0].video; + it('should not include the bidfloor parameter if it is missing in the bid request', function() { + const bidRequest = Object.assign({}, bidRequests[0]); + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data).to.not.include.any.keys('bidfloor'); + }); - expect(videoImp.placement).to.equal(3); - }); + describe('coppa', function() { + it('should add coppa to request if enabled', function() { + config.setConfig({coppa: true}); + const bidRequest = Object.assign({}, bidRequests[0]); + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data.coppa).to.eq(true); + }); - it('should default placement to 4 if not provided', () => { - bidRequests[1].mediaTypes.video.context = 'outstream'; + it('should not add coppa to request if disabled', function() { + config.setConfig({coppa: false}); + const bidRequest = Object.assign({}, bidRequests[0]); + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data.coppa).to.be.undefined; + }); - const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[1]; - const videoImp = builtRequest.data.imp[0].video; + it('should not add coppa to request if unknown value', function() { + config.setConfig({coppa: 'something'}); + const bidRequest = Object.assign({}, bidRequests[0]); + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data.coppa).to.be.undefined; + }); + }); + }); - expect(videoImp.placement).to.equal(4); - }); + describe('.interpretResponse', function() { + it('returns a correctly parsed out response', function() { + expect(spec.interpretResponse(bidderResponse, prebidRequests[0])[0]).to.deep.include( + { + width: 1, + height: 1, + cpm: 12.34, + creativeId: 'aCreativeId', + dealId: 'aDealId', + currency: 'USD', + netRevenue: true, + ttl: 360, + meta: { advertiserDomains: [] } }); - }); + }); - describe('first party data', () => { - const firstPartyData = { - site: { - name: 'example', - keywords: 'power tools, drills', - search: 'drill', - content: { - userrating: '4', - }, - ext: { - data: { - pageType: 'article', - category: 'repair', - }, - }, - }, - user: { - yob: 1985, - gender: 'm', - ext: { - data: { - registered: true, - interests: ['cars'], - }, - }, - }, - }; - - let configStub; - - beforeEach(() => { - configStub = sinon.stub(config, 'getConfig'); - configStub.withArgs('ortb2').returns(firstPartyData); + it('returns a correctly parsed out response with largest size when strData.skipIframeBusting is true', function() { + expect(spec.interpretResponse(bidderResponse, prebidRequests[1])[0]).to.include( + { + width: 300, + height: 300, + cpm: 12.34, + creativeId: 'aCreativeId', + dealId: 'aDealId', + currency: 'USD', + netRevenue: true, + ttl: 360 }); + }); - afterEach(() => { - configStub.restore(); + it('returns a correctly parsed out response with explicitly defined size when strData.skipIframeBusting is true and strData.iframeSize is provided', function() { + expect(spec.interpretResponse(bidderResponse, prebidRequests[2])[0]).to.include( + { + width: 500, + height: 500, + cpm: 12.34, + creativeId: 'aCreativeId', + dealId: 'aDealId', + currency: 'USD', + netRevenue: true, + ttl: 360 }); + }); - it('should include first party data in open rtb request, site section', () => { - const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data; + it('returns a correctly parsed out response with explicitly defined size when strData.skipIframeBusting is false and strData.sizes contains [0, 0] only', function() { + expect(spec.interpretResponse(bidderResponse, prebidRequests[3])[0]).to.include( + { + width: 0, + height: 0, + cpm: 12.34, + creativeId: 'aCreativeId', + dealId: 'aDealId', + currency: 'USD', + netRevenue: true, + ttl: 360 + }); + }); - expect(openRtbReq.site.name).to.equal(firstPartyData.site.name); - expect(openRtbReq.site.keywords).to.equal(firstPartyData.site.keywords); - expect(openRtbReq.site.search).to.equal(firstPartyData.site.search); - expect(openRtbReq.site.content).to.deep.equal(firstPartyData.site.content); - expect(openRtbReq.site.ext).to.deep.equal(firstPartyData.site.ext); + it('returns a correctly parsed out response with explicitly defined size when strData.skipIframeBusting is false and strData.sizes contains multiple sizes', function() { + expect(spec.interpretResponse(bidderResponse, prebidRequests[4])[0]).to.include( + { + width: 300, + height: 300, + cpm: 12.34, + creativeId: 'aCreativeId', + dealId: 'aDealId', + currency: 'USD', + netRevenue: true, + ttl: 360 }); + }); - it('should include first party data in open rtb request, user section', () => { - const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data; + it('returns a blank array if there are no creatives', function() { + const bidResponse = { body: { creatives: [] } }; + expect(spec.interpretResponse(bidResponse, prebidRequests[0])).to.be.an('array').that.is.empty; + }); - expect(openRtbReq.user.yob).to.equal(firstPartyData.user.yob); - expect(openRtbReq.user.gender).to.equal(firstPartyData.user.gender); - expect(openRtbReq.user.ext.data).to.deep.equal(firstPartyData.user.ext.data); - expect(openRtbReq.user.ext.eids).not.to.be.undefined; - }); - }); + it('returns a blank array if body object is empty', function() { + const bidResponse = { body: {} }; + expect(spec.interpretResponse(bidResponse, prebidRequests[0])).to.be.an('array').that.is.empty; }); - describe('interpretResponse', function () { - let request; - let response; - - describe('banner', () => { - beforeEach(() => { - request = spec.buildRequests(bidRequests, bidderRequest)[0]; - response = { - body: { - seatbid: [{ - bid: [{ - id: '123', - impid: 'bidId1', - w: 300, - h: 250, - price: 42, - crid: 'creative', - dealid: 'deal', - adomain: ['domain.com'], - adm: 'markup', - }, { - id: '456', - impid: 'bidId2', - w: 640, - h: 480, - price: 42, - adm: 'vastTag', - }], - }], - }, - }; - }); + it('returns a blank array if body is null', function() { + const bidResponse = { body: null }; + expect(spec.interpretResponse(bidResponse, prebidRequests[0])).to.be.an('array').that.is.empty; + }); - it('should return a banner bid', () => { - const resp = spec.interpretResponse(response, request); - - const bannerBid = resp[0]; - expect(bannerBid.requestId).to.equal('bidId1'); - expect(bannerBid.width).to.equal(300); - expect(bannerBid.height).to.equal(250); - expect(bannerBid.cpm).to.equal(42); - expect(bannerBid.creativeId).to.equal('creative'); - expect(bannerBid.dealId).to.equal('deal'); - expect(bannerBid.mediaType).to.equal('banner'); - expect(bannerBid.currency).to.equal('USD'); - expect(bannerBid.netRevenue).to.equal(true); - expect(bannerBid.ttl).to.equal(360); - expect(bannerBid.ad).to.equal('markup'); - expect(bannerBid.meta.advertiserDomains).to.deep.equal(['domain.com']); - expect(bannerBid.vastXml).to.be.undefined; - }); - }); + it('correctly generates ad markup when skipIframeBusting is false', function() { + const adMarkup = spec.interpretResponse(bidderResponse, prebidRequests[0])[0].ad; + let resp = null; - describe('video', () => { - beforeEach(() => { - request = spec.buildRequests(bidRequests, bidderRequest)[1]; - response = { - body: { - seatbid: [{ - bid: [{ - id: '456', - impid: 'bidId2', - w: 640, - h: 480, - price: 42, - adm: 'vastTag', - }], - }], - }, - }; - }); + expect(() => btoa(JSON.stringify(bidderResponse))).to.throw(); + expect(() => resp = sharethroughInternal.b64EncodeUnicode(JSON.stringify(bidderResponse))).not.to.throw(); + expect(adMarkup).to.match( + /data-str-native-key="pKey" data-stx-response-name="str_response_bidId"/); + expect(!!adMarkup.indexOf(resp)).to.eql(true); - it('should return a video bid', () => { - const resp = spec.interpretResponse(response, request); - - const bannerBid = resp[0]; - expect(bannerBid.requestId).to.equal('bidId2'); - expect(bannerBid.width).to.equal(640); - expect(bannerBid.height).to.equal(480); - expect(bannerBid.cpm).to.equal(42); - expect(bannerBid.creativeId).to.be.undefined; - expect(bannerBid.dealId).to.be.null; - expect(bannerBid.mediaType).to.equal('video'); - expect(bannerBid.currency).to.equal('USD'); - expect(bannerBid.netRevenue).to.equal(true); - expect(bannerBid.ttl).to.equal(3600); - expect(bannerBid.ad).to.equal('vastTag'); - expect(bannerBid.meta.advertiserDomains).to.deep.equal([]); - expect(bannerBid.vastXml).to.equal('vastTag'); - }); - }); + // insert functionality to autodetect whether or not in safeframe, and handle JS insertion + expect(adMarkup).to.match(/isLockedInFrame/); + expect(adMarkup).to.match(/handleIframe/); }); - describe('getUserSyncs', function () { - const cookieSyncs = ['cookieUrl1', 'cookieUrl2', 'cookieUrl3']; - const serverResponses = [{ body: { cookieSyncUrls: cookieSyncs } }]; + it('correctly generates ad markup when skipIframeBusting is true', function() { + const adMarkup = spec.interpretResponse(bidderResponse, prebidRequests[1])[0].ad; + let resp = null; + + expect(() => btoa(JSON.stringify(bidderResponse))).to.throw(); + expect(() => resp = sharethroughInternal.b64EncodeUnicode(JSON.stringify(bidderResponse))).not.to.throw(); + expect(adMarkup).to.match( + /data-str-native-key="pKey" data-stx-response-name="str_response_bidId"/); + expect(!!adMarkup.indexOf(resp)).to.eql(true); + expect(adMarkup).to.match( + /"'; -describe('slimcutBidAdapter', function() { - const adapter = newBidder(spec); - describe('inherited functions', function() { - it('exists and is a function', function() { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - describe('isBidRequestValid', function() { - let bid = { - 'bidder': 'slimcut', - 'params': { - 'placementId': 83 - }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250], - [300, 600] - ], - 'bidId': '3c871ffa8ef14c', - 'bidderRequestId': 'b41642f1aee381', - 'auctionId': '4e156668c977d7' - }; - it('should return true when required params found', function() { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - it('should return false when placementId is not valid (letters)', function() { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - 'placementId': 'ABCD' - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - it('should return false when placementId < 0', function() { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - 'placementId': -1 - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - it('should return false when required params are not passed', function() { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {}; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - describe('buildRequests', function() { - let bidRequests = [{ - 'bidder': 'teads', - 'params': { - 'placementId': 10433394 - }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250], - [300, 600] - ], - 'bidId': '3c871ffa8ef14c', - 'bidderRequestId': 'b41642f1aee381', - 'auctionId': '4e156668c977d7', - 'deviceWidth': 1680 - }]; - let bidderResquestDefault = { - 'auctionId': '4e156668c977d7', - 'bidderRequestId': 'b41642f1aee381', - 'timeout': 3000 - }; - it('sends bid request to ENDPOINT via POST', function() { - const request = spec.buildRequests(bidRequests, bidderResquestDefault); - expect(request.url).to.equal(ENDPOINT); - expect(request.method).to.equal('POST'); - }); - it('should send GDPR to endpoint', function() { - let consentString = 'JRJ8RKfDeBNsERRDCSAAZ+A=='; - let bidderRequest = { - 'auctionId': '4e156668c977d7', - 'bidderRequestId': 'b41642f1aee381', - 'timeout': 3000, - 'gdprConsent': { - 'consentString': consentString, - 'gdprApplies': true, - 'vendorData': { - 'hasGlobalConsent': false - } - } - }; - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - expect(payload.gdpr_iab).to.exist; - expect(payload.gdpr_iab.consent).to.equal(consentString); - }); - it('should add referer info to payload', function() { - const bidRequest = Object.assign({}, bidRequests[0]) - const bidderRequest = { - refererInfo: { - referer: 'https://example.com/page.html', - reachedTop: true, - numIframes: 2 - } - } - const request = spec.buildRequests([bidRequest], bidderRequest); - const payload = JSON.parse(request.data); - expect(payload.referrer).to.exist; - expect(payload.referrer).to.deep.equal('https://example.com/page.html') - }); - }); - describe('getUserSyncs', () => { - let bids = { - 'body': { - 'responses': [{ - 'ad': AD_SCRIPT, - 'cpm': 0.5, - 'currency': 'USD', - 'height': 250, - 'netRevenue': true, - 'requestId': '3ede2a3fa0db94', - 'ttl': 360, - 'width': 300, - 'creativeId': 'er2ee', - 'transactionId': 'deadb33f', - 'winUrl': 'https://sb.freeskreen.com/win' - }] - } - }; - it('should get the correct number of sync urls', () => { - let urls = spec.getUserSyncs({ - iframeEnabled: true - }, bids); - expect(urls.length).to.equal(1); - expect(urls[0].url).to.equal('https://sb.freeskreen.com/async_usersync.html'); - }); - it('should return no url if not iframe enabled', () => { - let urls = spec.getUserSyncs({ - iframeEnabled: false - }, bids); - expect(urls.length).to.equal(0); - }); - }); - describe('interpretResponse', function() { - let bids = { - 'body': { - 'responses': [{ - 'ad': AD_SCRIPT, - 'cpm': 0.5, - 'currency': 'USD', - 'height': 250, - 'netRevenue': true, - 'requestId': '3ede2a3fa0db94', - 'ttl': 360, - 'width': 300, - 'creativeId': 'er2ee', - 'transactionId': 'deadb33f', - 'winUrl': 'https://sb.freeskreen.com/win' - }] - } - }; - it('should get correct bid response', function() { - let expectedResponse = [{ - 'cpm': 0.5, - 'width': 300, - 'height': 250, - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 360, - 'ad': AD_SCRIPT, - 'requestId': '3ede2a3fa0db94', - 'creativeId': 'er2ee', - 'transactionId': 'deadb33f', - 'winUrl': 'https://sb.freeskreen.com/win', - 'meta': { - 'advertiserDomains': [] - } - }]; - let result = spec.interpretResponse(bids); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); - }); - it('handles nobid responses', function() { - let bids = { - 'body': { - 'responses': [] - } - }; - let result = spec.interpretResponse(bids); - expect(result.length).to.equal(0); - }); - }); -}); diff --git a/test/spec/modules/smaatoBidAdapter_spec.js b/test/spec/modules/smaatoBidAdapter_spec.js index 38df03652b1..faa288306a5 100644 --- a/test/spec/modules/smaatoBidAdapter_spec.js +++ b/test/spec/modules/smaatoBidAdapter_spec.js @@ -127,15 +127,6 @@ describe('smaatoBidAdapterTest', () => { } }; - let sandbox; - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }) - it('auction type is 1 (first price auction)', () => { const reqs = spec.buildRequests([singleBannerBidRequest], defaultBidderRequest); @@ -296,23 +287,6 @@ describe('smaatoBidAdapterTest', () => { expect(req.regs.ext.us_privacy).to.equal('uspConsentString'); }); - it('sends no schain if no schain exists', () => { - const reqs = spec.buildRequests([singleBannerBidRequest], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.source.ext.schain).to.not.exist; - }); - - it('sends instl if instl exists', () => { - const instl = { instl: 1 }; - const bidRequestWithInstl = Object.assign({}, singleBannerBidRequest, {ortb2Imp: instl}); - - const reqs = spec.buildRequests([bidRequestWithInstl], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.imp[0].instl).to.equal(1); - }); - it('sends tmax', () => { const reqs = spec.buildRequests([singleBannerBidRequest], defaultBidderRequest); @@ -328,15 +302,12 @@ describe('smaatoBidAdapterTest', () => { }); it('sends first party data', () => { - sandbox.stub(config, 'getConfig').callsFake(key => { + this.sandbox = sinon.sandbox.create() + this.sandbox.stub(config, 'getConfig').callsFake(key => { const config = { ortb2: { site: { - keywords: 'power tools,drills', - publisher: { - id: 'otherpublisherid', - name: 'publishername' - } + keywords: 'power tools,drills' }, user: { keywords: 'a,b', @@ -357,6 +328,7 @@ describe('smaatoBidAdapterTest', () => { expect(req.user.ext.consent).to.equal(CONSENT_STRING); expect(req.site.keywords).to.eql('power tools,drills'); expect(req.site.publisher.id).to.equal('publisherId'); + this.sandbox.restore(); }); it('has no user ids', () => { @@ -463,16 +435,6 @@ describe('smaatoBidAdapterTest', () => { expect(req.imp[0].bidfloor).to.be.equal(0.456); }); - it('sends instl if instl exists', () => { - const instl = { instl: 1 }; - const bidRequestWithInstl = Object.assign({}, singleVideoBidRequest, {ortb2Imp: instl}); - - const reqs = spec.buildRequests([bidRequestWithInstl], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.imp[0].instl).to.equal(1); - }); - it('splits multi format bid requests', () => { const combinedBannerAndVideoBidRequest = { bidder: 'smaato', @@ -554,17 +516,6 @@ describe('smaatoBidAdapterTest', () => { expect(req.imp[1].video.sequence).to.be.equal(2); }); - it('sends instl if instl exists', () => { - const instl = { instl: 1 }; - const bidRequestWithInstl = Object.assign({}, longFormVideoBidRequest, {ortb2Imp: instl}); - - const reqs = spec.buildRequests([bidRequestWithInstl], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.imp[0].instl).to.equal(1); - expect(req.imp[1].instl).to.equal(1); - }); - it('sends bidfloor when configured', () => { const longFormVideoBidRequestWithFloor = Object.assign({}, longFormVideoBidRequest); longFormVideoBidRequestWithFloor.getFloor = function(arg) { @@ -903,29 +854,6 @@ describe('smaatoBidAdapterTest', () => { expect(req.user.ext.eids).to.have.length(2); }); }); - - describe('schain in request', () => { - it('schain is added to source.ext.schain', () => { - const schain = { - ver: '1.0', - complete: 1, - nodes: [ - { - 'asi': 'asi', - 'sid': 'sid', - 'rid': 'rid', - 'hp': 1 - } - ] - }; - const bidRequestWithSchain = Object.assign({}, singleBannerBidRequest, {schain: schain}); - - const reqs = spec.buildRequests([bidRequestWithSchain], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.source.ext.schain).to.deep.equal(schain); - }); - }); }); describe('interpretResponse', () => { diff --git a/test/spec/modules/smarthubBidAdapter_spec.js b/test/spec/modules/smarthubBidAdapter_spec.js deleted file mode 100644 index 05fb1424dca..00000000000 --- a/test/spec/modules/smarthubBidAdapter_spec.js +++ /dev/null @@ -1,392 +0,0 @@ -import { expect } from 'chai'; -import { spec } from '../../../modules/smarthubBidAdapter'; -import { BANNER, VIDEO, NATIVE } from '../../../src/mediaTypes.js'; -import { getUniqueIdentifierStr } from '../../../src/utils.js'; - -const bidder = 'smarthub' - -describe('SmartHubBidAdapter', function () { - const bids = [ - { - bidId: getUniqueIdentifierStr(), - bidder: bidder, - mediaTypes: { - [BANNER]: { - sizes: [[300, 250]] - } - }, - params: { - partnerName: 'testname', - seat: 'testSeat', - token: 'testBanner', - iabCat: ['IAB1-1', 'IAB3-1', 'IAB4-3'], - minBidfloor: 10, - pos: 1, - } - }, - { - bidId: getUniqueIdentifierStr(), - bidder: bidder, - mediaTypes: { - [VIDEO]: { - playerSize: [[300, 300]], - minduration: 5, - maxduration: 60, - } - }, - params: { - partnerName: 'testname', - seat: 'testSeat', - token: 'testVideo', - iabCat: ['IAB1-1', 'IAB3-1', 'IAB4-3'], - minBidfloor: 10, - pos: 1, - } - }, - { - bidId: getUniqueIdentifierStr(), - bidder: bidder, - mediaTypes: { - [NATIVE]: { - native: { - title: { - required: true - }, - body: { - required: true - }, - icon: { - required: true, - size: [64, 64] - } - } - } - }, - params: { - partnerName: 'testname', - seat: 'testSeat', - token: 'testToken', - iabCat: ['IAB1-1', 'IAB3-1', 'IAB4-3'], - minBidfloor: 10, - pos: 1, - } - } - ]; - - const invalidBid = { - bidId: getUniqueIdentifierStr(), - bidder: bidder, - mediaTypes: { - [BANNER]: { - sizes: [[300, 250]] - } - }, - params: { - - } - } - - const bidderRequest = { - uspConsent: '1---', - gdprConsent: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw', - refererInfo: { - referer: 'https://test.com' - } - }; - - describe('isBidRequestValid', function () { - it('Should return true if there are bidId, params and key parameters present', function () { - expect(spec.isBidRequestValid(bids[0])).to.be.true; - }); - it('Should return false if at least one of parameters is not present', function () { - expect(spec.isBidRequestValid(invalidBid)).to.be.false; - }); - }); - - describe('buildRequests', function () { - let [serverRequest] = spec.buildRequests(bids, bidderRequest); - - it('Creates a ServerRequest object with method, URL and data', function () { - expect(serverRequest).to.exist; - expect(serverRequest.method).to.exist; - expect(serverRequest.url).to.exist; - expect(serverRequest.data).to.exist; - }); - - it('Returns POST method', function () { - expect(serverRequest.method).to.equal('POST'); - }); - - it('Returns valid URL', function () { - expect(serverRequest.url).to.equal('https://testname-prebid.smart-hub.io/pbjs'); - }); - - it('Returns general data valid', function () { - let data = serverRequest.data; - expect(data).to.be.an('object'); - expect(data).to.have.all.keys('deviceWidth', - 'deviceHeight', - 'language', - 'secure', - 'host', - 'page', - 'placements', - 'coppa', - 'ccpa', - 'gdpr', - 'tmax' - ); - expect(data.deviceWidth).to.be.a('number'); - expect(data.deviceHeight).to.be.a('number'); - expect(data.language).to.be.a('string'); - expect(data.secure).to.be.within(0, 1); - expect(data.host).to.be.a('string'); - expect(data.page).to.be.a('string'); - expect(data.coppa).to.be.a('number'); - expect(data.gdpr).to.be.a('string'); - expect(data.ccpa).to.be.a('string'); - expect(data.tmax).to.be.a('number'); - expect(data.placements).to.have.lengthOf(3); - }); - - it('Returns valid placements', function () { - const { placements } = serverRequest.data; - for (let i = 0, len = placements.length; i < len; i++) { - const placement = placements[i]; - expect(placement.adFormat).to.be.oneOf([BANNER, VIDEO, NATIVE]); - expect(placement.bidId).to.be.a('string'); - expect(placement.partnerName).to.be.a('string'); - expect(placement.seat).to.be.a('string'); - expect(placement.token).to.be.a('string'); - expect(placement.iabCat).to.be.an('array'); - expect(placement.minBidfloor).to.be.a('number'); - expect(placement.pos).to.be.within(0, 7); - expect(placement.schain).to.be.an('object'); - expect(placement.bidfloor).to.exist.and.to.equal(0); - - if (placement.adFormat === BANNER) { - expect(placement.sizes).to.be.an('array'); - } - switch (placement.adFormat) { - case BANNER: - expect(placement.sizes).to.be.an('array'); - break; - case VIDEO: - expect(placement.playerSize).to.be.an('array'); - expect(placement.minduration).to.be.an('number'); - expect(placement.maxduration).to.be.an('number'); - break; - case NATIVE: - expect(placement.native).to.be.an('object'); - break; - } - } - }); - - it('Returns data with gdprConsent and without uspConsent', function () { - delete bidderRequest.uspConsent; - serverRequest = spec.buildRequests(bids, bidderRequest); - let data = serverRequest[0].data; - expect(data.gdpr).to.exist; - expect(data.gdpr).to.be.a('string'); - expect(data.gdpr).to.equal(bidderRequest.gdprConsent); - expect(data.ccpa).to.not.exist; - delete bidderRequest.gdprConsent; - }); - - it('Returns data with uspConsent and without gdprConsent', function () { - bidderRequest.uspConsent = '1---'; - delete bidderRequest.gdprConsent; - serverRequest = spec.buildRequests(bids, bidderRequest); - let data = serverRequest[0].data; - expect(data.ccpa).to.exist; - expect(data.ccpa).to.be.a('string'); - expect(data.ccpa).to.equal(bidderRequest.uspConsent); - expect(data.gdpr).to.not.exist; - }); - - it('Returns empty data if no valid requests are passed', function () { - serverRequest = spec.buildRequests([], bidderRequest); - expect(serverRequest).to.be.an('array').that.is.empty; - }); - }); - - describe('interpretResponse', function () { - it('Should interpret banner response', function () { - const banner = { - body: [{ - mediaType: 'banner', - width: 300, - height: 250, - cpm: 0.4, - ad: 'Test', - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1', - meta: { - advertiserDomains: ['google.com'], - advertiserId: 1234 - } - }] - }; - let bannerResponses = spec.interpretResponse(banner); - expect(bannerResponses).to.be.an('array').that.is.not.empty; - let dataItem = bannerResponses[0]; - expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', - 'netRevenue', 'currency', 'dealId', 'mediaType', 'meta'); - expect(dataItem.requestId).to.equal(banner.body[0].requestId); - expect(dataItem.cpm).to.equal(banner.body[0].cpm); - expect(dataItem.width).to.equal(banner.body[0].width); - expect(dataItem.height).to.equal(banner.body[0].height); - expect(dataItem.ad).to.equal(banner.body[0].ad); - expect(dataItem.ttl).to.equal(banner.body[0].ttl); - expect(dataItem.creativeId).to.equal(banner.body[0].creativeId); - expect(dataItem.netRevenue).to.be.true; - expect(dataItem.currency).to.equal(banner.body[0].currency); - expect(dataItem.meta).to.be.an('object').that.has.property('advertiserDomains'); - }); - it('Should interpret video response', function () { - const video = { - body: [{ - vastUrl: 'test.com', - mediaType: 'video', - cpm: 0.5, - requestId: '23fhj33i987f', - width: 300, - height: 250, - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1', - meta: { - advertiserDomains: ['google.com'], - advertiserId: 1234 - } - }] - }; - let videoResponses = spec.interpretResponse(video); - expect(videoResponses).to.be.an('array').that.is.not.empty; - - let dataItem = videoResponses[0]; - expect(dataItem).to.have.all.keys('requestId', 'cpm', 'vastUrl', 'ttl', 'creativeId', - 'netRevenue', 'currency', 'dealId', 'mediaType', 'meta', 'width', 'height'); - expect(dataItem.requestId).to.equal('23fhj33i987f'); - expect(dataItem.cpm).to.equal(0.5); - expect(dataItem.vastUrl).to.equal('test.com'); - expect(dataItem.ttl).to.equal(120); - expect(dataItem.creativeId).to.equal('2'); - expect(dataItem.netRevenue).to.be.true; - expect(dataItem.currency).to.equal('USD'); - expect(dataItem.meta).to.be.an('object').that.has.property('advertiserDomains'); - }); - it('Should interpret native response', function () { - const native = { - body: [{ - mediaType: 'native', - native: { - clickUrl: 'test.com', - title: 'Test', - image: 'test.com', - impressionTrackers: ['test.com'], - }, - ttl: 120, - cpm: 0.4, - requestId: '23fhj33i987f', - creativeId: '2', - netRevenue: true, - currency: 'USD', - meta: { - advertiserDomains: ['google.com'], - advertiserId: 1234 - } - }] - }; - let nativeResponses = spec.interpretResponse(native); - expect(nativeResponses).to.be.an('array').that.is.not.empty; - - let dataItem = nativeResponses[0]; - expect(dataItem).to.have.keys('requestId', 'cpm', 'ttl', 'creativeId', 'netRevenue', 'currency', 'mediaType', 'native', 'meta'); - expect(dataItem.native).to.have.keys('clickUrl', 'impressionTrackers', 'title', 'image') - expect(dataItem.requestId).to.equal('23fhj33i987f'); - expect(dataItem.cpm).to.equal(0.4); - expect(dataItem.native.clickUrl).to.equal('test.com'); - expect(dataItem.native.title).to.equal('Test'); - expect(dataItem.native.image).to.equal('test.com'); - expect(dataItem.native.impressionTrackers).to.be.an('array').that.is.not.empty; - expect(dataItem.native.impressionTrackers[0]).to.equal('test.com'); - expect(dataItem.ttl).to.equal(120); - expect(dataItem.creativeId).to.equal('2'); - expect(dataItem.netRevenue).to.be.true; - expect(dataItem.currency).to.equal('USD'); - expect(dataItem.meta).to.be.an('object').that.has.property('advertiserDomains'); - }); - it('Should return an empty array if invalid banner response is passed', function () { - const invBanner = { - body: [{ - width: 300, - cpm: 0.4, - ad: 'Test', - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - - let serverResponses = spec.interpretResponse(invBanner); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - it('Should return an empty array if invalid video response is passed', function () { - const invVideo = { - body: [{ - mediaType: 'video', - cpm: 0.5, - requestId: '23fhj33i987f', - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - let serverResponses = spec.interpretResponse(invVideo); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - it('Should return an empty array if invalid native response is passed', function () { - const invNative = { - body: [{ - mediaType: 'native', - clickUrl: 'test.com', - title: 'Test', - impressionTrackers: ['test.com'], - ttl: 120, - requestId: '23fhj33i987f', - creativeId: '2', - netRevenue: true, - currency: 'USD', - }] - }; - let serverResponses = spec.interpretResponse(invNative); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - it('Should return an empty array if invalid response is passed', function () { - const invalid = { - body: [{ - ttl: 120, - creativeId: '2', - netRevenue: true, - currency: 'USD', - dealId: '1' - }] - }; - let serverResponses = spec.interpretResponse(invalid); - expect(serverResponses).to.be.an('array').that.is.empty; - }); - }); -}); diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index ddee2fa3347..89c03034ba4 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -189,14 +189,6 @@ describe('The smartx adapter', function () { domain: '', publisher: { id: '__name__' - }, - content: { - ext: { - prebid: { - name: 'pbjs', - version: '$prebid.version$' - } - } } }); }); @@ -503,7 +495,7 @@ describe('The smartx adapter', function () { }; }); - it('should attempt to insert the script without outstream config options set', function () { + it('should attempt to insert the script', function () { var scriptTag; sinon.stub(window.document, 'getElementById').returns({ appendChild: sinon.stub().callsFake(function (script) { @@ -514,52 +506,8 @@ describe('The smartx adapter', function () { responses[0].renderer.render(responses[0]); - expect(responses[0].renderer.url).to.equal('https://dco.smartclip.net/?plc=7777778'); - - window.document.getElementById.restore(); - }); - - it('should attempt to insert the script with outstream config options set', function () { - var scriptTag; - sinon.stub(window.document, 'getElementById').returns({ - appendChild: sinon.stub().callsFake(function (script) { - scriptTag = script - }) - }); - var responses = spec.interpretResponse(serverResponse, bidderRequestObj); - - bidderRequestObj.bidRequest.bids[0].params.outstream_options.startOpen = 'true'; - bidderRequestObj.bidRequest.bids[0].params.outstream_options.endingScreen = 'true'; - bidderRequestObj.bidRequest.bids[0].params.outstream_options.title = 'abc'; - bidderRequestObj.bidRequest.bids[0].params.outstream_options.skipOffset = 2; - bidderRequestObj.bidRequest.bids[0].params.outstream_options.desiredBitrate = 123; - bidderRequestObj.bidRequest.bids[0].params.outstream_options.visibilityThreshold = 30; - - responses[0].renderer.render(responses[0]); - - bidderRequestObj.bidRequest.bids[0].params.outstream_options.startOpen = 'false'; - bidderRequestObj.bidRequest.bids[0].params.outstream_options.endingScreen = 'false'; - - responses[0].renderer.render(responses[0]); - - expect(responses[0].renderer.url).to.equal('https://dco.smartclip.net/?plc=7777778'); - - window.document.getElementById.restore(); - }); - - it('should attempt to insert the script without defined slot', function () { - var scriptTag; - sinon.stub(window.document, 'getElementById').returns({ - appendChild: sinon.stub().callsFake(function (script) { - scriptTag = script - }) - }); - var responses = spec.interpretResponse(serverResponse, bidderRequestObj); - - delete bidderRequestObj.bidRequest.bids[0].params.outstream_options.slot; - - responses[0].renderer.render(responses[0]); - + // expect(scriptTag.getAttribute('type')).to.equal('text/javascript'); + // expect(scriptTag.getAttribute('src')).to.equal('https://dco.smartclip.net/?plc=7777778'); expect(responses[0].renderer.url).to.equal('https://dco.smartclip.net/?plc=7777778'); window.document.getElementById.restore(); @@ -592,7 +540,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 3.21); }); - it('obtain floor from params', function () { + it('obtain floor from params', function() { bid.getFloor = () => { return { currency: 'EUR', @@ -605,7 +553,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 0.64); }); - it('check currency USD', function () { + it('check currency USD', function() { bid.getFloor = () => { return { currency: 'USD', @@ -619,7 +567,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 1.23); }); - it('check defaut currency EUR', function () { + it('check defaut currency EUR', function() { delete bid.params.bidfloorcur; bid.getFloor = () => { @@ -634,7 +582,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 4.56); }); - it('bad floor value', function () { + it('bad floor value', function() { bid.getFloor = () => { return { currency: 'EUR', @@ -646,7 +594,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 0); }); - it('empty floor object', function () { + it('empty floor object', function() { bid.getFloor = () => { return {}; }; @@ -655,7 +603,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 0); }); - it('undefined floor result', function () { + it('undefined floor result', function() { bid.getFloor = () => {}; const payload = spec.buildRequests([bid], bidRequestObj)[0]; diff --git a/test/spec/modules/smartyadsBidAdapter_spec.js b/test/spec/modules/smartyadsBidAdapter_spec.js index 3474753c838..14363329a9e 100644 --- a/test/spec/modules/smartyadsBidAdapter_spec.js +++ b/test/spec/modules/smartyadsBidAdapter_spec.js @@ -7,19 +7,17 @@ describe('SmartyadsAdapter', function () { bidId: '23fhj33i987f', bidder: 'smartyads', params: { - host: 'prebid', - sourceid: '0', - accountid: '0', + placementId: 0, traffic: 'banner' } }; describe('isBidRequestValid', function () { - it('Should return true if there are bidId, params and sourceid parameters present', function () { + it('Should return true if there are bidId, params and placementId parameters present', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); it('Should return false if at least one of parameters is not present', function () { - delete bid.params.sourceid; + delete bid.params.placementId; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); @@ -36,7 +34,7 @@ describe('SmartyadsAdapter', function () { expect(serverRequest.method).to.equal('POST'); }); it('Returns valid URL', function () { - expect(serverRequest.url).to.equal('https://n1.smartyads.com/?c=o&m=prebid&secret_key=prebid_js'); + expect(serverRequest.url).to.equal('https://ssp-nj.webtradehub.com/?c=o&m=multi'); }); it('Returns valid data if array of bids is valid', function () { let data = serverRequest.data; @@ -50,8 +48,8 @@ describe('SmartyadsAdapter', function () { expect(data.host).to.be.a('string'); expect(data.page).to.be.a('string'); let placement = data['placements'][0]; - expect(placement).to.have.keys('placementId', 'bidId', 'traffic', 'sizes', 'publisherId'); - expect(placement.placementId).to.equal('0'); + expect(placement).to.have.keys('placementId', 'bidId', 'traffic', 'sizes'); + expect(placement.placementId).to.equal(0); expect(placement.bidId).to.equal('23fhj33i987f'); expect(placement.traffic).to.equal('banner'); }); @@ -243,18 +241,13 @@ describe('SmartyadsAdapter', function () { }); }); describe('getUserSyncs', function () { - const syncUrl = 'https://as.ck-ie.com/prebidjs?p=7c47322e527cf8bdeb7facc1bb03387a&gdpr=0&gdpr_consent=&type=iframe&us_privacy='; - const syncOptions = { - iframeEnabled: true - }; - let userSync = spec.getUserSyncs(syncOptions); + let userSync = spec.getUserSyncs(); it('Returns valid URL and type', function () { expect(userSync).to.be.an('array').with.lengthOf(1); expect(userSync[0].type).to.exist; expect(userSync[0].url).to.exist; - expect(userSync).to.deep.equal([ - { type: 'iframe', url: syncUrl } - ]); + expect(userSync[0].type).to.be.equal('image'); + expect(userSync[0].url).to.be.equal('https://ssp-nj.webtradehub.com/?c=o&m=cookie'); }); }); }); diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index f56f4e0c12b..8eee973794a 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -238,17 +238,14 @@ describe('SonobiBidAdapter', function () { }); describe('.buildRequests', function () { - let sandbox; beforeEach(function() { sinon.stub(userSync, 'canBidderRegisterSync'); sinon.stub(utils, 'getGptSlotInfoForAdUnitCode') - .onFirstCall().returns({gptSlot: '/123123/gpt_publisher/adunit-code-3', divId: 'adunit-code-3-div-id'}); - sandbox = sinon.createSandbox(); + .onFirstCall().returns({gptSlot: '/123123/gpt_publisher/adunit-code-3', divId: 'adunit-code-3-div-id'}) }); afterEach(function() { userSync.canBidderRegisterSync.restore(); utils.getGptSlotInfoForAdUnitCode.restore(); - sandbox.restore(); }); let bidRequest = [{ 'schain': { @@ -336,36 +333,6 @@ describe('SonobiBidAdapter', function () { uspConsent: 'someCCPAString' }; - it('should set fpd if there is any data in ortb2', function() { - const ortb2 = { - site: { - ext: { - data: { - pageType: 'article', - category: 'tools' - } - } - }, - user: { - ext: { - data: { - registered: true, - interests: ['cars'] - } - } - } - }; - - sandbox.stub(config, 'getConfig').callsFake(key => { - const config = { - ortb2: ortb2 - }; - return utils.deepAccess(config, key); - }); - const bidRequests = spec.buildRequests(bidRequest, bidderRequests); - expect(bidRequests.data.fpd).to.equal(JSON.stringify(ortb2)); - }); - it('should populate coppa as 1 if set in config', function () { config.setConfig({coppa: true}); const bidRequests = spec.buildRequests(bidRequest, bidderRequests); @@ -785,7 +752,6 @@ describe('SonobiBidAdapter', function () { expect(resp.width).to.equal(prebidResponse[i].width); expect(resp.height).to.equal(prebidResponse[i].height); expect(resp.renderer).to.be.ok; - expect(resp.ad).to.equal(undefined); } else if (resp.mediaType === 'video') { expect(resp.vastUrl.indexOf('vast.xml')).to.be.greaterThan(0); expect(resp.ad).to.be.undefined; diff --git a/test/spec/modules/sortableAnalyticsAdapter_spec.js b/test/spec/modules/sortableAnalyticsAdapter_spec.js index 9300756eae2..258c4b8f74d 100644 --- a/test/spec/modules/sortableAnalyticsAdapter_spec.js +++ b/test/spec/modules/sortableAnalyticsAdapter_spec.js @@ -1,6 +1,6 @@ import {expect} from 'chai'; import sortableAnalyticsAdapter, {TIMEOUT_FOR_REGISTRY, DEFAULT_PBID_TIMEOUT} from 'modules/sortableAnalyticsAdapter.js'; -import * as events from 'src/events.js'; +import events from 'src/events.js'; import CONSTANTS from 'src/constants.json'; import * as prebidGlobal from 'src/prebidGlobal.js'; import {server} from 'test/mocks/xhr.js'; @@ -148,6 +148,7 @@ describe('Sortable Analytics Adapter', function() { } } }); + sortableAnalyticsAdapter.enableAnalytics(initialConfig); }); @@ -202,11 +203,11 @@ describe('Sortable Analytics Adapter', function() { brc: 1, brid: ['10141593b1d84a', '37a8760be6db23'], rs: ['300x250', '728x90'], - btcp: [0.70, 0.50].map(n => n * 0.95), + btcp: [0.70, 0.50], btcc: 'USD', btin: true, btsrc: 'sortable', - c: [0.70, 0.50].map(n => n * 0.95), + c: [0.70, 0.50], cc: 'USD', did: null, inr: true, diff --git a/test/spec/modules/sortableBidAdapter_spec.js b/test/spec/modules/sortableBidAdapter_spec.js index 7357fa77952..17f77e96d51 100644 --- a/test/spec/modules/sortableBidAdapter_spec.js +++ b/test/spec/modules/sortableBidAdapter_spec.js @@ -112,13 +112,6 @@ describe('sortableBidAdapter', function() { 'key2': 'val2' } }, - 'ortb2Imp': { - 'ext': { - 'data': { - 'pbadslot': 'abc/123' - } - } - }, 'sizes': [ [300, 250] ], @@ -183,10 +176,6 @@ describe('sortableBidAdapter', function() { expect(requestBody.imp[0].floor).to.equal(0.21); }); - it('includes pbadslot in the bid request', function () { - expect(requestBody.imp[0].ext.gpid).to.equal('abc/123'); - }); - it('sets domain and href correctly', function () { expect(requestBody.site.domain).to.equal('example.com'); expect(requestBody.site.page).to.equal('http://example.com/page?param=val'); diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index 83a13f0db7b..518ea1f0a70 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -1,92 +1,79 @@ -import {expect} from 'chai'; -import {spec} from 'modules/sovrnBidAdapter.js'; -import {config} from 'src/config.js'; +import {expect} from 'chai' +import {spec} from 'modules/sovrnBidAdapter.js' +import {config} from 'src/config.js' import * as utils from 'src/utils.js' -const ENDPOINT = `https://ap.lijit.com/rtb/bid?src=$$REPO_AND_VERSION$$`; +const ENDPOINT = `https://ap.lijit.com/rtb/bid?src=$$REPO_AND_VERSION$$` const baseBidRequest = { - 'bidder': 'sovrn', - 'params': { - 'tagid': 403370 + bidder: 'sovrn', + params: { + tagid: 403370 }, - 'adUnitCode': 'adunit-code', - 'sizes': [ + adUnitCode: 'adunit-code', + sizes: [ [300, 250], [300, 600] ], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', } const baseBidderRequest = { refererInfo: { referer: 'http://example.com/page.html', } -}; +} describe('sovrnBidAdapter', function() { describe('isBidRequestValid', function () { it('should return true when required params found', function () { - expect(spec.isBidRequestValid(baseBidRequest)).to.equal(true); - }); + expect(spec.isBidRequestValid(baseBidRequest)).to.equal(true) + }) it('should return false when tagid not passed correctly', function () { const bidRequest = { ...baseBidRequest, - 'params': { + params: { ...baseBidRequest.params, - 'tagid': 'ABCD' + tagid: 'ABCD' }, - }; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false when require params are not passed', function () { - const bidRequest = { - ...baseBidRequest, - 'params': {} } - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); + expect(spec.isBidRequestValid(bidRequest)).to.equal(false) + }) - it('should return false when require video params are not passed', function () { + it('should return false when require params are not passed', function () { const bidRequest = { ...baseBidRequest, - 'mediaTypes': { - 'video': { - } - } + params: {} } - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - }); + expect(spec.isBidRequestValid(bidRequest)).to.equal(false) + }) + }) describe('buildRequests', function () { describe('basic bid parameters', function() { - const request = spec.buildRequests([baseBidRequest], baseBidderRequest); - const payload = JSON.parse(request.data); + const request = spec.buildRequests([baseBidRequest], baseBidderRequest) + const payload = JSON.parse(request.data) it('sends bid request to our endpoint via POST', function () { - expect(request.method).to.equal('POST'); - }); + expect(request.method).to.equal('POST') + }) it('attaches source and version to endpoint URL as query params', function () { expect(request.url).to.equal(ENDPOINT) - }); + }) it('sets the proper banner object', function() { const bannerBidRequest = { ...baseBidRequest, - 'mediaTypes': { + mediaTypes: { banner: {} } } const request = spec.buildRequests([bannerBidRequest], baseBidderRequest) - const payload = JSON.parse(request.data) const impression = payload.imp[0] @@ -105,7 +92,7 @@ describe('sovrnBidAdapter', function() { const startdelay = 0 const videoBidRequest = { ...baseBidRequest, - 'mediaTypes': { + mediaTypes: { video: { mimes, protocols, @@ -117,7 +104,6 @@ describe('sovrnBidAdapter', function() { } } const request = spec.buildRequests([videoBidRequest], baseBidderRequest) - const payload = JSON.parse(request.data) const impression = payload.imp[0] @@ -131,9 +117,9 @@ describe('sovrnBidAdapter', function() { }) it('gets correct site info', function() { - expect(payload.site.page).to.equal('http://example.com/page.html'); - expect(payload.site.domain).to.equal('example.com'); - }); + expect(payload.site.page).to.equal('http://example.com/page.html') + expect(payload.site.domain).to.equal('example.com') + }) it('includes the ad unit code in the request', function() { const impression = payload.imp[0] @@ -142,22 +128,21 @@ describe('sovrnBidAdapter', function() { it('converts tagid to string', function () { expect(request.data).to.contain('"tagid":"403370"') - }); + }) }) it('accepts a single array as a size', function() { const singleSizeBidRequest = { ...baseBidRequest, - 'params': { - 'iv': 'vet' + params: { + iv: 'vet' }, - 'sizes': [300, 250], - 'mediaTypes': { + sizes: [300, 250], + mediaTypes: { banner: {} }, } const request = spec.buildRequests([singleSizeBidRequest], baseBidderRequest) - const payload = JSON.parse(request.data) const impression = payload.imp[0] @@ -176,22 +161,21 @@ describe('sovrnBidAdapter', function() { const request = spec.buildRequests([ivBidRequest], baseBidderRequest) expect(request.url).to.contain('iv=vet') - }); + }) it('sends gdpr info if exists', function () { const bidderRequest = { ...baseBidderRequest, - 'bidderCode': 'sovrn', - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000, - 'gdprConsent': { - 'consentString': 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==', - 'gdprApplies': true + bidderCode: 'sovrn', + auctionId: '1d1a030790a475', + bidderRequestId: '22edbae2733bf6', + timeout: 3000, + gdprConsent: { + consentString: 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==', + gdprApplies: true }, - 'bids': [baseBidRequest] - }; - + bids: [baseBidRequest] + } const { regs, user } = JSON.parse(spec.buildRequests([baseBidRequest], bidderRequest).data) expect(regs.ext.gdpr).to.exist.and.to.be.a('number') @@ -203,14 +187,13 @@ describe('sovrnBidAdapter', function() { it('should send us_privacy if bidderRequest has a value for uspConsent', function () { const bidderRequest = { ...baseBidderRequest, - 'bidderCode': 'sovrn', - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000, - 'uspConsent': '1NYN', - 'bids': [baseBidRequest] + bidderCode: 'sovrn', + auctionId: '1d1a030790a475', + bidderRequestId: '22edbae2733bf6', + timeout: 3000, + uspConsent: '1NYN', + bids: [baseBidRequest] } - const data = JSON.parse(spec.buildRequests([baseBidRequest], bidderRequest).data) expect(data.regs.ext['us_privacy']).to.equal(bidderRequest.uspConsent) @@ -219,21 +202,20 @@ describe('sovrnBidAdapter', function() { it('should add schain if present', function() { const schainRequest = { ...baseBidRequest, - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ + schain: { + ver: '1.0', + complete: 1, + nodes: [ { - 'asi': 'directseller.com', - 'sid': '00001', - 'rid': 'BidRequest1', - 'hp': 1 + asi: 'directseller.com', + sid: '00001', + rid: 'BidRequest1', + hp: 1 } ] } } const schainRequests = [schainRequest, baseBidRequest] - const data = JSON.parse(spec.buildRequests(schainRequests, baseBidderRequest).data) expect(data.source.ext.schain.nodes.length).to.equal(1) @@ -248,7 +230,6 @@ describe('sovrnBidAdapter', function() { } } const criteoIdRequests = [criteoIdRequest, baseBidRequest] - const ext = JSON.parse(spec.buildRequests(criteoIdRequests, baseBidderRequest).data).user.ext const firstEID = ext.eids[0] const secondEID = ext.eids[1] @@ -294,7 +275,6 @@ describe('sovrnBidAdapter', function() { bidfloor: 2.00 } } - const request = spec.buildRequests([floorBid], baseBidderRequest) const payload = JSON.parse(request.data) @@ -309,7 +289,6 @@ describe('sovrnBidAdapter', function() { tagid: 1234, bidfloor: 2.00 } - const request = spec.buildRequests([floorBid], baseBidderRequest) const impression = JSON.parse(request.data).imp[0] @@ -359,7 +338,6 @@ describe('sovrnBidAdapter', function() { } } } - const request = spec.buildRequests([fpdBidRequest], baseBidderRequest) const payload = JSON.parse(request.data) @@ -381,7 +359,6 @@ describe('sovrnBidAdapter', function() { } } } - const request = spec.buildRequests([fpdBid], baseBidderRequest) const impression = JSON.parse(request.data).imp[0] @@ -390,102 +367,100 @@ describe('sovrnBidAdapter', function() { expect(impression.ext.deals).to.deep.equal(['seg1', 'seg2']) }) }) - }); + }) describe('interpretResponse', function () { - let response; + let response const baseResponse = { - 'requestId': '263c448586f5a1', - 'cpm': 0.45882675, - 'width': 728, - 'height': 90, - 'creativeId': 'creativelycreatedcreativecreative', - 'dealId': null, - 'currency': 'USD', - 'netRevenue': true, - 'mediaType': 'banner', - 'ttl': 90, - 'meta': { advertiserDomains: [] }, - 'ad': decodeURIComponent(``), + requestId: '263c448586f5a1', + cpm: 0.45882675, + width: 728, + height: 90, + creativeId: 'creativelycreatedcreativecreative', + dealId: null, + currency: 'USD', + netRevenue: true, + mediaType: 'banner', + ttl: 90, + meta: { advertiserDomains: [] }, + ad: decodeURIComponent(``), } const videoBid = { - 'id': 'a_403370_332fdb9b064040ddbec05891bd13ab28', - 'crid': 'creativelycreatedcreativecreative', - 'impid': '263c448586f5a1', - 'price': 0.45882675, - 'nurl': '', - 'adm': 'key%3Dvalue', - 'h': 480, - 'w': 640 + id: 'a_403370_332fdb9b064040ddbec05891bd13ab28', + crid: 'creativelycreatedcreativecreative', + impid: '263c448586f5a1', + price: 0.45882675, + nurl: '', + adm: 'key%3Dvalue', + h: 480, + w: 640 } const bannerBid = { - 'id': 'a_403370_332fdb9b064040ddbec05891bd13ab28', - 'crid': 'creativelycreatedcreativecreative', - 'impid': '263c448586f5a1', - 'price': 0.45882675, - 'nurl': '', - 'adm': '', - 'h': 90, - 'w': 728 + id: 'a_403370_332fdb9b064040ddbec05891bd13ab28', + crid: 'creativelycreatedcreativecreative', + impid: '263c448586f5a1', + price: 0.45882675, + nurl: '', + adm: '', + h: 90, + w: 728 } + beforeEach(function () { response = { body: { - 'id': '37386aade21a71', - 'seatbid': [{ - 'bid': [{ + id: '37386aade21a71', + seatbid: [{ + bid: [{ ...bannerBid }] }] } - }; - }); + } + }) it('should get the correct bid response', function () { const expectedResponse = { ...baseResponse, - 'ttl': 60000, - }; - - const result = spec.interpretResponse(response); + ad: decodeURIComponent(`>`), + ttl: 60000, + } + const result = spec.interpretResponse(response) - expect(result[0]).to.have.deep.keys(expectedResponse) - }); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse)) + }) it('crid should default to the bid id if not on the response', function () { - delete response.body.seatbid[0].bid[0].crid; + delete response.body.seatbid[0].bid[0].crid const expectedResponse = { ...baseResponse, - 'creativeId': response.body.seatbid[0].bid[0].id, - 'ad': decodeURIComponent(``), + creativeId: response.body.seatbid[0].bid[0].id, + ad: decodeURIComponent(``), } + const result = spec.interpretResponse(response) - const result = spec.interpretResponse(response); - - expect(result[0]).to.deep.equal(expectedResponse); - }); + expect(result[0]).to.deep.equal(expectedResponse) + }) it('should get correct bid response when dealId is passed', function () { - response.body.seatbid[0].bid[0].dealid = 'baking'; + response.body.seatbid[0].bid[0].dealid = 'baking' const expectedResponse = { ...baseResponse, - 'dealId': 'baking', + dealId: 'baking', } - const result = spec.interpretResponse(response) - expect(result[0]).to.deep.equal(expectedResponse); - }); + expect(result[0]).to.deep.equal(expectedResponse) + }) it('should get correct bid response when ttl is set', function () { - response.body.seatbid[0].bid[0].ext = { 'ttl': 480 } + response.body.seatbid[0].bid[0].ext = { ttl: 480 } const expectedResponse = { ...baseResponse, - 'ttl': 480, + ttl: 480, } - const result = spec.interpretResponse(response) expect(result[0]).to.deep.equal(expectedResponse) @@ -494,20 +469,19 @@ describe('sovrnBidAdapter', function() { it('handles empty bid response', function () { const response = { body: { - 'id': '37386aade21a71', - 'seatbid': [] + id: '37386aade21a71', + seatbid: [] } - }; - + } const result = spec.interpretResponse(response) - expect(result.length).to.equal(0); - }); + expect(result.length).to.equal(0) + }) it('should get the correct bid response with 2 different bids', function () { const expectedVideoResponse = { ...baseResponse, - 'vastXml': decodeURIComponent(videoBid.adm) + vastXml: decodeURIComponent(videoBid.adm) } delete expectedVideoResponse.ad @@ -533,90 +507,87 @@ describe('sovrnBidAdapter', function() { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse)) expect(Object.keys(result[1])).to.deep.equal(Object.keys(expectedResponse)) }) - }); + }) describe('interpretResponse video', function () { - let videoResponse; - const bidAdm = 'key%3Dvalue'; - const decodedBidAdm = decodeURIComponent(bidAdm); + let videoResponse + const bidAdm = 'key%3Dvalue' + const decodedBidAdm = decodeURIComponent(bidAdm) const baseVideoResponse = { - 'requestId': '263c448586f5a1', - 'cpm': 0.45882675, - 'width': 640, - 'height': 480, - 'creativeId': 'creativelycreatedcreativecreative', - 'dealId': null, - 'currency': 'USD', - 'netRevenue': true, - 'mediaType': 'video', - 'ttl': 90, - 'meta': { advertiserDomains: [] }, - 'vastXml': decodedBidAdm + requestId: '263c448586f5a1', + cpm: 0.45882675, + width: 640, + height: 480, + creativeId: 'creativelycreatedcreativecreative', + dealId: null, + currency: 'USD', + netRevenue: true, + mediaType: 'video', + ttl: 90, + meta: { advertiserDomains: [] }, + vastXml: decodedBidAdm } + beforeEach(function () { videoResponse = { body: { - 'id': '37386aade21a71', - 'seatbid': [{ - 'bid': [{ - 'id': 'a_403370_332fdb9b064040ddbec05891bd13ab28', - 'crid': 'creativelycreatedcreativecreative', - 'impid': '263c448586f5a1', - 'price': 0.45882675, - 'nurl': '', - 'adm': bidAdm, - 'h': 480, - 'w': 640 + id: '37386aade21a71', + seatbid: [{ + bid: [{ + id: 'a_403370_332fdb9b064040ddbec05891bd13ab28', + crid: 'creativelycreatedcreativecreative', + impid: '263c448586f5a1', + price: 0.45882675, + nurl: '', + adm: bidAdm, + h: 480, + w: 640 }] }] } - }; - }); + } + }) it('should get the correct bid response', function () { const expectedResponse = { ...baseVideoResponse, - 'ttl': 60000, - }; - - const result = spec.interpretResponse(videoResponse); + ttl: 60000, + } + const result = spec.interpretResponse(videoResponse) expect(result[0]).to.have.deep.keys(expectedResponse) - }); + }) it('crid should default to the bid id if not on the response', function () { - delete videoResponse.body.seatbid[0].bid[0].crid; + delete videoResponse.body.seatbid[0].bid[0].crid const expectedResponse = { ...baseVideoResponse, - 'creativeId': videoResponse.body.seatbid[0].bid[0].id, + creativeId: videoResponse.body.seatbid[0].bid[0].id, } + const result = spec.interpretResponse(videoResponse) - const result = spec.interpretResponse(videoResponse); - - expect(result[0]).to.deep.equal(expectedResponse); - }); + expect(result[0]).to.deep.equal(expectedResponse) + }) it('should get correct bid response when dealId is passed', function () { - videoResponse.body.seatbid[0].bid[0].dealid = 'baking'; + videoResponse.body.seatbid[0].bid[0].dealid = 'baking' const expectedResponse = { ...baseVideoResponse, - 'dealId': 'baking', + dealId: 'baking', } - const result = spec.interpretResponse(videoResponse) - expect(result[0]).to.deep.equal(expectedResponse); - }); + expect(result[0]).to.deep.equal(expectedResponse) + }) it('should get correct bid response when ttl is set', function () { videoResponse.body.seatbid[0].bid[0].ext = { 'ttl': 480 } const expectedResponse = { ...baseVideoResponse, - 'ttl': 480, + ttl: 480, } - const result = spec.interpretResponse(videoResponse) expect(result[0]).to.deep.equal(expectedResponse) @@ -625,52 +596,51 @@ describe('sovrnBidAdapter', function() { it('handles empty bid response', function () { const response = { body: { - 'id': '37386aade21a71', - 'seatbid': [] + id: '37386aade21a71', + seatbid: [] } - }; - + } const result = spec.interpretResponse(response) - expect(result.length).to.equal(0); - }); - }); + expect(result.length).to.equal(0) + }) + }) describe('getUserSyncs ', function() { - const syncOptions = { iframeEnabled: true, pixelEnabled: false }; - const iframeDisabledSyncOptions = { iframeEnabled: false, pixelEnabled: false }; + const syncOptions = { iframeEnabled: true, pixelEnabled: false } + const iframeDisabledSyncOptions = { iframeEnabled: false, pixelEnabled: false } const serverResponse = [ { - 'body': { - 'id': '546956d68c757f', - 'seatbid': [ + body: { + id: '546956d68c757f', + seatbid: [ { - 'bid': [ + bid: [ { - 'id': 'a_448326_16c2ada014224bee815a90d2248322f5', - 'impid': '2a3826aae345f4', - 'price': 1.0099999904632568, - 'nurl': 'http://localhost/rtb/impression?bannerid=220958&campaignid=3890&rtb_tid=15588614-75d2-40ab-b27e-13d2127b3c2e&rpid=1295&seatid=seat1&zoneid=448326&cb=26900712&tid=a_448326_16c2ada014224bee815a90d2248322f5', - 'adm': 'yo a creative', - 'crid': 'cridprebidrtb', - 'w': 160, - 'h': 600 + id: 'a_448326_16c2ada014224bee815a90d2248322f5', + impid: '2a3826aae345f4', + price: 1.0099999904632568, + nurl: 'http://localhost/rtb/impression?bannerid=220958&campaignid=3890&rtb_tid=15588614-75d2-40ab-b27e-13d2127b3c2e&rpid=1295&seatid=seat1&zoneid=448326&cb=26900712&tid=a_448326_16c2ada014224bee815a90d2248322f5', + adm: 'yo a creative', + crid: 'cridprebidrtb', + w: 160, + h: 600 }, { - 'id': 'a_430392_beac4c1515da4576acf6cb9c5340b40c', - 'impid': '3cf96fd26ed4c5', - 'price': 1.0099999904632568, - 'nurl': 'http://localhost/rtb/impression?bannerid=220957&campaignid=3890&rtb_tid=5bc0e68b-3492-448d-a6f9-26fa3fd0b646&rpid=1295&seatid=seat1&zoneid=430392&cb=62735099&tid=a_430392_beac4c1515da4576acf6cb9c5340b40c', - 'adm': 'yo a creative', - 'crid': 'cridprebidrtb', - 'w': 300, - 'h': 250 + id: 'a_430392_beac4c1515da4576acf6cb9c5340b40c', + impid: '3cf96fd26ed4c5', + price: 1.0099999904632568, + nurl: 'http://localhost/rtb/impression?bannerid=220957&campaignid=3890&rtb_tid=5bc0e68b-3492-448d-a6f9-26fa3fd0b646&rpid=1295&seatid=seat1&zoneid=430392&cb=62735099&tid=a_430392_beac4c1515da4576acf6cb9c5340b40c', + adm: 'yo a creative', + crid: 'cridprebidrtb', + w: 300, + h: 250 }, ] } ], - 'ext': { - 'iid': 13487408, + ext: { + iid: 13487408, sync: { pixels: [ { @@ -683,20 +653,19 @@ describe('sovrnBidAdapter', function() { } } }, - 'headers': {} + headers: {} } - ]; + ] it('should return if iid present on server response & iframe syncs enabled', function() { const expectedReturnStatement = { - 'type': 'iframe', - 'url': 'https://ap.lijit.com/beacon?informer=13487408', + type: 'iframe', + url: 'https://ap.lijit.com/beacon?informer=13487408', } + const returnStatement = spec.getUserSyncs(syncOptions, serverResponse) - const returnStatement = spec.getUserSyncs(syncOptions, serverResponse); - - expect(returnStatement[0]).to.deep.equal(expectedReturnStatement); - }); + expect(returnStatement[0]).to.deep.equal(expectedReturnStatement) + }) it('should include gdpr consent string if present', function() { const gdprConsent = { @@ -704,64 +673,63 @@ describe('sovrnBidAdapter', function() { consentString: 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==' } const expectedReturnStatement = { - 'type': 'iframe', - 'url': `https://ap.lijit.com/beacon?gdpr_consent=${gdprConsent.consentString}&informer=13487408`, + type: 'iframe', + url: `https://ap.lijit.com/beacon?gdpr_consent=${gdprConsent.consentString}&informer=13487408`, } - const returnStatement = spec.getUserSyncs(syncOptions, serverResponse, gdprConsent, ''); + const returnStatement = spec.getUserSyncs(syncOptions, serverResponse, gdprConsent, '') - expect(returnStatement[0]).to.deep.equal(expectedReturnStatement); - }); + expect(returnStatement[0]).to.deep.equal(expectedReturnStatement) + }) it('should include us privacy string if present', function() { - const uspString = '1NYN'; + const uspString = '1NYN' const expectedReturnStatement = { - 'type': 'iframe', - 'url': `https://ap.lijit.com/beacon?us_privacy=${uspString}&informer=13487408`, + type: 'iframe', + url: `https://ap.lijit.com/beacon?us_privacy=${uspString}&informer=13487408`, } - const returnStatement = spec.getUserSyncs(syncOptions, serverResponse, null, uspString); + const returnStatement = spec.getUserSyncs(syncOptions, serverResponse, null, uspString) - expect(returnStatement[0]).to.deep.equal(expectedReturnStatement); - }); + expect(returnStatement[0]).to.deep.equal(expectedReturnStatement) + }) it('should include all privacy strings if present', function() { const gdprConsent = { gdprApplies: 1, consentString: 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==' } - const uspString = '1NYN'; + const uspString = '1NYN' const expectedReturnStatement = { - 'type': 'iframe', - 'url': `https://ap.lijit.com/beacon?gdpr_consent=${gdprConsent.consentString}&us_privacy=${uspString}&informer=13487408`, + type: 'iframe', + url: `https://ap.lijit.com/beacon?gdpr_consent=${gdprConsent.consentString}&us_privacy=${uspString}&informer=13487408`, } const returnStatement = spec.getUserSyncs(syncOptions, serverResponse, gdprConsent, uspString) expect(returnStatement[0]).to.deep.equal(expectedReturnStatement) - }); + }) it('should not return if iid missing on server response', function() { - const returnStatement = spec.getUserSyncs(syncOptions, []); + const returnStatement = spec.getUserSyncs(syncOptions, []) - expect(returnStatement).to.be.empty; - }); + expect(returnStatement).to.be.empty + }) it('should not return if iframe syncs disabled', function() { - const returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse); + const returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse) - expect(returnStatement).to.be.empty; - }); + expect(returnStatement).to.be.empty + }) it('should include pixel syncs', function() { const pixelEnabledOptions = { iframeEnabled: false, pixelEnabled: true } - const otherResponce = { ...serverResponse, - 'body': { + body: { ...serverResponse.body, - 'ext': { - 'iid': 13487408, + ext: { + iid: 13487408, sync: { pixels: [ { @@ -778,33 +746,33 @@ describe('sovrnBidAdapter', function() { const returnStatement = spec.getUserSyncs(pixelEnabledOptions, [...serverResponse, otherResponce]) - expect(returnStatement.length).to.equal(4); + expect(returnStatement.length).to.equal(4) expect(returnStatement).to.deep.include.members([ { type: 'image', url: 'http://idprovider1.com' }, { type: 'image', url: 'http://idprovider2.com' }, { type: 'image', url: 'http://idprovider3.com' }, { type: 'image', url: 'http://idprovider4.com' } - ]); + ]) }) }) describe('prebid 3 upgrade', function() { const bidRequest = { ...baseBidRequest, - 'params': { - 'tagid': '403370' + params: { + tagid: '403370' }, - 'mediaTypes': { - 'banner': { - 'sizes': [ + mediaTypes: { + banner: { + sizes: [ [300, 250], [300, 600] ] } }, - }; - const request = spec.buildRequests([bidRequest], baseBidderRequest); - const payload = JSON.parse(request.data); + } + const request = spec.buildRequests([bidRequest], baseBidderRequest) + const payload = JSON.parse(request.data) it('gets sizes from mediaTypes.banner', function() { expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]) @@ -813,8 +781,8 @@ describe('sovrnBidAdapter', function() { }) it('gets correct site info', function() { - expect(payload.site.page).to.equal('http://example.com/page.html'); - expect(payload.site.domain).to.equal('example.com'); + expect(payload.site.page).to.equal('http://example.com/page.html') + expect(payload.site.domain).to.equal('example.com') }) }) }) diff --git a/test/spec/modules/spotxBidAdapter_spec.js b/test/spec/modules/spotxBidAdapter_spec.js index d536976092b..2db8a1c9d2c 100644 --- a/test/spec/modules/spotxBidAdapter_spec.js +++ b/test/spec/modules/spotxBidAdapter_spec.js @@ -403,42 +403,6 @@ describe('the spotx adapter', function () { expect(request.data.ext.wrap_response).to.equal(0); config.getConfig.restore(); }); - - it('should pass price floor in USD from the floors module if available', function () { - var request; - - bid.getFloor = function () { - return { currency: 'USD', floor: 3 }; - } - - bid.params.price_floor = 2; - - request = spec.buildRequests([bid], bidRequestObj)[0]; - - expect(request.data.imp.bidfloor).to.equal(3); - }); - - it('should not pass price floor if price floors module gives a non-USD currency', function () { - var request; - - bid.getFloor = function () { - return { currency: 'EUR', floor: 3 }; - } - - request = spec.buildRequests([bid], bidRequestObj)[0]; - - expect(request.data.imp.bidfloor).to.be.undefined; - }); - - it('if floors module is not available, should pass price floor from price_floor param if available', function () { - var request; - - bid.params.price_floor = 2; - - request = spec.buildRequests([bid], bidRequestObj)[0]; - - expect(request.data.imp.bidfloor).to.equal(2); - }); }); describe('interpretResponse', function() { diff --git a/test/spec/modules/sspBCBidAdapter_spec.js b/test/spec/modules/sspBCBidAdapter_spec.js index a0c4837bb51..ae27cf8deea 100644 --- a/test/spec/modules/sspBCBidAdapter_spec.js +++ b/test/spec/modules/sspBCBidAdapter_spec.js @@ -40,6 +40,13 @@ describe('SSPBC adapter', function () { bidderRequestId, bidId: auctionId + '1', transactionId, + ortb2Imp: { + ext: { + data: { + pbadslot: 'test_wideboard' + } + } + } }, { adUnitCode: 'test_rectangle', @@ -62,85 +69,46 @@ describe('SSPBC adapter', function () { bidderRequestId, bidId: auctionId + '2', transactionId, - } - ]; - const bid_OneCode = { - adUnitCode: 'test_wideboard', + }, + { + adUnitCode: 'test_rectangle_2', bidder: BIDDER_CODE, mediaTypes: { banner: { sizes: [ - [728, 90], - [750, 100], - [750, 200] + [300, 250] ] } }, sizes: [ - [728, 90], - [750, 100], - [750, 200] + [300, 250] ], - auctionId, - bidderRequestId, - bidId: auctionId + '1', - transactionId, - }; - const bid_native = { - adUnitCode: 'test_native', - bidder: BIDDER_CODE, - mediaTypes: { - native: { - image: { - required: true, - sizes: [150, 50], - }, - title: { - required: true, - len: 80 - }, - sponsoredBy: { - required: true, - }, - clickUrl: { - required: true, - }, - privacyLink: { - required: false, - }, - body: { - required: true, - }, - icon: { - required: true, - sizes: [50, 50] - } - } + params: { + id: '011', + siteId: '8816', }, - sizes: [ - [1, 1], - ], auctionId, bidderRequestId, - bidId: auctionId + '1', + bidId: auctionId + '3', transactionId, - }; - const bid_video = { - adUnitCode: 'test_video', + } + ]; + const bid_OneCode = { + adUnitCode: 'test_wideboard', bidder: BIDDER_CODE, mediaTypes: { - video: { - context: 'instream', - playerSize: [[640, 480]], - mimes: ['video/mp4', 'video/x-ms-wmv', 'video/webm', 'video/3gpp', 'application/javascript'], - protocols: [2, 3, 5, 6], - api: [2], - maxduration: 30, - linearity: 1 + banner: { + sizes: [ + [728, 90], + [750, 100], + [750, 200] + ] } }, sizes: [ - [640, 480], + [728, 90], + [750, 100], + [750, 200] ], auctionId, bidderRequestId, @@ -225,30 +193,6 @@ describe('SSPBC adapter', function () { stack: ['https://test.site.pl/'], } }; - const bidRequestNative = { - auctionId, - bidderCode: BIDDER_CODE, - bidderRequestId, - bids: [bid_native], - gdprConsent, - refererInfo: { - reachedTop: true, - referer: 'https://test.site.pl/', - stack: ['https://test.site.pl/'], - } - }; - const bidRequestVideo = { - auctionId, - bidderCode: BIDDER_CODE, - bidderRequestId, - bids: [bid_video], - gdprConsent, - refererInfo: { - reachedTop: true, - referer: 'https://test.site.pl/', - stack: ['https://test.site.pl/'], - } - }; const bidRequestOneCode = { auctionId, bidderCode: BIDDER_CODE, @@ -320,6 +264,21 @@ describe('SSPBC adapter', function () { }], 'seat': 'dsp2', 'group': 0 + }, { + 'bid': [{ + 'id': '2d766853-ea07-4529-8299-5f0ebaddfaza', + 'impid': '011', + 'siteid': '8816', + 'slotid': '011', + 'price': 2, + 'adm': 'AD CODE 3', + 'cid': '57745', + 'crid': '858253', + 'w': 300, + 'h': 250 + }], + 'seat': 'dsp3', + 'group': 0 }], 'cur': 'PLN' } @@ -376,58 +335,6 @@ describe('SSPBC adapter', function () { 'cur': 'PLN' } }; - const serverResponseVideo = { - 'body': { - 'id': auctionId, - 'seatbid': [{ - 'bid': [{ - 'id': '3347324c-6889-46d2-a800-ae78a5214c06', - 'impid': 'bidid-' + auctionId + '1', - 'price': 1, - 'adid': 'lxHWkB7OnZeso3QiN1N4', - 'nurl': '', - 'adm': 'adnxs', - 'adomain': ['adomain.pl'], - 'cid': 'BZ4gAg21T5nNtxlUCDSW', - 'crid': 'lxHWkB7OnZeso3QiN1N4', - 'w': 640, - 'h': 480, - 'ext': { - 'siteid': '8816', - 'slotid': '150', - }, - }], - 'seat': 'dsp1', - 'group': 0 - }], - 'cur': 'PLN' - } - }; - const serverResponseNative = { - 'body': { - 'id': auctionId, - 'seatbid': [{ - 'bid': [{ - 'id': '3347324c-6889-46d2-a800-ae78a5214c06', - 'impid': 'bidid-' + auctionId + '1', - 'price': 1, - 'adid': 'lxHWkB7OnZeso3QiN1N4', - 'nurl': '', - 'adm': '{\"native\":{\"assets\":[{\"id\":3,\"img\":{\"url\":\"native_image\",\"w\":300,\"h\":150}},{\"id\":2,\"img\":{\"url\":\"native_icon\",\"w\":50,\"h\":50}},{\"id\":0,\"title\":{\"text\":\"native_title\"}},{\"id\":5,\"data\":{\"value\":\"native adomain\"}},{\"id\":4,\"data\":{\"value\":\"native_text\"}}],\"link\":{\"url\":\"native_url\"},\"imptrackers\":[\"native_tracker\"]}}', - 'adomain': ['adomain.pl'], - 'cid': 'BZ4gAg21T5nNtxlUCDSW', - 'crid': 'lxHWkB7OnZeso3QiN1N4', - 'ext': { - 'siteid': '8816', - 'slotid': '80', - }, - }], - 'seat': 'dsp1', - 'group': 0 - }], - 'cur': 'PLN' - } - }; const emptyResponse = { 'body': { 'id': auctionId, @@ -438,20 +345,14 @@ describe('SSPBC adapter', function () { bids, bids_test, bids_timeouted, - bid_native, - bid_video, bidRequest, bidRequestOneCode, bidRequestSingle, - bidRequestNative, - bidRequestVideo, bidRequestTest, bidRequestTestNoGDPR, serverResponse, serverResponseOneCode, serverResponseSingle, - serverResponseVideo, - serverResponseNative, emptyResponse }; }; @@ -476,15 +377,14 @@ describe('SSPBC adapter', function () { }); describe('buildRequests', function () { - const { bids, bid_native, bid_video, bidRequest, bidRequestSingle, bidRequestNative, bidRequestVideo } = prepareTestData(); + const { bids, bidRequest, bidRequestSingle } = prepareTestData(); const request = spec.buildRequests(bids, bidRequest); const requestSingle = spec.buildRequests([bids[0]], bidRequestSingle); - const requestNative = spec.buildRequests([bid_native], bidRequestNative); - const requestVideo = spec.buildRequests([bid_video], bidRequestVideo); const payload = request ? JSON.parse(request.data) : { site: false, imp: false }; - const payloadSingle = requestSingle ? JSON.parse(requestSingle.data) : { site: false, imp: false }; - const payloadNative = requestNative ? JSON.parse(requestNative.data) : { site: false, imp: false }; - const payloadVideo = requestVideo ? JSON.parse(requestVideo.data) : { site: false, imp: false }; + const payloadSingle = request ? JSON.parse(requestSingle.data) : { site: false, imp: false }; + const payloadExt0 = payload.imp ? payload.imp[0].ext : {}; + const payloadExt1 = payload.imp ? payload.imp[1].ext : {}; + const payloadExt2 = payload.imp ? payload.imp[2].ext : {}; it('should send bid request to endpoint via POST', function () { expect(request.url).to.contain(BIDDER_URL); @@ -501,6 +401,17 @@ describe('SSPBC adapter', function () { expect(payloadSingle.imp.length).to.equal(1); }); + it('should add first party data (pbslot)', function () { + expect(payloadExt0.data).to.be.an('object').and.to.have.property('pbadslot'); + }); + + it('should add maximum size of adunit, and how many times this size has been requested (pbsize)', function () { + expect(payloadExt0.data).to.be.an('object').and.to.have.property('pbsize'); + expect(payloadExt0.data.pbsize).to.equal('750x200_1'); + expect(payloadExt1.data.pbsize).to.equal('300x250_1'); + expect(payloadExt2.data.pbsize).to.equal('300x250_2'); + }); + it('should save bidder request data', function () { expect(request.bidderRequest).to.deep.equal(bidRequest); }); @@ -514,82 +425,16 @@ describe('SSPBC adapter', function () { }); it('should send gdpr data', function () { - expect(payload.regs).to.be.an('object').and.to.have.property('gdpr', 1); - expect(payload.user).to.be.an('object').and.to.have.property('consent', bidRequest.gdprConsent.consentString); - }); - - it('should send net info and pvid', function () { - expect(payload.user).to.be.an('object').and.to.have.property('data').that.is.an('array'); - - const userData = payload.user.data; - expect(userData.length).to.equal(2); - - const netInfo = userData[0]; - expect(netInfo.id).to.equal('12'); - expect(netInfo.name).to.equal('NetInfo'); - expect(netInfo).to.have.property('segment').that.is.an('array'); - - const pvid = userData[1]; - expect(pvid.id).to.equal('7'); - expect(pvid.name).to.equal('pvid'); - expect(pvid).to.have.property('segment').that.is.an('array'); - expect(pvid.segment[0]).to.have.property('value'); - }); - - it('pvid should be constant on a single page view', function () { - const userData1 = payload.user.data; - const userData2 = payloadNative.user.data; - const pvid1 = userData1[1]; - const pvid2 = userData2[1]; - - expect(pvid1.segment[0].value).to.equal(pvid2.segment[0].value); - }); - - it('should build correct native payload', function () { - const nativeAssets = payloadNative.imp && payloadNative.imp[0].native.request; - - expect(payloadNative.imp.length).to.equal(1); - expect(nativeAssets).to.contain('{"id":0,"required":true,"title":{"len":80}}'); - expect(nativeAssets).to.contain('{"id":2,"required":true,"img":{"type":1,"w":50,"h":50}}'); - expect(nativeAssets).to.contain('{"id":3,"required":true,"img":{"type":3,"w":150,"h":50}}'); - expect(nativeAssets).to.contain('{"id":4,"required":true,"data":{"type":2}'); - expect(nativeAssets).to.contain('{"id":5,"required":true,"data":{"type":1}'); - }); - - it('should build correct video payload', function () { - const videoAssets = payloadVideo.imp && payloadVideo.imp[0].video; - - expect(payloadVideo.imp.length).to.equal(1); - expect(videoAssets).to.have.property('w').that.equals(640); - expect(videoAssets).to.have.property('h').that.equals(480); - expect(videoAssets).to.have.property('context').that.equals('instream'); - expect(videoAssets).to.have.property('maxduration').that.equals(30); - expect(videoAssets).to.have.property('linearity').that.equals(1); - expect(videoAssets).to.have.property('mimes').that.is.an('array'); - expect(videoAssets).to.have.property('protocols').that.is.an('array'); - expect(videoAssets).to.have.property('api').that.is.an('array'); - }); - - it('should create auxilary placement identifier (size_numUsed), that is constant for a given adUnit', function () { - const extAssets1 = payload.imp && payload.imp[0].ext.data; - const extAssets2 = payloadSingle.imp && payloadSingle.imp[0].ext.data; - - /* - note that payload comes from first, and payloadSingle from second auction in the test run - also, since both have same adUnitName, value of pbsize property should be the same - */ - expect(extAssets1).to.have.property('pbsize').that.equals('750x200_1') - expect(extAssets2).to.have.property('pbsize').that.equals('750x200_1') + expect(payload.regs).to.be.an('object').and.to.have.property('[ortb_extensions.gdpr]', 1); + expect(payload.user).to.be.an('object').and.to.have.property('[ortb_extensions.consent]', bidRequest.gdprConsent.consentString); }); }); describe('interpretResponse', function () { - const { bid_OneCode, bid_video, bid_native, bids, emptyResponse, serverResponse, serverResponseOneCode, serverResponseSingle, serverResponseVideo, serverResponseNative, bidRequest, bidRequestOneCode, bidRequestSingle, bidRequestVideo, bidRequestNative } = prepareTestData(); + const { bid_OneCode, bids, emptyResponse, serverResponse, serverResponseOneCode, serverResponseSingle, bidRequest, bidRequestOneCode, bidRequestSingle } = prepareTestData(); const request = spec.buildRequests(bids, bidRequest); const requestSingle = spec.buildRequests([bids[0]], bidRequestSingle); const requestOneCode = spec.buildRequests([bid_OneCode], bidRequestOneCode); - const requestVideo = spec.buildRequests([bid_video], bidRequestVideo); - const requestNative = spec.buildRequests([bid_native], bidRequestNative); it('should handle nobid responses', function () { let result = spec.interpretResponse(emptyResponse, request); @@ -631,30 +476,7 @@ describe('SSPBC adapter', function () { expect(adcode).to.contain('window.mcad'); expect(adcode).to.contain('window.gdpr'); expect(adcode).to.contain('window.page'); - }); - - it('should create a correct video bid', function () { - let resultVideo = spec.interpretResponse(serverResponseVideo, requestVideo); - - expect(resultVideo.length).to.equal(1); - - let videoBid = resultVideo[0]; - expect(videoBid).to.have.keys('adType', 'bidderCode', 'cpm', 'creativeId', 'currency', 'width', 'height', 'meta', 'mediaType', 'netRevenue', 'requestId', 'ttl', 'vastContent', 'vastXml'); - expect(videoBid.adType).to.equal('instream'); - expect(videoBid.mediaType).to.equal('video'); - expect(videoBid.vastXml).to.match(/^<\?xml.*<\/VAST>$/); - expect(videoBid.vastContent).to.match(/^<\?xml.*<\/VAST>$/); - }); - - it('should create a correct native bid', function () { - let resultNative = spec.interpretResponse(serverResponseNative, requestNative); - - expect(resultNative.length).to.equal(1); - - let nativeBid = resultNative[0]; - expect(nativeBid).to.have.keys('bidderCode', 'cpm', 'creativeId', 'currency', 'width', 'height', 'meta', 'mediaType', 'netRevenue', 'requestId', 'ttl', 'native'); - expect(nativeBid.native).to.have.keys('image', 'icon', 'title', 'sponsoredBy', 'body', 'clickUrl', 'impressionTrackers', 'javascriptTrackers'); - }); + }) }); describe('getUserSyncs', function () { @@ -668,8 +490,8 @@ describe('SSPBC adapter', function () { }); it('should send no syncs, if frame sync is not allowed', function () { - expect(syncResultImage).to.have.length(0); ; - expect(syncResultNone).to.have.length(0); ; + expect(syncResultImage).to.be.undefined; + expect(syncResultNone).to.be.undefined; }); }); @@ -686,7 +508,7 @@ describe('SSPBC adapter', function () { let notificationPayload = spec.onBidWon(bid); expect(notificationPayload).to.have.property('event').that.equals('bidWon'); expect(notificationPayload).to.have.property('requestId').that.equals(bid.auctionId); - expect(notificationPayload).to.have.property('tagid').that.deep.equals([bid.adUnitCode]); + expect(notificationPayload).to.have.property('adUnit').that.deep.equals([bid.adUnitCode]); expect(notificationPayload).to.have.property('siteId').that.is.an('array'); expect(notificationPayload).to.have.property('slotId').that.is.an('array'); }); @@ -707,7 +529,7 @@ describe('SSPBC adapter', function () { expect(notificationPayload).to.have.property('event').that.equals('timeout'); expect(notificationPayload).to.have.property('requestId').that.equals(bids_timeouted[0].auctionId); - expect(notificationPayload).to.have.property('tagid').that.deep.equals([bids_timeouted[0].adUnitCode, bids_timeouted[1].adUnitCode]); + expect(notificationPayload).to.have.property('adUnit').that.deep.equals([bids_timeouted[0].adUnitCode, bids_timeouted[1].adUnitCode]); }); }); }); diff --git a/test/spec/modules/stroeerCoreBidAdapter_spec.js b/test/spec/modules/stroeerCoreBidAdapter_spec.js index e723523de31..6f24da85cfe 100644 --- a/test/spec/modules/stroeerCoreBidAdapter_spec.js +++ b/test/spec/modules/stroeerCoreBidAdapter_spec.js @@ -2,7 +2,7 @@ import {assert} from 'chai'; import {spec} from 'modules/stroeerCoreBidAdapter.js'; import * as utils from 'src/utils.js'; import {BANNER, VIDEO} from '../../../src/mediaTypes.js'; -import {find} from 'src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; describe('stroeerCore bid adapter', function () { let sandbox; diff --git a/test/spec/modules/sublimeBidAdapter_spec.js b/test/spec/modules/sublimeBidAdapter_spec.js index e687ff0970f..5c72c6c4dc5 100644 --- a/test/spec/modules/sublimeBidAdapter_spec.js +++ b/test/spec/modules/sublimeBidAdapter_spec.js @@ -1,177 +1,11 @@ import { expect } from 'chai'; import { spec } from 'modules/sublimeBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; -const sinon = require('sinon'); - -const utils = require('src/utils'); - -const USER_AGENT = { - // UNKOWN - 'Opera/9.80 (S60; SymbOS; Opera Mobi/1209; U; sk) Presto/2.5.28 Version/10.1': { - type: 'desktop', os: { name: '', version: 0 }, browser: { name: '', version: 0 }, - }, - 'Opera/12.02 (Android 4.1; Linux; Opera Mobi/ADR-1111101157; U; en-US) Presto/2.9.201 Version/12.02': { - type: 'tablet', os: { name: 'android', version: 4.1 }, browser: { name: '', version: 0 }, - }, - - // MOBILES - // Android Mobile User Agents - 'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)': { - type: 'mobile', os: { name: 'windowsPhone', version: 7.5 }, browser: { name: 'Internet Explorer', version: 9 }, - }, - 'Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; HTC Vision Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1': { - type: 'mobile', os: { name: 'android', version: 2.3 }, browser: { name: 'Safari', version: 4 }, - }, - 'Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30': { - type: 'mobile', os: { name: 'android', version: 4 }, browser: { name: 'Safari', version: 4 }, - }, - 'Mozilla/5.0 (Linux; U; Android 4.4.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30': { - type: 'mobile', os: { name: 'android', version: 4.4 }, browser: { name: 'Safari', version: 4 }, - }, - 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Mobile Safari/537.36': { - type: 'mobile', os: { name: 'android', version: 6 }, browser: { name: 'Chrome', version: 55 }, - }, - 'Mozilla/5.0 (Linux; Android 7.0; SM-G892A Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Mobile Safari/537.36': { - type: 'mobile', os: { name: 'android', version: 7 }, browser: { name: 'Chrome', version: 60 }, - }, - 'Mozilla/5.0 (Linux; Android 7.0; SM-G930VC Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.83 Mobile Safari/537.36': { - type: 'mobile', os: { name: 'android', version: 7 }, browser: { name: 'Chrome', version: 58 }, - }, - 'Mozilla/5.0 (Linux; Android 6.0.1; SM-G935S Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/55.0.2883.91 Mobile Safari/537.36': { - type: 'mobile', os: { name: 'android', version: 6 }, browser: { name: 'Chrome', version: 55 }, - }, - 'Mozilla/5.0 (Linux; Android 6.0.1; SM-G920V Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36': { - type: 'mobile', os: { name: 'android', version: 6 }, browser: { name: 'Chrome', version: 52 }, - }, - 'Mozilla/5.0 (Linux; Android 5.1.1; SM-G928X Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36': { - type: 'mobile', os: { name: 'android', version: 5.1 }, browser: { name: 'Chrome', version: 47 }, - }, - 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 6P Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36': { - type: 'mobile', os: { name: 'android', version: 6 }, browser: { name: 'Chrome', version: 47 }, - }, - 'Mozilla/5.0 (Linux; Android 7.1.1; G8231 Build/41.2.A.0.219; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/59.0.3071.125 Mobile Safari/537.36': { - type: 'mobile', os: { name: 'android', version: 7.1 }, browser: { name: 'Chrome', version: 59 }, - }, - 'Mozilla/5.0 (Linux; Android 6.0.1; E6653 Build/32.2.A.0.253) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36': { - type: 'mobile', os: { name: 'android', version: 6 }, browser: { name: 'Chrome', version: 52 }, - }, - 'Mozilla/5.0 (Linux; Android 6.0; HTC One X10 Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36': { - type: 'mobile', os: { name: 'android', version: 6 }, browser: { name: 'Chrome', version: 61 }, - }, - 'Mozilla/5.0 (Linux; Android 6.0; HTC One M9 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.3': { - type: 'mobile', os: { name: 'android', version: 6 }, browser: { name: 'Chrome', version: 52 }, - }, - 'Mozilla/5.0 (Linux; U; 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML like Gecko) Version/4.0 Mobile Safari/534.30': { - type: 'mobile', os: { name: '', version: 0 }, browser: { name: 'Safari', version: 4 }, - }, - // iPhone User Agents - 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1': { - type: 'mobile', os: { name: 'iOS', version: 11 }, browser: { name: 'Safari', version: 11 }, - }, - 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1': { - type: 'mobile', os: { name: 'iOS', version: 11 }, browser: { name: 'Safari', version: 11 }, - }, - 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5370a Safari/604.1': { - type: 'mobile', os: { name: 'iOS', version: 11 }, browser: { name: 'Safari', version: 11 }, - }, - 'Mozilla/5.0 (iPhone9,3; U; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1': { - type: 'mobile', os: { name: 'iOS', version: 10 }, browser: { name: 'Safari', version: 10 }, - }, - 'Mozilla/5.0 (iPhone9,4; U; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1': { - type: 'mobile', os: { name: 'iOS', version: 10 }, browser: { name: 'Safari', version: 10 }, - }, - 'Mozilla/5.0 (Apple-iPhone7C2/1202.466; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543 Safari/419.3': { - type: 'mobile', os: { name: '', version: 0 }, browser: { name: 'Safari', version: 3 }, - }, - 'Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; Microsoft; RM-1152) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Mobile Safari/537.36 Edge/15.15254': { - type: 'mobile', os: { name: 'windowsPhone', version: 10 }, browser: { name: 'Edge', version: 15.15254 }, - }, - 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; RM-1127_16056) AppleWebKit/537.36(KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Edge/12.10536': { - type: 'mobile', os: { name: 'windowsPhone', version: 10 }, browser: { name: 'Edge', version: 12.10536 }, - }, - 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.1058': { - type: 'mobile', os: { name: 'windowsPhone', version: 10 }, browser: { name: 'Edge', version: 13.1058 }, - }, - 'Mozilla/5.0 (Linux; 7.0; SM-G892A Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Mobile Safari/537.36': { - type: 'mobile', os: { name: '', version: 0 }, browser: { name: 'Chrome', version: 60 }, - }, - 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1': { - type: 'mobile', os: { name: 'iOS', version: 11.3 }, browser: { name: 'Safari', version: 11 }, - }, - 'Mozilla/5.0 (Linux; Android 6.0.1; SM-G903F Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Mobile Safari/537.36 ACHEETAHI/1': { - type: 'mobile', os: { name: 'android', version: 6 }, browser: { name: 'Chrome', version: 44 }, - }, - - // TABLETS - 'Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-T550 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.3 Chrome/38.0.2125.102 Safari/537.36': { - type: 'tablet', os: { name: 'android', version: 5 }, browser: { name: 'Chrome', version: 38 }, - }, - 'Mozilla/5.0 (Linux; Android 5.1.1; SHIELD Tablet Build/LMY48C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Safari/537.36': { - type: 'tablet', os: { name: 'android', version: 5.1 }, browser: { name: 'Chrome', version: 52 }, - }, - 'Mozilla/5.0 (Linux; Android 7.0; Pixel C Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/52.0.2743.98 Safari/537.36': { - type: 'tablet', os: { name: 'android', version: 7 }, browser: { name: 'Chrome', version: 52 }, - }, - 'Mozilla/5.0 (Linux; Android 6.0.1; SGP771 Build/32.2.A.0.253; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/52.0.2743.98 Safari/537.36': { - type: 'tablet', os: { name: 'android', version: 6 }, browser: { name: 'Chrome', version: 52 }, - }, - 'Mozilla/5.0 (Linux; Android 6.0.1; SHIELD Tablet K1 Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/55.0.2883.91 Safari/537.36': { - type: 'tablet', os: { name: 'android', version: 6 }, browser: { name: 'Chrome', version: 55 }, - }, - 'Mozilla/5.0 (Linux; Android 7.0; SM-T827R4 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.116 Safari/537.36': { - type: 'tablet', os: { name: 'android', version: 7 }, browser: { name: 'Chrome', version: 60 }, - }, - 'Mozilla/5.0 (Linux; Android 4.4.3; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/47.1.79 like Chrome/47.0.2526.80 Safari/537.36': { - type: 'tablet', os: { name: 'android', version: 4.4 }, browser: { name: 'Chrome', version: 47 }, - }, - 'Mozilla/5.0 (Linux; Android 5.0.2; LG-V410/V41020c Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/34.0.1847.118 Safari/537.36': { - type: 'tablet', os: { name: 'android', version: 5 }, browser: { name: 'Chrome', version: 34 }, - }, - 'Mozilla/5.0 (iPad; CPU OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13F69 Safari/601.1': { - type: 'tablet', os: { name: 'iOS', version: 9.3 }, browser: { name: 'Safari', version: 9 }, - }, - 'Mozilla/5.0 (iPad; CPU OS 11_0_2 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A421 Safari/604.1': { - type: 'tablet', os: { name: 'iOS', version: 11 }, browser: { name: 'Safari', version: 11 }, - }, - 'Mozilla/5.0 (Android 7.0; Tablet; rv:62.0) Gecko/62.0 Firefox/62.0': { - type: 'tablet', os: { name: 'android', version: 7 }, browser: { name: 'Firefox', version: 62 }, - }, - - // DESKTOP - 'Mozilla/ 5.0(Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari / 537.36': { - type: 'desktop', os: { name: 'Windows', version: 6.1 }, browser: { name: 'Chrome', version: 41 }, - }, - 'Mozilla/5.0 (hone; CPU one OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1': { - type: 'desktop', os: { name: '', version: 0 }, browser: { name: 'Safari', version: 11 }, - }, - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246': { - type: 'desktop', os: { name: 'Windows', version: 10 }, browser: { name: 'Edge', version: 12.246 }, - }, - 'Mozilla/5.0 (X11; CrOS x86_64 8172.45.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.64 Safari/537.36': { - type: 'desktop', os: { name: '', version: 0 }, browser: { name: 'Chrome', version: 51 }, - }, - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9': { - type: 'desktop', os: { name: 'Mac', version: 10.11 }, browser: { name: 'Safari', version: 9 }, - }, - 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36': { - type: 'desktop', os: { name: 'Windows', version: 6.1 }, browser: { name: 'Chrome', version: 47 }, - }, -}; -describe('Sublime Adapter', function () { - describe('detectDevice', function () { - it('should correctly detect device', function () { - const uaStub = sinon.stub(window.navigator, 'userAgent'); - - Object.keys(USER_AGENT).forEach(userAgent => { - const value = USER_AGENT[userAgent]; - uaStub.value(userAgent); - expect(spec.detectDevice()).to.equal(value.type.charAt(0)); - }); +let utils = require('src/utils'); - uaStub.restore(); - }) - }); +describe('Sublime Adapter', function () { + const adapter = newBidder(spec); describe('sendEvent', function () { let sandbox; @@ -208,98 +42,28 @@ describe('Sublime Adapter', function () { describe('inherited functions', function () { it('exists and is a function', function () { - const adapter = newBidder(spec); expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); describe('isBidRequestValid', function () { - let bid; - beforeEach(function () { - bid = { - bidder: 'sublime', - params: { - zoneId: 24549, - endpoint: '', - }, - }; - }) - - afterEach(function () { - delete window.sublime; - }) + const bid = { + bidder: 'sublime', + params: { + zoneId: 24549, + endpoint: '', + }, + }; it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when a valid notifyId is provided', function () { - bid.params.notifyId = 'f1514724-0922-4b45-a297-27531aeb829a'; - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when an invalid notifyId is provided', function () { - bid.params.notifyId = 'some_invalid_notify_id'; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - it('should return false when required params are not passed', function () { + const bid = Object.assign({}, bid); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - - it('should return false when the notifyId does not match sublime one', function () { - bid.params.notifyId = 'f1514724-0922-4b45-a297-27531aeb829a'; - window.sublime = { notifyId: '5c444a48-7713-4333-a895-44b1ae793417' }; - expect(spec.isBidRequestValid(bid)).to.equal(false); // FIX THIS - delete window.sublime; - }); - }); - - describe('getNotifyId', function () { - afterEach(function () { - delete window.sublime; - }); - - it('generates a notifyId (not in params, not in sublime)', function () { - const params = Object.freeze({}); - window.sublime = {}; - const notifyId = spec.getNotifyId(params); - expect(spec.isValidNotifyId(notifyId)).to.be.true; - expect(window.sublime.notifyId).to.equal(notifyId); - }); - - it('uses sublime notifyId (not in params, present in sublime)', function () { - const params = Object.freeze({}); - window.sublime = { notifyId: '5c444a48-7713-4333-a895-44b1ae793417' }; - const notifyId = spec.getNotifyId(params); - expect(notifyId).to.equal('5c444a48-7713-4333-a895-44b1ae793417'); - expect(window.sublime.notifyId).to.equal('5c444a48-7713-4333-a895-44b1ae793417'); - }); - - it('assigns notifyId from params to sublime (present in params, not in sublime)', function () { - const params = Object.freeze({ notifyId: 'f1514724-0922-4b45-a297-27531aeb829a' }); - window.sublime = {}; - const notifyId = spec.getNotifyId(params); - expect(notifyId).to.equal('f1514724-0922-4b45-a297-27531aeb829a'); - expect(window.sublime.notifyId).to.equal('f1514724-0922-4b45-a297-27531aeb829a'); - }); - - it('returns notifyId from params (same in params & in sublime)', function () { - const params = Object.freeze({ notifyId: 'f1514724-0922-4b45-a297-27531aeb829a' }); - window.sublime = { notifyId: 'f1514724-0922-4b45-a297-27531aeb829a' }; - const notifyId = spec.getNotifyId(params); - expect(notifyId).to.equal('f1514724-0922-4b45-a297-27531aeb829a'); - expect(window.sublime.notifyId).to.equal('f1514724-0922-4b45-a297-27531aeb829a'); - }); - - it('returns notifyId from params (present in params & in sublime, with mismatch)', function () { - const params = Object.freeze({ notifyId: 'f1514724-0922-4b45-a297-27531aeb829a' }); - window.sublime = { notifyId: '5c444a48-7713-4333-a895-44b1ae793417' }; - const notifyId = spec.getNotifyId(params); - expect(notifyId).to.equal('f1514724-0922-4b45-a297-27531aeb829a'); - expect(window.sublime.notifyId).to.equal('5c444a48-7713-4333-a895-44b1ae793417'); // did not change - }); }); describe('buildRequests', function () { @@ -312,8 +76,7 @@ describe('Sublime Adapter', function () { requestId: 'xyz654', params: { zoneId: 123, - callbackName: 'false', - notifyId: 'ea252d4f-93d9-4c2f-8cca-88cec3a0a347' + callbackName: 'false' } }, { bidder: 'sublime', @@ -338,32 +101,23 @@ describe('Sublime Adapter', function () { } }; + const request = spec.buildRequests(bidRequests, bidderRequest); + it('should have a post method', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); expect(request[0].method).to.equal('POST'); expect(request[1].method).to.equal('POST'); }); it('should contains a request id equals to the bid id', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); for (let i = 0; i < request.length; i = i + 1) { expect(JSON.parse(request[i].data).requestId).to.equal(bidRequests[i].bidId); } }); it('should have an url that contains bid keyword', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); expect(request[0].url).to.match(/bid/); expect(request[1].url).to.match(/bid/); }); - - it('should contains a request notifyId', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - for (let i = 0; i < request.length; i = i + 1) { - const { notifyId } = JSON.parse(request[i].data); - expect(spec.isValidNotifyId(notifyId)).to.be.true; - } - }); }); describe('buildRequests: default arguments', function () { @@ -378,8 +132,9 @@ describe('Sublime Adapter', function () { } }]; + const request = spec.buildRequests(bidRequests); + it('should have an url that match the default endpoint', function () { - const request = spec.buildRequests(bidRequests); expect(request[0].url).to.equal('https://pbjs.sskzlabs.com/bid'); }); }); @@ -412,7 +167,7 @@ describe('Sublime Adapter', function () { sspname: 'foo', netRevenue: true, ttl: 600, - pbav: '0.8.0', + pbav: '0.7.3', ad: '', }, ]; @@ -455,7 +210,7 @@ describe('Sublime Adapter', function () { netRevenue: true, ttl: 600, ad: '', - pbav: '0.8.0', + pbav: '0.7.3', sspname: 'sublime' }; @@ -508,7 +263,7 @@ describe('Sublime Adapter', function () { netRevenue: true, ttl: 600, ad: '', - pbav: '0.8.0', + pbav: '0.7.3', }; expect(result[0]).to.deep.equal(expectedResponse); @@ -604,7 +359,7 @@ describe('Sublime Adapter', function () { it('should set timeout value in state', function () { spec.onTimeout(timeoutData); - expect(spec.state).to.deep.include({ timeout: 1234 }); + expect(spec.state).to.deep.equal({ timeout: 1234, debug: false, notifyId: undefined, transactionId: undefined, zoneId: 123 }); }); afterEach(function () { diff --git a/test/spec/modules/synacormediaBidAdapter_spec.js b/test/spec/modules/synacormediaBidAdapter_spec.js index b9a02799219..5f3633ec311 100644 --- a/test/spec/modules/synacormediaBidAdapter_spec.js +++ b/test/spec/modules/synacormediaBidAdapter_spec.js @@ -244,13 +244,6 @@ describe('synacormediaBidAdapter ', function () { rtiPartner: 'TDID' } }] - }, - { - source: 'neustar.biz', - uids: [{ - id: 'neustar809-044-23njhwer3', - atype: 1 - }] } ]; @@ -996,7 +989,7 @@ describe('synacormediaBidAdapter ', function () { netRevenue: true, mediaType: 'video', ad: '\n\n\n\nSynacor Media Ad Server - 9999\nhttps://uat-net.technoratimedia.com/openrtb/tags?ID=QVVDVElPTl9JRD1lOTBhYWU1My1hZDkwLTRkNDEtYTQxMC1lZDY1MjIxMDc0ZGMmQVVDVElPTl9CSURfSUQ9MTEzMzkxMjgwMDE2OTIzMzd-OTk5OX4wJkFVQ1RJT05fU0VBVF9JRD05OTk5JkFVQ1RJT05fSU1QX0lEPXYyZGE3MzIyYjJkZjYxZi02NDB4NDgwJkFDVE9SX1JFRj1ha2thLnRjcDovL2F3cy1lYXN0MUBhZHMxMy5jYXAtdXNlMS5zeW5hY29yLmNvbToyNTUxL3VzZXIvJGNMYmZiIy0xOTk4NTIzNTk3JlNFQVRfSUQ9cHJlYmlk&AUCTION_PRICE=0.45\n\n\n', - ttl: 420, + ttl: 60, meta: { advertiserDomains: ['psacentral.org'] }, videoCacheKey: 'QVVDVElPTl9JRD1lOTBhYWU1My1hZDkwLTRkNDEtYTQxMC1lZDY1MjIxMDc0ZGMmQVVDVElPTl9CSURfSUQ9MTEzMzkxMjgwMDE2OTIzMzd-OTk5OX4wJkFVQ1RJT05fU0VBVF9JRD05OTk5JkFVQ1RJT05fSU1QX0lEPXYyZGE3MzIyYjJkZjYxZi02NDB4NDgwJkFDVE9SX1JFRj1ha2thLnRjcDovL2F3cy1lYXN0MUBhZHMxMy5jYXAtdXNlMS5zeW5hY29yLmNvbToyNTUxL3VzZXIvJGNMYmZiIy0xOTk4NTIzNTk3JlNFQVRfSUQ9cHJlYmlk', vastUrl: 'https://uat-net.technoratimedia.com/openrtb/tags?ID=QVVDVElPTl9JRD1lOTBhYWU1My1hZDkwLTRkNDEtYTQxMC1lZDY1MjIxMDc0ZGMmQVVDVElPTl9CSURfSUQ9MTEzMzkxMjgwMDE2OTIzMzd-OTk5OX4wJkFVQ1RJT05fU0VBVF9JRD05OTk5JkFVQ1RJT05fSU1QX0lEPXYyZGE3MzIyYjJkZjYxZi02NDB4NDgwJkFDVE9SX1JFRj1ha2thLnRjcDovL2F3cy1lYXN0MUBhZHMxMy5jYXAtdXNlMS5zeW5hY29yLmNvbToyNTUxL3VzZXIvJGNMYmZiIy0xOTk4NTIzNTk3JlNFQVRfSUQ9cHJlYmlk&AUCTION_PRICE=0.45' @@ -1017,7 +1010,7 @@ describe('synacormediaBidAdapter ', function () { netRevenue: true, mediaType: BANNER, ad: '', - ttl: 420 + ttl: 60 }); }); @@ -1039,7 +1032,7 @@ describe('synacormediaBidAdapter ', function () { netRevenue: true, mediaType: BANNER, ad: '', - ttl: 420 + ttl: 60 }); expect(resp[1]).to.eql({ @@ -1052,7 +1045,7 @@ describe('synacormediaBidAdapter ', function () { netRevenue: true, mediaType: BANNER, ad: '', - ttl: 420 + ttl: 60 }); }); @@ -1163,7 +1156,7 @@ describe('synacormediaBidAdapter ', function () { netRevenue: true, mediaType: 'video', ad: '\n\n\n\nSynacor Media Ad Server - 9999\nhttps://uat-net.technoratimedia.com/openrtb/tags?ID=QVVDVElPTl9JRD1lOTBhYWU1My1hZDkwLTRkNDEtYTQxMC1lZDY1MjIxMDc0ZGMmQVVDVElPTl9CSURfSUQ9MTEzMzkxMjgwMDE2OTIzMzd-OTk5OX4wJkFVQ1RJT05fU0VBVF9JRD05OTk5JkFVQ1RJT05fSU1QX0lEPXYyZGE3MzIyYjJkZjYxZi02NDB4NDgwJkFDVE9SX1JFRj1ha2thLnRjcDovL2F3cy1lYXN0MUBhZHMxMy5jYXAtdXNlMS5zeW5hY29yLmNvbToyNTUxL3VzZXIvJGNMYmZiIy0xOTk4NTIzNTk3JlNFQVRfSUQ9cHJlYmlk&AUCTION_PRICE=0.45\n\n\n', - ttl: 420, + ttl: 60, meta: { advertiserDomains: ['psacentral.org'] }, videoCacheKey: 'QVVDVElPTl9JRD1lOTBhYWU1My1hZDkwLTRkNDEtYTQxMC1lZDY1MjIxMDc0ZGMmQVVDVElPTl9CSURfSUQ9MTEzMzkxMjgwMDE2OTIzMzd-OTk5OX4wJkFVQ1RJT05fU0VBVF9JRD05OTk5JkFVQ1RJT05fSU1QX0lEPXYyZGE3MzIyYjJkZjYxZi02NDB4NDgwJkFDVE9SX1JFRj1ha2thLnRjcDovL2F3cy1lYXN0MUBhZHMxMy5jYXAtdXNlMS5zeW5hY29yLmNvbToyNTUxL3VzZXIvJGNMYmZiIy0xOTk4NTIzNTk3JlNFQVRfSUQ9cHJlYmlk', vastUrl: 'https://uat-net.technoratimedia.com/openrtb/tags?ID=QVVDVElPTl9JRD1lOTBhYWU1My1hZDkwLTRkNDEtYTQxMC1lZDY1MjIxMDc0ZGMmQVVDVElPTl9CSURfSUQ9MTEzMzkxMjgwMDE2OTIzMzd-OTk5OX4wJkFVQ1RJT05fU0VBVF9JRD05OTk5JkFVQ1RJT05fSU1QX0lEPXYyZGE3MzIyYjJkZjYxZi02NDB4NDgwJkFDVE9SX1JFRj1ha2thLnRjcDovL2F3cy1lYXN0MUBhZHMxMy5jYXAtdXNlMS5zeW5hY29yLmNvbToyNTUxL3VzZXIvJGNMYmZiIy0xOTk4NTIzNTk3JlNFQVRfSUQ9cHJlYmlk&AUCTION_PRICE=0.45' @@ -1216,63 +1209,9 @@ describe('synacormediaBidAdapter ', function () { netRevenue: true, mediaType: BANNER, ad: '', - ttl: 420 + ttl: 60 }); }); - - it('should return ttl equal to DEFAULT_TTL_MAX if bid.exp and bid.ext["imds.tv"].ttl are both undefined', function() { - const br = { ...bidResponse }; - serverResponse.body.seatbid[0].bid.push(br); - const resp = spec.interpretResponse(serverResponse, bidRequest); - expect(resp).to.be.an('array').to.have.lengthOf(1); - expect(resp[0]).to.have.property('ttl'); - expect(resp[0].ttl).to.equal(420); - }); - - it('should return ttl equal to bid.ext["imds.tv"].ttl if it is defined but bid.exp is undefined', function() { - let br = { ext: { 'imds.tv': { ttl: 4321 } }, ...bidResponse }; - serverResponse.body.seatbid[0].bid.push(br); - let resp = spec.interpretResponse(serverResponse, bidRequest); - expect(resp).to.be.an('array').to.have.lengthOf(1); - expect(resp[0]).to.have.property('ttl'); - expect(resp[0].ttl).to.equal(4321); - }); - - it('should return ttl equal to bid.exp if bid.exp is less than or equal to DEFAULT_TTL_MAX and bid.ext["imds.tv"].ttl is undefined', function() { - const br = { exp: 123, ...bidResponse }; - serverResponse.body.seatbid[0].bid.push(br); - const resp = spec.interpretResponse(serverResponse, bidRequest); - expect(resp).to.be.an('array').to.have.lengthOf(1); - expect(resp[0]).to.have.property('ttl'); - expect(resp[0].ttl).to.equal(123); - }); - - it('should return ttl equal to DEFAULT_TTL_MAX if bid.exp is greater than DEFAULT_TTL_MAX and bid.ext["imds.tv"].ttl is undefined', function() { - const br = { exp: 4321, ...bidResponse }; - serverResponse.body.seatbid[0].bid.push(br); - const resp = spec.interpretResponse(serverResponse, bidRequest); - expect(resp).to.be.an('array').to.have.lengthOf(1); - expect(resp[0]).to.have.property('ttl'); - expect(resp[0].ttl).to.equal(420); - }); - - it('should return ttl equal to bid.exp if bid.exp is less than or equal to bid.ext["imds.tv"].ttl', function() { - const br = { exp: 1234, ext: { 'imds.tv': { ttl: 4321 } }, ...bidResponse }; - serverResponse.body.seatbid[0].bid.push(br); - const resp = spec.interpretResponse(serverResponse, bidRequest); - expect(resp).to.be.an('array').to.have.lengthOf(1); - expect(resp[0]).to.have.property('ttl'); - expect(resp[0].ttl).to.equal(1234); - }); - - it('should return ttl equal to bid.ext["imds.tv"].ttl if bid.exp is greater than bid.ext["imds.tv"].ttl', function() { - const br = { exp: 4321, ext: { 'imds.tv': { ttl: 1234 } }, ...bidResponse }; - serverResponse.body.seatbid[0].bid.push(br); - const resp = spec.interpretResponse(serverResponse, bidRequest); - expect(resp).to.be.an('array').to.have.lengthOf(1); - expect(resp[0]).to.have.property('ttl'); - expect(resp[0].ttl).to.equal(1234); - }); }); describe('getUserSyncs', function () { it('should return a usersync when iframes is enabled', function () { @@ -1292,74 +1231,4 @@ describe('synacormediaBidAdapter ', function () { expect(usersyncs).to.be.an('array').that.is.empty; }); }); - - describe('Bid Requests with price module should use if available', function () { - let validVideoBidRequest = { - bidder: 'synacormedia', - params: { - bidfloor: '0.50', - seatId: 'prebid', - placementId: 'demo1', - pos: 1, - video: {} - }, - renderer: { - url: '../syncOutstreamPlayer.js' - }, - mediaTypes: { - video: { - playerSize: [[300, 250]], - context: 'outstream' - } - }, - adUnitCode: 'div-1', - transactionId: '0869f34e-090b-4b20-84ee-46ff41405a39', - sizes: [[300, 250]], - bidId: '22b3a2268d9f0e', - bidderRequestId: '1d195910597e13', - auctionId: '3375d336-2aea-4ee7-804c-6d26b621ad20', - src: 'client', - bidRequestsCount: 1, - bidderRequestsCount: 1, - bidderWinsCount: 0 - }; - - let validBannerBidRequest = { - bidId: '9876abcd', - sizes: [[300, 250]], - params: { - bidfloor: '0.50', - seatId: 'prebid', - placementId: '1234', - } - }; - - let bidderRequest = { - refererInfo: { - referer: 'http://localhost:9999/' - }, - bidderCode: 'synacormedia', - auctionId: 'f8a75621-d672-4cbb-9275-3db7d74fb110' - }; - - it('should return valid bidfloor using price module for banner/video impression', function () { - let bannerRequest = spec.buildRequests([validBannerBidRequest], bidderRequest); - let videoRequest = spec.buildRequests([validVideoBidRequest], bidderRequest); - - expect(bannerRequest.data.imp[0].bidfloor).to.equal(0.5); - expect(videoRequest.data.imp[0].bidfloor).to.equal(0.5); - - let priceModuleFloor = 3; - let floorResponse = { currency: 'USD', floor: priceModuleFloor }; - - validBannerBidRequest.getFloor = () => { return floorResponse; }; - validVideoBidRequest.getFloor = () => { return floorResponse; }; - - bannerRequest = spec.buildRequests([validBannerBidRequest], bidderRequest); - videoRequest = spec.buildRequests([validVideoBidRequest], bidderRequest); - - expect(bannerRequest.data.imp[0].bidfloor).to.equal(priceModuleFloor); - expect(videoRequest.data.imp[0].bidfloor).to.equal(priceModuleFloor); - }); - }); }); diff --git a/test/spec/modules/talkadsBidAdapter_spec.js b/test/spec/modules/talkadsBidAdapter_spec.js deleted file mode 100644 index c48808cbc15..00000000000 --- a/test/spec/modules/talkadsBidAdapter_spec.js +++ /dev/null @@ -1,233 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/talkadsBidAdapter.js'; -import {newBidder} from 'src/adapters/bidderFactory.js'; -import {config} from '../../../src/config'; -import {server} from '../../mocks/xhr'; - -describe('TalkAds adapter', function () { - const commonBidderRequest = { - refererInfo: { - referer: 'https://example.com/' - }, - timeout: 3000, - } - const commonBidRequest = { - bidder: 'talkads', - params: { - tag_id: 999999, - bidder_url: 'https://test.natexo-programmatic.com/tad/tag/prebid', - }, - bidId: '1a2b3c4d56e7f0', - auctionId: '12345678-1234-1a2b-3c4d-1a2b3c4d56e7', - transactionId: '4f68b713-04ba-4d7f-8df9-643bcdab5efb', - }; - const nativeBidRequestParams = { - nativeParams: {}, - }; - const bannerBidRequestParams = { - sizes: [[300, 250], [300, 600]], - }; - - /** - * isBidRequestValid - */ - describe('isBidRequestValid1', function() { - it('should fail when config is invalid', function () { - const bidRequest = { - ...commonBidRequest, - ...bannerBidRequestParams, - }; - bidRequest.params = Object.assign({}, bidRequest.params); - delete bidRequest.params; - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - }); // isBidRequestValid1 - describe('isBidRequestValid2', function() { - it('should fail when config is invalid', function () { - const bidRequest = { - ...commonBidRequest, - ...bannerBidRequestParams, - }; - bidRequest.params = Object.assign({}, bidRequest.params); - delete bidRequest.params.bidder_url; - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - }); // isBidRequestValid2 - describe('isBidRequestValid3', function() { - it('should fail when config is invalid', function () { - const bidRequest = { - ...commonBidRequest, - ...bannerBidRequestParams, - }; - bidRequest.params = Object.assign({}, bidRequest.params); - delete bidRequest.params.tag_id; - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - }); // isBidRequestValid3 - describe('isBidRequestValid4', function() { - let bidRequest = { - ...commonBidRequest, - ...bannerBidRequestParams, - }; - it('should succeed when a banner bid is valid', function () { - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - bidRequest = { - ...commonBidRequest, - ...nativeBidRequestParams, - }; - it('should succeed when a native bid is valid', function () { - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - }); // isBidRequestValid4 - - /** - * buildRequests - */ - describe('buildRequests1', function() { - let bidRequest = { - ...commonBidRequest, - ...bannerBidRequestParams, - }; - const loServerRequest = { - cur: 'EUR', - timeout: commonBidderRequest.timeout, - auction_id: commonBidRequest.auctionId, - transaction_id: commonBidRequest.transactionId, - bids: [{ id: 0, bid_id: commonBidRequest.bidId, type: 'banner', size: bannerBidRequestParams.sizes }], - gdpr: { applies: false, consent: false }, - }; - it('should generate a valid banner bid request', function () { - let laResponse = spec.buildRequests([bidRequest], commonBidderRequest); - expect(laResponse.method).to.equal('POST'); - expect(laResponse.url).to.equal('https://test.natexo-programmatic.com/tad/tag/prebid/999999'); - expect(laResponse.data).to.equal(JSON.stringify(loServerRequest)); - }); - }); // buildRequests1 - describe('buildRequests2', function() { - let bidRequest = { - ...commonBidRequest, - ...nativeBidRequestParams, - }; - const loServerRequest = { - cur: 'EUR', - timeout: commonBidderRequest.timeout, - auction_id: commonBidRequest.auctionId, - transaction_id: commonBidRequest.transactionId, - bids: [{ id: 0, bid_id: commonBidRequest.bidId, type: 'native', size: [] }], - gdpr: { applies: false, consent: false }, - }; - it('should generate a valid native bid request', function () { - let laResponse = spec.buildRequests([bidRequest], commonBidderRequest); - expect(laResponse.method).to.equal('POST'); - expect(laResponse.url).to.equal('https://test.natexo-programmatic.com/tad/tag/prebid/999999'); - expect(laResponse.data).to.equal(JSON.stringify(loServerRequest)); - }); - const bidderRequest = { - ...commonBidderRequest, - gdprConsent: { gdprApplies: true, consentString: 'yes' } - }; - const loServerRequest2 = { - ...loServerRequest, - gdpr: { applies: true, consent: 'yes' }, - }; - it('should generate a valid native bid request', function () { - let laResponse = spec.buildRequests([bidRequest], bidderRequest); - expect(laResponse.method).to.equal('POST'); - expect(laResponse.url).to.equal('https://test.natexo-programmatic.com/tad/tag/prebid/999999'); - expect(laResponse.data).to.equal(JSON.stringify(loServerRequest2)); - }); - }); // buildRequests2 - - /** - * interpretResponse - */ - describe('interpretResponse1', function() { - it('should return empty array if no valid bids', function () { - const laResult = spec.interpretResponse({}, []) - expect(laResult).to.be.an('array').that.is.empty; - }); - const loServerResult = { - body: { status: 'error', error: 'aie' } - }; - it('should return empty array if there is an error', function () { - const laResult = spec.interpretResponse(loServerResult, []) - expect(laResult).to.be.an('array').that.is.empty; - }); - }); // interpretResponse1 - describe('interpretResponse2', function() { - const loServerResult = { - body: { - status: 'ok', - error: '', - pbid: '6147833a65749742875ace47', - bids: [{ - requestId: commonBidRequest.bidId, - cpm: 0.10, - currency: 'EUR', - width: 300, - height: 250, - ad: 'test ad', - ttl: 60, - creativeId: 'c123a456', - netRevenue: false, - }] - } - }; - const loExpected = [{ - requestId: '1a2b3c4d56e7f0', - cpm: 0.1, - currency: 'EUR', - width: 300, - height: 250, - ad: 'test ad', - ttl: 60, - creativeId: 'c123a456', - netRevenue: false, - pbid: '6147833a65749742875ace47' - }]; - it('should return a correct bid response', function () { - const laResult = spec.interpretResponse(loServerResult, []) - expect(JSON.stringify(laResult)).to.equal(JSON.stringify(loExpected)); - }); - }); // interpretResponse2 - - /** - * onBidWon - */ - describe('onBidWon', function() { - it('should not make an ajax call if pbid is null', function () { - const loBid = { - requestId: '1a2b3c4d56e7f0', - cpm: 0.1, - currency: 'EUR', - width: 300, - height: 250, - ad: 'test ad', - ttl: 60, - creativeId: 'c123a456', - netRevenue: false, - params: [Object.assign({}, commonBidRequest.params)], - } - spec.onBidWon(loBid) - expect(server.requests.length).to.equals(0); - }); - it('should make an ajax call', function () { - const loBid = { - requestId: '1a2b3c4d56e7f0', - cpm: 0.1, - currency: 'EUR', - width: 300, - height: 250, - ad: 'test ad', - ttl: 60, - creativeId: 'c123a456', - netRevenue: false, - pbid: '6147833a65749742875ace47', - params: [Object.assign({}, commonBidRequest.params)], - } - spec.onBidWon(loBid) - expect(server.requests[0].url).to.equals('https://test.natexo-programmatic.com/tad/tag/prebidwon/6147833a65749742875ace47'); - }); - }); // onBidWon -}); diff --git a/test/spec/modules/tappxBidAdapter_spec.js b/test/spec/modules/tappxBidAdapter_spec.js index 8866670df77..c4e0329de17 100644 --- a/test/spec/modules/tappxBidAdapter_spec.js +++ b/test/spec/modules/tappxBidAdapter_spec.js @@ -1,6 +1,6 @@ import { assert } from 'chai'; import { spec } from 'modules/tappxBidAdapter.js'; -import { _checkParamDataType, _getHostInfo, _extractPageUrl } from '../../../modules/tappxBidAdapter.js'; +import { _checkParamDataType, _getHostInfo } from '../../../modules/tappxBidAdapter.js'; const c_BIDREQUEST = { data: { @@ -70,10 +70,7 @@ const c_SERVERRESPONSE_B = { adm: "\t", w: 320, h: 480, - lurl: 'https:\/\/ssp.api.tappx.com\/burlURL', - burl: 'https:\/\/ssp.api.tappx.com\/burlURL', - nurl: 'https:\/\/ssp.api.tappx.com\/nurllURL', - dealId: 'b21d0704-9688-4e46-81d9-41de1050fef7', + lurl: 'http://testing.ssp.tappx.com/rtb/RTBv2Loss?id=3811165568213389257&ep=ZZ1234PBJS&au=test&bu=localhost&sz=320x480&pu=0.005&pt=0.01&cid=&crid=&adv=&aid=${AUCTION_ID}&bidid=${AUCTION_BID_ID}&impid=${AUCTION_IMP_ID}&sid=${AUCTION_SEAT_ID}&adid=${AUCTION_AD_ID}&ap=${AUCTION_PRICE}&cur=${AUCTION_CURRENCY}&mbr=${AUCTION_MBR}&l=${AUCTION_LOSS}', cid: '01744fbb521e9fb10ffea926190effea', crid: 'a13cf884e66e7c660afec059c89d98b6', adomain: [ @@ -101,10 +98,7 @@ const c_SERVERRESPONSE_V = { impid: 1, price: 0.05, adm: "Tappx<\/AdSystem>Tappx<\/AdTitle><\/Impression><\/Error>00:00:22<\/Duration><\/Tracking><\/Tracking><\/Tracking><\/Tracking><\/Tracking><\/Tracking><\/Tracking><\/TrackingEvents><\/ClickThrough><\/ClickTracking><\/VideoClicks><\/MediaFile><\/MediaFiles><\/Linear><\/Creative><\/Creatives><\/InLine><\/Ad><\/VAST>", - lurl: 'https:\/\/ssp.api.tappx.com\/lurlURL', - burl: 'https:\/\/ssp.api.tappx.com\/burlURL', - nurl: 'https:\/\/ssp.api.tappx.com\/nurllURL', - dealId: 'b21d0704-9688-4e46-81d9-41de1050fef7', + 'lurl': 'https:\/\/ssp.api.tappx.com\/rtb\/RTBv2Loss?id=5001829913749291152&ep=VZ12TESTCTV&au=test&bu=localhost&sz=6x6&pu=0.005&pt=0.01&cid=&crid=&adv=&aid=${AUCTION_ID}&bidid=${AUCTION_BID_ID}&impid=${AUCTION_IMP_ID}&sid=${AUCTION_SEAT_ID}&adid=${AUCTION_AD_ID}&ap=${AUCTION_PRICE}&cur=${AUCTION_CURRENCY}&mbr=${AUCTION_MBR}&l=${AUCTION_LOSS}', cid: '01744fbb521e9fb10ffea926190effea', crid: 'a13cf884e66e7c660afec059c89d98b6', adomain: [ @@ -123,7 +117,6 @@ const c_VALIDBIDREQUESTS = [{'bidder': 'tappx', 'params': {'host': 'testing.ssp. const c_VALIDBIDAPPREQUESTS = [{'bidder': 'tappx', 'params': {'host': 'testing.ssp.tappx.com\/rtb\/v2\/', 'tappxkey': 'pub-1234-android-1234', 'endpoint': 'ZZ1234PBJS', 'bidfloor': 0.005, 'test': 1, 'app': {'name': 'Tappx Test', 'bundle': 'com.test.tappx', 'domain': 'tappx.com', 'publisher': { 'name': 'Tappx', 'domain': 'tappx.com' }}}, 'userId': {'haloId': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'id5id': {'uid': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'ext': {'linkType': 0}}, 'intentIqId': 'GIF89a\u0001\u0000\u0001\u0000�\u0000\u0000���\u0000\u0000\u0000!�\u0004\u0001\u0000\u0000\u0000\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0002D\u0001\u0000;', 'lotamePanoramaId': '8003916b61a95b185690ec103bdf4945a70213e01818a5e5d8690b542730755a', 'parrableId': {'eid': '01.1617088921.7faa68d9570a50ea8e4f359e9b99ca4b7509e948a6175b3e5b0b8cbaf5b62424104ccfb0191ca79366de8368ed267b89a68e236df5f41f96f238e4301659e9023fec05e46399fb1ad0a0'}, 'pubcid': 'b7143795-852f-42f0-8864-5ecbea1ade4e', 'pubProvidedId': [{'source': 'domain.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 1, 'ext': {'stype': 'ppuid'}}]}, {'source': '3rdpartyprovided.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 3, 'ext': {'stype': 'sha256email'}}]}]}, 'userIdAsEids': [{'source': 'audigent.com', 'uids': [{'id': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'atype': 1}]}, {'source': 'id5-sync.com', 'uids': [{'id': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'atype': 1, 'ext': {'linkType': 0}}]}, {'source': 'intentiq.com', 'uids': [{'id': 'GIF89a\u0001\u0000\u0001\u0000�\u0000\u0000���\u0000\u0000\u0000!�\u0004\u0001\u0000\u0000\u0000\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0002D\u0001\u0000;', 'atype': 1}]}, {'source': 'crwdcntrl.net', 'uids': [{'id': '8003916b61a95b185690ec103bdf4945a70213e01818a5e5d8690b542730755a', 'atype': 1}]}, {'source': 'parrable.com', 'uids': [{'id': '01.1617088921.7faa68d9570a50ea8e4f359e9b99ca4b7509e948a6175b3e5b0b8cbaf5b62424104ccfb0191ca79366de8368ed267b89a68e236df5f41f96f238e4301659e9023fec05e46399fb1ad0a0', 'atype': 1}]}, {'source': 'pubcid.org', 'uids': [{'id': 'b7143795-852f-42f0-8864-5ecbea1ade4e', 'atype': 1}]}, {'source': 'domain.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 1, 'ext': {'stype': 'ppuid'}}]}, {'source': '3rdpartyprovided.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 3, 'ext': {'stype': 'sha256email'}}]}], 'ortb2Imp': {'ext': {'data': {'adserver': {'name': 'gam', 'adslot': '/19968336/header-bid-tag-0'}, 'pbadslot': '/19968336/header-bid-tag-0'}}}, 'mediaTypes': {'banner': {'sizes': [[320, 480], [320, 50]]}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '71c0d86b-4b47-4aff-a6da-1af0b1712439', 'sizes': [[320, 480], [320, 50]], 'bidId': '264d7969b125a5', 'bidderRequestId': '1c674c14a3889c', 'auctionId': '13a8a3a9-ed3a-4101-9435-4699ee77bb62', 'src': 'client', 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0}]; const c_BIDDERREQUEST_B = {'bidderCode': 'tappx', 'auctionId': '13a8a3a9-ed3a-4101-9435-4699ee77bb62', 'bidderRequestId': '1c674c14a3889c', 'bids': [{'bidder': 'tappx', 'params': {'host': 'testing.ssp.tappx.com\/rtb\/v2\/', 'tappxkey': 'pub-1234-android-1234', 'endpoint': 'ZZ1234PBJS', 'bidfloor': 0.005, 'test': 1}, 'userId': {'haloId': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'id5id': {'uid': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'ext': {'linkType': 0}}, 'intentIqId': 'GIF89a\u0000\u0000\u0000\u0000�\u0000\u0000���\u0000\u0000\u0000?�\u0000\u0000\u0000\u0000\u0000\u0000,\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000A\u0000\u0000;', 'lotamePanoramaId': '8003916b61a95b185690ec103bdf4945a70213e01818a5e5d8690b542730755a', 'parrableId': {'eid': '01.1617088921.7faa68d9570a50ea8e4f359e9b99ca4b7509e948a6175b3e5b0b8cbaf5b62424104ccfb0191ca79366de8368ed267b89a68e236df5f41f96f238e4301659e9023fec05e46399fb1ad0a0'}, 'pubcid': 'b7143795-852f-42f0-8864-5ecbea1ade4e', 'pubProvidedId': [{'source': 'domain.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 1, 'ext': {'stype': 'ppuid'}}]}, {'source': '3rdpartyprovided.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 3, 'ext': {'stype': 'sha256email'}}]}]}, 'userIdAsEids': [{'source': 'audigent.com', 'uids': [{'id': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'atype': 1}]}, {'source': 'id5-sync.com', 'uids': [{'id': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'atype': 1, 'ext': {'linkType': 0}}]}], 'ortb2Imp': {'ext': {'data': {'adserver': {'name': 'gam', 'adslot': '/19968336/header-bid-tag-0'}, 'pbadslot': '/19968336/header-bid-tag-0'}}}, 'mediaTypes': {'banner': {'sizes': [[320, 480], [320, 50]]}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '71c0d86b-4b47-4aff-a6da-1af0b1712439', 'sizes': [[320, 480], [320, 50]], 'bidId': '264d7969b125a5', 'bidderRequestId': '1c674c14a3889c', 'auctionId': '13a8a3a9-ed3a-4101-9435-4699ee77bb62', 'src': 'client', 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0}], 'auctionStart': 1617088922120, 'timeout': 700, 'refererInfo': {'referer': 'http://localhost:9999/integrationExamples/gpt/gdpr_hello_world.html?pbjs_debug=true', 'reachedTop': true, 'isAmp': false, 'numIframes': 0, 'stack': ['http://localhost:9999/integrationExamples/gpt/gdpr_hello_world.html?pbjs_debug=true'], 'canonicalUrl': null}, 'gdprConsent': {'consentString': c_CONSENTSTRING, 'vendorData': {'metadata': 'BO-JeiTPABAOkAAABAENABA', 'gdprApplies': true, 'hasGlobalScope': false, 'cookieVersion': 1, 'created': '2020-12-09T09:22:09.900Z', 'lastUpdated': '2021-01-14T15:44:03.600Z', 'cmpId': 0, 'cmpVersion': 1, 'consentScreen': 0, 'consentLanguage': 'EN', 'vendorListVersion': 1, 'maxVendorId': 0, 'purposeConsents': {}, 'vendorConsents': {}}, 'gdprApplies': true, 'apiVersion': 1}, 'uspConsent': '1YCC', 'start': 1611308859099}; const c_BIDDERREQUEST_V = {'method': 'POST', 'url': 'https://testing.ssp.tappx.com/rtb/v2//VZ12TESTCTV?type_cnn=prebidjs&v=0.1.10329', 'data': '{"site":{"name":"localhost","bundle":"localhost","domain":"localhost"},"user":{"ext":{}},"id":"0fecfa84-c541-49f8-8c45-76b90fddc30e","test":1,"at":1,"tmax":1000,"bidder":"tappx","imp":[{"video":{"mimes":["video/mp4","application/javascript"],"minduration":3,"maxduration":30,"startdelay":5,"playbackmethod":[1,3],"api":[1,2],"protocols":[2,3],"battr":[13,14],"linearity":1,"placement":2,"minbitrate":10,"maxbitrate":10,"w":320,"h":250},"id":"2398241a5a860b","tagid":"localhost_typeAdBanVid_windows","secure":1,"bidfloor":0.005,"ext":{"bidder":{"tappxkey":"pub-1234-desktop-1234","endpoint":"vz34906po","host":"https://vz34906po.pub.tappx.com/rtb/","bidfloor":0.005}}}],"device":{"os":"windows","ip":"peer","ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36","h":864,"w":1536,"dnt":0,"language":"en","make":"Google Inc."},"params":{"host":"tappx.com","bidfloor":0.005},"regs":{"gdpr":0,"ext":{}}}', 'bids': {'bidder': 'tappx', 'params': {'host': 'testing.ssp.tappx.com/rtb/v2/', 'tappxkey': 'pub-1234-desktop-1234', 'endpoint': 'VZ12TESTCTV', 'bidfloor': 0.005, 'test': true}, 'crumbs': {'pubcid': 'dccfe922-3823-4676-b7b2-e5ed8743154e'}, 'ortb2Imp': {'ext': {'data': {'pbadslot': 'video-ad-div'}}}, 'renderer': {'options': {'text': 'Tappx Outstream Video'}}, 'mediaTypes': {'video': {'mimes': ['video/mp4', 'application/javascript'], 'minduration': 3, 'maxduration': 30, 'startdelay': 5, 'playbackmethod': [1, 3], 'api': [1, 2], 'protocols': [2, 3], 'battr': [13, 14], 'linearity': 1, 'placement': 2, 'minbitrate': 10, 'maxbitrate': 10, 'w': 320, 'h': 250}}, 'adUnitCode': 'video-ad-div', 'transactionId': 'ed41c805-d14c-49c3-954d-26b98b2aa2c2', 'sizes': [[320, 250]], 'bidId': '28f49c71b13f2f', 'bidderRequestId': '1401710496dc7', 'auctionId': 'e807363f-3095-43a8-a4a6-f44196cb7318', 'src': 'client', 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0}} -const c_BIDDERREQUEST_VOutstream = {'method': 'POST', 'url': 'https://testing.ssp.tappx.com/rtb/v2//VZ12TESTCTV?type_cnn=prebidjs&v=0.1.10329', 'data': '{"site":{"name":"localhost","bundle":"localhost","domain":"localhost"},"user":{"ext":{}},"id":"0fecfa84-c541-49f8-8c45-76b90fddc30e","test":1,"at":1,"tmax":1000,"bidder":"tappx","imp":[{"video":{"context": "outstream","playerSize":[640, 480],"mimes":["video/mp4","application/javascript"],"minduration":3,"maxduration":30,"startdelay":5,"playbackmethod":[1,3],"api":[1,2],"protocols":[2,3],"battr":[13,14],"linearity":1,"placement":2,"minbitrate":10,"maxbitrate":10,"w":320,"h":250},"id":"2398241a5a860b","tagid":"localhost_typeAdBanVid_windows","secure":1,"bidfloor":0.005,"ext":{"bidder":{"tappxkey":"pub-1234-desktop-1234","endpoint":"vz34906po","host":"https://vz34906po.pub.tappx.com/rtb/","bidfloor":0.005}}}],"device":{"os":"windows","ip":"peer","ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36","h":864,"w":1536,"dnt":0,"language":"en","make":"Google Inc."},"params":{"host":"tappx.com","bidfloor":0.005},"regs":{"gdpr":0,"ext":{}}}', 'bids': {'bidder': 'tappx', 'params': {'host': 'testing.ssp.tappx.com/rtb/v2/', 'tappxkey': 'pub-1234-desktop-1234', 'endpoint': 'VZ12TESTCTV', 'bidfloor': 0.005, 'test': true}, 'crumbs': {'pubcid': 'dccfe922-3823-4676-b7b2-e5ed8743154e'}, 'ortb2Imp': {'ext': {'data': {'pbadslot': 'video-ad-div'}}}, 'renderer': {'options': {'text': 'Tappx Outstream Video'}}, 'mediaTypes': {'video': {'mimes': ['video/mp4', 'application/javascript'], 'minduration': 3, 'maxduration': 30, 'startdelay': 5, 'playbackmethod': [1, 3], 'api': [1, 2], 'protocols': [2, 3], 'battr': [13, 14], 'linearity': 1, 'placement': 2, 'minbitrate': 10, 'maxbitrate': 10, 'w': 320, 'h': 250}}, 'adUnitCode': 'video-ad-div', 'transactionId': 'ed41c805-d14c-49c3-954d-26b98b2aa2c2', 'sizes': [[320, 250]], 'bidId': '28f49c71b13f2f', 'bidderRequestId': '1401710496dc7', 'auctionId': 'e807363f-3095-43a8-a4a6-f44196cb7318', 'src': 'client', 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0}} describe('Tappx bid adapter', function () { /** @@ -134,6 +127,12 @@ describe('Tappx bid adapter', function () { assert.isTrue(spec.isBidRequestValid(c_BIDREQUEST.bids[0]), JSON.stringify(c_BIDREQUEST)); }); + it('should return false when params are missing', function () { + let badBidRequestParam = JSON.parse(JSON.stringify(c_BIDREQUEST)); + delete badBidRequestParam.bids[0].params; + assert.isFalse(spec.isBidRequestValid(badBidRequestParam.bids[0])); + }); + it('should return false when tappxkey is missing', function () { let badBidRequestTpxkey = JSON.parse(JSON.stringify(c_BIDREQUEST)); ; delete badBidRequestTpxkey.bids[0].params.tappxkey; @@ -159,18 +158,24 @@ describe('Tappx bid adapter', function () { assert.isTrue(spec.isBidRequestValid(badBidRequestNwEp.bids[0])); }); - it('should return false for not instream/outstream requests', function () { + it('should return false mimes param is missing', function () { + let badBidRequest_mimes = c_BIDDERREQUEST_V; + delete badBidRequest_mimes.bids.mediaTypes.video; + badBidRequest_mimes.bids.mediaTypes.video = {}; + badBidRequest_mimes.bids.mediaTypes.video.context = 'instream'; + badBidRequest_mimes.bids.mediaTypes.video.playerSize = [320, 250]; + assert.isFalse(spec.isBidRequestValid(badBidRequest_mimes.bids), badBidRequest_mimes); + }); + + it('should return false for not instream requests', function () { let badBidRequest_v = c_BIDDERREQUEST_V; delete badBidRequest_v.bids.mediaTypes.banner; badBidRequest_v.bids.mediaTypes.video = {}; - badBidRequest_v.bids.mediaTypes.video.context = ''; + badBidRequest_v.bids.mediaTypes.video.context = 'outstream'; + badBidRequest_v.bids.mediaTypes.video.mimes = [ 'video/mp4', 'application/javascript' ]; badBidRequest_v.bids.mediaTypes.video.playerSize = [320, 250]; assert.isFalse(spec.isBidRequestValid(badBidRequest_v.bids)); }); - - it('should export the TCF vendor ID', function () { - expect(spec.gvlid).to.equal(628); - }) }); /** @@ -180,13 +185,11 @@ describe('Tappx bid adapter', function () { // Web Test let validBidRequests = c_VALIDBIDREQUESTS; let validBidRequests_V = c_VALIDBIDREQUESTS; - let validBidRequests_Voutstream = c_VALIDBIDREQUESTS; // App Test let validAppBidRequests = c_VALIDBIDAPPREQUESTS; let bidderRequest = c_BIDDERREQUEST_B; let bidderRequest_V = c_BIDDERREQUEST_V; - let bidderRequest_VOutstream = c_BIDDERREQUEST_VOutstream; it('should add gdpr/usp consent information to the request', function () { const request = spec.buildRequests(validBidRequests, bidderRequest); @@ -212,13 +215,6 @@ describe('Tappx bid adapter', function () { }); it('should properly build a video request', function () { - delete validBidRequests_V[0].mediaTypes.banner - validBidRequests_V[0].mediaTypes.video = {}; - validBidRequests_V[0].mediaTypes.video.playerSize = [640, 480]; - validBidRequests_V[0].mediaTypes.video.context = 'instream'; - - bidderRequest_V.bids.mediaTypes.context = 'instream'; - const request = spec.buildRequests(validBidRequests_V, bidderRequest_V); expect(request[0].url).to.match(/^(http|https):\/\/(.*)\.tappx\.com\/.+/); expect(request[0].method).to.equal('POST'); @@ -227,46 +223,9 @@ describe('Tappx bid adapter', function () { expect(data.site).to.not.equal(null); expect(data.imp).to.have.lengthOf(1); expect(data.imp[0].bidfloor, data).to.not.be.null; - expect(data.imp[0].video).to.not.equal(null); - }); - - it('should properly build a video outstream request', function () { - delete validBidRequests_Voutstream[0].mediaTypes.banner - validBidRequests_Voutstream[0].mediaTypes.video = {}; - validBidRequests_Voutstream[0].mediaTypes.video.playerSize = [640, 480]; - validBidRequests_Voutstream[0].mediaTypes.video.context = 'outstream'; - - bidderRequest_VOutstream.bids.mediaTypes.context = 'outstream'; - - const request = spec.buildRequests(validBidRequests_Voutstream, bidderRequest_VOutstream); - expect(request[0].url).to.match(/^(http|https):\/\/(.*)\.tappx\.com\/.+/); - expect(request[0].method).to.equal('POST'); - - const data = JSON.parse(request[0].data); - expect(data.site).to.not.equal(null); - expect(data.imp).to.have.lengthOf(1); - expect(data.imp[0].bidfloor, data).to.not.be.null; - expect(data.imp[0].video).to.not.equal(null); - }); - - it('should properly create video rewarded request', function () { - delete validBidRequests_Voutstream[0].mediaTypes.banner - validBidRequests_Voutstream[0].mediaTypes.video = {}; - validBidRequests_Voutstream[0].mediaTypes.video.rewarded = 1; - validBidRequests_Voutstream[0].mediaTypes.video.playerSize = [640, 480]; - validBidRequests_Voutstream[0].mediaTypes.video.context = 'outstream'; - - bidderRequest_VOutstream.bids.mediaTypes.context = 'outstream'; - - const request = spec.buildRequests(validBidRequests_Voutstream, bidderRequest_VOutstream); - expect(request[0].url).to.match(/^(http|https):\/\/(.*)\.tappx\.com\/.+/); - expect(request[0].method).to.equal('POST'); - - const data = JSON.parse(request[0].data); - expect(data.site).to.not.equal(null); - expect(data.imp).to.have.lengthOf(1); - expect(data.imp[0].bidfloor, data).to.not.be.null; - expect(data.imp[0].video).to.not.equal(null); + expect(data.imp[0].banner).to.not.equal(null); + expect(data.imp[0].banner.w).to.be.oneOf([320, 50, 250, 480]); + expect(data.imp[0].banner.h).to.be.oneOf([320, 50, 250, 480]); }); it('should set user eids array', function () { @@ -455,13 +414,4 @@ describe('Tappx bid adapter', function () { expect(_checkParamDataType('Wrong array', false, 'array')).to.be.undefined; }); }) - - describe('_extractPageUrl tests', function() { - let validBidRequests = c_VALIDBIDREQUESTS; - let bidderRequest = c_BIDDERREQUEST_B; - it('should return the Domain of the site', function () { - validBidRequests[0].params.domainUrl = 'testUrl.com'; - assert.isString(_extractPageUrl(validBidRequests, bidderRequest)); - }); - }) }); diff --git a/test/spec/modules/targetVideoBidAdapter_spec.js b/test/spec/modules/targetVideoBidAdapter_spec.js deleted file mode 100644 index 0ce6f0fb70d..00000000000 --- a/test/spec/modules/targetVideoBidAdapter_spec.js +++ /dev/null @@ -1,96 +0,0 @@ -import { spec } from '../../../modules/targetVideoBidAdapter.js' - -describe('TargetVideo Bid Adapter', function() { - const bannerRequest = [{ - bidder: 'targetVideo', - mediaTypes: { - banner: { - sizes: [[300, 250]], - } - }, - params: { - placementId: 12345, - } - }]; - - it('Test the bid validation function', function() { - const validBid = spec.isBidRequestValid(bannerRequest[0]); - const invalidBid = spec.isBidRequestValid(null); - - expect(validBid).to.be.true; - expect(invalidBid).to.be.false; - }); - - it('Test the request processing function', function () { - const request = spec.buildRequests(bannerRequest, bannerRequest[0]); - expect(request).to.not.be.empty; - - const payload = JSON.parse(request.data); - expect(payload).to.not.be.empty; - expect(payload.sdk).to.deep.equal({ - source: 'pbjs', - version: '$prebid.version$' - }); - expect(payload.tags[0].id).to.equal(12345); - expect(payload.tags[0].gpid).to.equal('targetVideo'); - expect(payload.tags[0].ad_types[0]).to.equal('video'); - }); - - it('Handle nobid responses', function () { - const responseBody = { - 'version': '0.0.1', - 'tags': [{ - 'uuid': '84ab500420319d', - 'tag_id': 5976557, - 'auction_id': '297492697822162468', - 'nobid': true - }] - }; - const bidderRequest = null; - - const bidResponse = spec.interpretResponse({ body: responseBody }, {bidderRequest}); - expect(bidResponse.length).to.equal(0); - }); - - it('Test the response parsing function', function () { - const responseBody = { - 'tags': [{ - 'uuid': '84ab500420319d', - 'ads': [{ - 'ad_type': 'video', - 'cpm': 0.500000, - 'notify_url': 'https://www.target-video.com/', - 'rtb': { - 'video': { - 'player_width': 640, - 'player_height': 360, - 'asset_url': 'https://www.target-video.com/' - } - } - }] - }] - }; - const bidderRequest = { - bids: [{ - bidId: '84ab500420319d', - adUnitCode: 'code', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - } - }] - }; - - const bidResponse = spec.interpretResponse({ body: responseBody }, {bidderRequest}); - expect(bidResponse).to.not.be.empty; - - const bid = bidResponse[0]; - expect(bid).to.not.be.empty; - expect(bid.cpm).to.equal(0.675); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - expect(bid.ad).to.include('') - expect(bid.ad).to.include('initPlayer') - }); -}); diff --git a/test/spec/modules/teadsBidAdapter_spec.js b/test/spec/modules/teadsBidAdapter_spec.js index 75ed7452b57..7fd3b70398b 100644 --- a/test/spec/modules/teadsBidAdapter_spec.js +++ b/test/spec/modules/teadsBidAdapter_spec.js @@ -582,93 +582,6 @@ describe('teadsBidAdapter', () => { }); }); - describe('Global Placement Id', function () { - let bidRequests = [ - { - 'bidder': 'teads', - 'params': { - 'placementId': 10433394, - 'pageId': 1234 - }, - 'adUnitCode': 'adunit-code-1', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'creativeId': 'er2ee', - 'deviceWidth': 1680 - }, - { - 'bidder': 'teads', - 'params': { - 'placementId': 10433395, - 'pageId': 1234 - }, - 'adUnitCode': 'adunit-code-2', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1f', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'creativeId': 'er2ef', - 'deviceWidth': 1680 - } - ]; - - it('should add gpid if ortb2Imp.ext.gpid is present and is non empty', function () { - const updatedBidRequests = bidRequests.map(function(bidRequest, index) { - return { - ...bidRequest, - ortb2Imp: { - ext: { - gpid: '1111/home-left-' + index - } - } - }; - } - ); - const request = spec.buildRequests(updatedBidRequests, bidderResquestDefault); - const payload = JSON.parse(request.data); - - expect(payload.data[0].gpid).to.equal('1111/home-left-0'); - expect(payload.data[1].gpid).to.equal('1111/home-left-1'); - }); - - it('should not add gpid if ortb2Imp.ext.gpid is present but empty', function () { - const updatedBidRequests = bidRequests.map(bidRequest => ({ - ...bidRequest, - ortb2Imp: { - ext: { - gpid: '' - } - } - })); - - const request = spec.buildRequests(updatedBidRequests, bidderResquestDefault); - const payload = JSON.parse(request.data); - - return payload.data.forEach(bid => { - expect(bid).not.to.have.property('gpid'); - }); - }); - - it('should not add gpid if ortb2Imp.ext.gpid is not present', function () { - const updatedBidRequests = bidRequests.map(bidRequest => ({ - ...bidRequest, - ortb2Imp: { - ext: { - } - } - })); - - const request = spec.buildRequests(updatedBidRequests, bidderResquestDefault); - const payload = JSON.parse(request.data); - - return payload.data.forEach(bid => { - expect(bid).not.to.have.property('gpid'); - }); - }); - }); - function checkMediaTypesSizes(mediaTypes, expectedSizes) { const bidRequestWithBannerSizes = Object.assign(bidRequests[0], mediaTypes); const requestWithBannerSizes = spec.buildRequests([bidRequestWithBannerSizes], bidderResquestDefault); diff --git a/test/spec/modules/telariaBidAdapter_spec.js b/test/spec/modules/telariaBidAdapter_spec.js index 457dd568764..25649115cc1 100644 --- a/test/spec/modules/telariaBidAdapter_spec.js +++ b/test/spec/modules/telariaBidAdapter_spec.js @@ -234,7 +234,9 @@ describe('TelariaAdapter', () => { }]; it('should get correct bid response', () => { - let expectedResponseKeys = ['requestId', 'cpm', 'creativeId', 'vastXml', 'vastUrl', 'mediaType', 'width', 'height', 'currency', 'netRevenue', 'ttl', 'ad', 'meta']; + let expectedResponseKeys = ['bidderCode', 'width', 'height', 'statusMessage', 'adId', 'mediaType', 'source', + 'getStatusCode', 'getSize', 'requestId', 'cpm', 'creativeId', 'vastXml', + 'vastUrl', 'currency', 'netRevenue', 'ttl', 'ad', 'meta']; let bidRequest = spec.buildRequests(stub, BIDDER_REQUEST)[0]; bidRequest.bidId = '1234'; diff --git a/test/spec/modules/timeoutRtdProvider_spec.js b/test/spec/modules/timeoutRtdProvider_spec.js deleted file mode 100644 index 88415a99b5e..00000000000 --- a/test/spec/modules/timeoutRtdProvider_spec.js +++ /dev/null @@ -1,339 +0,0 @@ - -import { timeoutRtdFunctions, timeoutSubmodule } from '../../../modules/timeoutRtdProvider' -import { expect } from 'chai'; -import * as ajax from 'src/ajax.js'; -import * as prebidGlobal from 'src/prebidGlobal.js'; - -const DEFAULT_USER_AGENT = window.navigator.userAgent; -const DEFAULT_CONNECTION = window.navigator.connection; - -const PC_USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246'; -const MOBILE_USER_AGENT = 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1'; -const TABLET_USER_AGENT = 'Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148'; - -function resetUserAgent() { - window.navigator.__defineGetter__('userAgent', () => DEFAULT_USER_AGENT); -}; - -function setUserAgent(userAgent) { - window.navigator.__defineGetter__('userAgent', () => userAgent); -} - -function resetConnection() { - window.navigator.__defineGetter__('connection', () => DEFAULT_CONNECTION); -} -function setConnectionType(connectionType) { - window.navigator.__defineGetter__('connection', () => { return {'type': connectionType} }); -} - -describe('getDeviceType', () => { - afterEach(() => { - resetUserAgent(); - }); - - [ - // deviceType, userAgent, deviceTypeNum - ['pc', PC_USER_AGENT, 2], - ['mobile', MOBILE_USER_AGENT, 4], - ['tablet', TABLET_USER_AGENT, 5], - ].forEach(function(args) { - const [deviceType, userAgent, deviceTypeNum] = args; - it(`should be able to recognize ${deviceType} devices`, () => { - setUserAgent(userAgent); - const res = timeoutRtdFunctions.getDeviceType(); - expect(res).to.equal(deviceTypeNum) - }) - }) -}); - -describe('getConnectionSpeed', () => { - afterEach(() => { - resetConnection(); - }); - [ - // connectionType, connectionSpeed - ['slow-2g', 'slow'], - ['2g', 'slow'], - ['3g', 'medium'], - ['bluetooth', 'fast'], - ['cellular', 'fast'], - ['ethernet', 'fast'], - ['wifi', 'fast'], - ['wimax', 'fast'], - ['4g', 'fast'], - ['not known', 'unknown'], - [undefined, 'unknown'], - ].forEach(function(args) { - const [connectionType, connectionSpeed] = args; - it(`should be able to categorize connection speed when the connection type is ${connectionType}`, () => { - setConnectionType(connectionType); - const res = timeoutRtdFunctions.getConnectionSpeed(); - expect(res).to.equal(connectionSpeed) - }) - }) -}); - -describe('Timeout modifier calculations', () => { - let sandbox; - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('should be able to detect video ad units', () => { - let adUnits = [] - let res = timeoutRtdFunctions.checkVideo(adUnits); - expect(res).to.be.false; - - adUnits = [{ - mediaTypes: { - video: [] - } - }]; - res = timeoutRtdFunctions.checkVideo(adUnits); - expect(res).to.be.true; - - adUnits = [{ - mediaTypes: { - banner: [] - } - }]; - res = timeoutRtdFunctions.checkVideo(adUnits); - expect(res).to.be.false; - }); - - it('should calculate the timeout modifier for video', () => { - sandbox.stub(timeoutRtdFunctions, 'checkVideo').returns(true); - const rules = { - includesVideo: { - 'true': 200, - 'false': 50 - } - } - const res = timeoutRtdFunctions.calculateTimeoutModifier([], rules); - expect(res).to.equal(200) - }); - - it('should calculate the timeout modifier for connectionSpeed', () => { - sandbox.stub(timeoutRtdFunctions, 'getConnectionSpeed').returns('slow'); - const rules = { - connectionSpeed: { - 'slow': 200, - 'medium': 100, - 'fast': 50 - } - } - const res = timeoutRtdFunctions.calculateTimeoutModifier([], rules); - expect(res).to.equal(200); - }); - - it('should calculate the timeout modifier for deviceType', () => { - sandbox.stub(timeoutRtdFunctions, 'getDeviceType').returns(4); - const rules = { - deviceType: { - '2': 50, - '4': 100, - '5': 200 - }, - } - const res = timeoutRtdFunctions.calculateTimeoutModifier([], rules); - expect(res).to.equal(100) - }); - - it('should calculate the timeout modifier for ranged numAdunits', () => { - const rules = { - numAdUnits: { - '1-5': 100, - '6-10': 200, - '11-15': 300, - } - } - const adUnits = [1, 2, 3, 4, 5, 6]; - const res = timeoutRtdFunctions.calculateTimeoutModifier(adUnits, rules); - expect(res).to.equal(200) - }); - - it('should calculate the timeout modifier for exact numAdunits', () => { - const rules = { - numAdUnits: { - '1': 100, - '2': 200, - '3': 300, - '4-5': 400, - } - } - const adUnits = [1, 2]; - const res = timeoutRtdFunctions.calculateTimeoutModifier(adUnits, rules); - expect(res).to.equal(200); - }); - - it('should add up all the modifiers when all the rules are present', () => { - sandbox.stub(timeoutRtdFunctions, 'getConnectionSpeed').returns('slow'); - sandbox.stub(timeoutRtdFunctions, 'getDeviceType').returns(4); - const rules = { - connectionSpeed: { - 'slow': 200, - 'medium': 100, - 'fast': 50 - }, - deviceType: { - '2': 50, - '4': 100, - '5': 200 - }, - includesVideo: { - 'true': 200, - 'false': 50 - }, - numAdUnits: { - '1': 100, - '2': 200, - '3': 300, - '4-5': 400, - } - } - const res = timeoutRtdFunctions.calculateTimeoutModifier([{ - mediaTypes: { - video: [] - } - }], rules); - expect(res).to.equal(600); - }); -}); - -describe('Timeout RTD submodule', () => { - let sandbox; - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('should init successfully', () => { - expect(timeoutSubmodule.init()).to.equal(true); - }); - - it('should make a request to the endpoint url if it is provided, and handle the response', () => { - const response = '{"deviceType":{ "2": 50, "4": 100, "5": 200 }}' - const ajaxStub = sandbox.stub().callsFake(function (url, callbackObj) { - callbackObj.success(response); - }); - sandbox.stub(ajax, 'ajaxBuilder').callsFake(function () { return ajaxStub }); - - const reqBidsConfigObj = {} - const expectedLink = 'https://somelink.json' - const config = { - 'name': 'timeout', - 'params': { - 'endpoint': { - url: expectedLink - } - } - } - const handleTimeoutIncrementStub = sandbox.stub(timeoutRtdFunctions, 'handleTimeoutIncrement'); - timeoutSubmodule.getBidRequestData(reqBidsConfigObj, function() {}, config) - - expect(ajaxStub.calledWith(expectedLink)).to.be.true; - expect(handleTimeoutIncrementStub.calledWith(reqBidsConfigObj, JSON.parse(response))).to.be.true; - }); - - it('should make a request to the endpoint url and ignore the rules object if the endpoint is provided', () => { - const ajaxStub = sandbox.stub().callsFake((url, callbackObj) => {}); - sandbox.stub(ajax, 'ajaxBuilder').callsFake(() => ajaxStub); - const expectedLink = 'https://somelink.json' - const config = { - 'name': 'timeout', - 'params': { - 'endpoint': { - url: expectedLink - }, - 'rules': { - 'includesVideo': { - 'true': 200, - }, - } - } - } - timeoutSubmodule.getBidRequestData({}, function() {}, config); - expect(ajaxStub.calledWith(expectedLink)).to.be.true; - }); - - it('should use the rules object if there is no endpoint url', () => { - const config = { - 'name': 'timeout', - 'params': { - 'rules': { - 'includesVideo': { - 'true': 200, - }, - } - } - } - const handleTimeoutIncrementStub = sandbox.stub(timeoutRtdFunctions, 'handleTimeoutIncrement'); - const reqBidsConfigObj = {}; - timeoutSubmodule.getBidRequestData(reqBidsConfigObj, function() {}, config); - expect(handleTimeoutIncrementStub.calledWith(reqBidsConfigObj, config.params.rules)).to.be.true; - }); - - it('should exit quietly if no relevant timeout config is found', () => { - const callback = sandbox.stub() - const ajaxStub = sandbox.stub().callsFake((url, callbackObj) => {}); - sandbox.stub(ajax, 'ajaxBuilder').callsFake(function() { return ajaxStub }); - const handleTimeoutIncrementStub = sandbox.stub(timeoutRtdFunctions, 'handleTimeoutIncrement'); - - timeoutSubmodule.getBidRequestData({}, callback, {}); - - expect(handleTimeoutIncrementStub.called).to.be.false; - expect(callback.called).to.be.true; - expect(ajaxStub.called).to.be.false; - }); - - it('should be able to increment the timeout with the calculated timeout modifier', () => { - const baseTimeout = 100; - const getConfigStub = sandbox.stub().returns(baseTimeout); - sandbox.stub(prebidGlobal, 'getGlobal').callsFake(() => { - return { - getConfig: getConfigStub - } - }); - - const reqBidsConfigObj = {adUnits: [1, 2, 3]} - const addedTimeout = 400; - const rules = { - numAdUnits: { - '3-5': addedTimeout, - } - } - - timeoutRtdFunctions.handleTimeoutIncrement(reqBidsConfigObj, rules) - expect(reqBidsConfigObj.timeout).to.be.equal(baseTimeout + addedTimeout); - }); - - it('should be able to increment the timeout with the calculated timeout modifier when there are multiple matching rules', () => { - const baseTimeout = 100; - const getConfigStub = sandbox.stub().returns(baseTimeout); - sandbox.stub(prebidGlobal, 'getGlobal').callsFake(() => { - return { - getConfig: getConfigStub - } - }); - - const reqBidsConfigObj = {adUnits: [1, 2, 3]} - const addedTimeout = 400; - const rules = { - numAdUnits: { - '3-5': addedTimeout / 2, - }, - includesVideo: { - 'false': addedTimeout / 2, - } - } - timeoutRtdFunctions.handleTimeoutIncrement(reqBidsConfigObj, rules) - expect(reqBidsConfigObj.timeout).to.be.equal(baseTimeout + addedTimeout); - }); -}); diff --git a/test/spec/modules/tpmnBidAdapter_spec.js b/test/spec/modules/tpmnBidAdapter_spec.js index 468769c2573..b4f6882dbe1 100644 --- a/test/spec/modules/tpmnBidAdapter_spec.js +++ b/test/spec/modules/tpmnBidAdapter_spec.js @@ -1,39 +1,9 @@ /* eslint-disable no-tabs */ -import {expect} from 'chai'; -import {spec, storage} from 'modules/tpmnBidAdapter.js'; -import {generateUUID} from '../../../src/utils.js'; -import {newBidder} from '../../../src/adapters/bidderFactory'; -import * as sinon from 'sinon'; +import { expect } from 'chai'; +import { spec } from 'modules/tpmnBidAdapter.js'; -describe('tpmnAdapterTests', function () { - const adapter = newBidder(spec); - const BIDDER_CODE = 'tpmn'; - let sandbox = sinon.sandbox.create(); - let getCookieStub; - - beforeEach(function () { - $$PREBID_GLOBAL$$.bidderSettings = { - tpmn: { - storageAllowed: true - } - }; - sandbox = sinon.sandbox.create(); - getCookieStub = sinon.stub(storage, 'getCookie'); - }); - - afterEach(function () { - sandbox.restore(); - getCookieStub.restore(); - $$PREBID_GLOBAL$$.bidderSettings = {}; - }); - - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(adapter.callBids).to.exist.and.to.be.a('function') - }) - }); - - describe('isBidRequestValid', function () { +describe('tpmnAdapterTests', function() { + describe('isBidRequestValid', function() { let bid = { adUnitCode: 'temp-unitcode', bidder: 'tpmn', @@ -50,18 +20,17 @@ describe('tpmnAdapterTests', function () { } } }; - - it('should return true if a bid is valid banner bid request', function () { + it('should return true if a bid is valid banner bid request', function() { expect(spec.isBidRequestValid(bid)).to.be.equal(true); }); - it('should return false where requried param is missing', function () { + it('should return false where requried param is missing', function() { let bid = Object.assign({}, bid); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.be.equal(false); }); - it('should return false when required param values have invalid type', function () { + it('should return false when required param values have invalid type', function() { let bid = Object.assign({}, bid); bid.params = { 'inventoryId': null, @@ -71,14 +40,14 @@ describe('tpmnAdapterTests', function () { }); }); - describe('buildRequests', function () { - it('should return an empty list if there are no bid requests', function () { + describe('buildRequests', function() { + it('should return an empty list if there are no bid requests', function() { const emptyBidRequests = []; const bidderRequest = {}; const request = spec.buildRequests(emptyBidRequests, bidderRequest); expect(request).to.be.an('array').that.is.empty; }); - it('should generate a POST server request with bidder API url, data', function () { + it('should generate a POST server request with bidder API url, data', function() { const bid = { adUnitCode: 'temp-unitcode', bidder: 'tpmn', @@ -96,15 +65,13 @@ describe('tpmnAdapterTests', function () { } }; const tempBidRequests = [bid]; - const tempBidderRequest = { - refererInfo: { - referer: 'http://localhost/test', - site: { - domain: 'localhost', - page: 'http://localhost/test' - } + const tempBidderRequest = {refererInfo: { + referer: 'http://localhost/test', + site: { + domain: 'localhost', + page: 'http://localhost/test' } - }; + }}; const builtRequest = spec.buildRequests(tempBidRequests, tempBidderRequest); expect(builtRequest).to.have.lengthOf(1); @@ -129,7 +96,7 @@ describe('tpmnAdapterTests', function () { }); }); - describe('interpretResponse', function () { + describe('interpretResponse', function() { const bid = { adUnitCode: 'temp-unitcode', bidder: 'tpmn', @@ -148,12 +115,12 @@ describe('tpmnAdapterTests', function () { }; const tempBidRequests = [bid]; - it('should return an empty aray to indicate no valid bids', function () { + it('should return an empty aray to indicate no valid bids', function() { const emptyServerResponse = {}; const bidResponses = spec.interpretResponse(emptyServerResponse, tempBidRequests); expect(bidResponses).is.an('array').that.is.empty; }); - it('should return an empty array to indicate no valid bids', function () { + it('should return an empty array to indicate no valid bids', function() { const mockBidResult = { requestId: '9cf19229-34f6-4d06-bc1d-0e44e8d616c8', cpm: 10.0, @@ -174,36 +141,4 @@ describe('tpmnAdapterTests', function () { expect(bidResponses).deep.equal([mockBidResult]); }); }); - - describe('getUserSync', function () { - const KEY_ID = 'uuid'; - const TMP_UUID = generateUUID().replace(/-/g, ''); - - it('getCookie mock Test', () => { - const uuid = storage.getCookie(KEY_ID); - expect(uuid).to.equal(undefined); - }); - - it('getCookie mock Test', () => { - expect(TMP_UUID.length).to.equal(32); - getCookieStub.withArgs(KEY_ID).returns(TMP_UUID); - const uuid = storage.getCookie(KEY_ID); - expect(uuid).to.equal(TMP_UUID); - }); - - it('case 1 -> allow iframe', () => { - const syncs = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}); - expect(syncs.length).to.equal(1); - expect(syncs[0].type).to.equal('iframe'); - }); - - it('case 2 -> allow pixel with static sync', () => { - const syncs = spec.getUserSyncs({ iframeEnabled: false, pixelEnabled: true }); - expect(syncs.length).to.be.equal(4); - expect(syncs[0].type).to.be.equal('image'); - expect(syncs[1].type).to.be.equal('image'); - expect(syncs[2].type).to.be.equal('image'); - expect(syncs[3].type).to.be.equal('image'); - }); - }); }); diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index fc33a7cd676..30377ec0a5d 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -11,7 +11,8 @@ const GDPR_CONSENT_STR = 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7V describe('triplelift adapter', function () { const adapter = newBidder(tripleliftAdapterSpec); - let bid, instreamBid, sandbox, logErrorSpy; + let bid, instreamBid; + let sandbox; this.beforeEach(() => { bid = { @@ -378,11 +379,9 @@ describe('triplelift adapter', function () { }, }; sandbox = sinon.sandbox.create(); - logErrorSpy = sinon.spy(utils, 'logError'); }); afterEach(() => { sandbox.restore(); - utils.logError.restore(); }); it('exists and is an object', function () { @@ -569,134 +568,6 @@ describe('triplelift adapter', function () { expect(payload.user.ext.eids).to.have.lengthOf(4); }); - it('should remove malformed ids that would otherwise break call', function () { - let tdidId = '6bca7f6b-a98a-46c0-be05-6020f7604598'; - let idlEnvId = null; // fail; can't be null - let criteoId = '53e30ea700424f7bbdd793b02abc5d7'; - let pubcid = ''; // fail; can't be empty string - - let bidRequestsMultiple = [ - { ...bidRequests[0], userId: { tdid: tdidId, idl_env: idlEnvId, criteoId, pubcid } }, - { ...bidRequests[0], userId: { tdid: tdidId, idl_env: idlEnvId, criteoId, pubcid } }, - { ...bidRequests[0], userId: { tdid: tdidId, idl_env: idlEnvId, criteoId, pubcid } } - ]; - - let request = tripleliftAdapterSpec.buildRequests(bidRequestsMultiple, bidderRequest); - let payload = request.data; - - expect(payload.user).to.deep.equal({ - ext: { - eids: [ - { - source: 'adserver.org', - uids: [ - { - id: tdidId, - ext: { rtiPartner: 'TDID' } - } - ], - }, - { - source: 'criteo.com', - uids: [ - { - id: criteoId, - ext: { rtiPartner: 'criteoId' } - } - ] - } - ] - } - }); - - expect(payload.user.ext.eids).to.be.an('array'); - expect(payload.user.ext.eids).to.have.lengthOf(2); - - tdidId = {}; // fail; can't be empty object - idlEnvId = { id: '987654' }; // pass - criteoId = [{ id: '123456' }]; // fail; can't be an array - pubcid = '3261d8ad-435d-481d-abd1-9f1a9ec99f0e'; // pass - - bidRequestsMultiple = [ - { ...bidRequests[0], userId: { tdid: tdidId, idl_env: idlEnvId, criteoId, pubcid } }, - { ...bidRequests[0], userId: { tdid: tdidId, idl_env: idlEnvId, criteoId, pubcid } }, - { ...bidRequests[0], userId: { tdid: tdidId, idl_env: idlEnvId, criteoId, pubcid } } - ]; - - request = tripleliftAdapterSpec.buildRequests(bidRequestsMultiple, bidderRequest); - payload = request.data; - - expect(payload.user).to.deep.equal({ - ext: { - eids: [ - { - source: 'liveramp.com', - uids: [ - { - id: '987654', - ext: { rtiPartner: 'idl' } - } - ] - }, - { - source: 'pubcid.org', - uids: [ - { - id: pubcid, - ext: { rtiPartner: 'pubcid' } - } - ] - } - ] - } - }); - - expect(payload.user.ext.eids).to.be.an('array'); - expect(payload.user.ext.eids).to.have.lengthOf(2); - - tdidId = { id: '987654' }; // pass - idlEnvId = { id: 987654 }; // fail; can't be an int - criteoId = '53e30ea700424f7bbdd793b02abc5d7'; // pass - pubcid = { id: '' }; // fail; can't be an empty string - - bidRequestsMultiple = [ - { ...bidRequests[0], userId: { tdid: tdidId, idl_env: idlEnvId, criteoId, pubcid } }, - { ...bidRequests[0], userId: { tdid: tdidId, idl_env: idlEnvId, criteoId, pubcid } }, - { ...bidRequests[0], userId: { tdid: tdidId, idl_env: idlEnvId, criteoId, pubcid } } - ]; - - request = tripleliftAdapterSpec.buildRequests(bidRequestsMultiple, bidderRequest); - payload = request.data; - - expect(payload.user).to.deep.equal({ - ext: { - eids: [ - { - source: 'adserver.org', - uids: [ - { - id: '987654', - ext: { rtiPartner: 'TDID' } - } - ], - }, - { - source: 'criteo.com', - uids: [ - { - id: criteoId, - ext: { rtiPartner: 'criteoId' } - } - ] - } - ] - } - }); - - expect(payload.user.ext.eids).to.be.an('array'); - expect(payload.user.ext.eids).to.have.lengthOf(2); - }); - it('should return a query string for TL call', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); const url = request.url; @@ -788,15 +659,6 @@ describe('triplelift adapter', function () { size: '*' })).to.be.true; }); - it('should catch error if getFloor throws error', function() { - bidRequests[0].getFloor = () => { - throw new Error('An exception!'); - }; - - tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); - - expect(logErrorSpy.calledOnce).to.equal(true); - }); it('should send global config fpd if kvps are available', function() { const sens = null; const category = ['news', 'weather', 'hurricane']; @@ -823,7 +685,7 @@ describe('triplelift adapter', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); const { data: payload } = request; expect(payload.ext.fpd.user).to.not.exist; - expect(payload.ext.fpd.context.ext.data).to.haveOwnProperty('category'); + expect(payload.ext.fpd.context.data).to.haveOwnProperty('category'); expect(payload.ext.fpd.context).to.haveOwnProperty('pmp_elig'); }); it('should send ad unit fpd if kvps are available', function() { @@ -947,8 +809,6 @@ describe('triplelift adapter', function () { expect(result).to.have.length(2); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); expect(Object.keys(result[1])).to.have.members(Object.keys(expectedResponse[1])); - expect(result[0].ttl).to.equal(300); - expect(result[1].ttl).to.equal(3600); }); it('should return multiple responses to support SRA', function () { diff --git a/test/spec/modules/trustpidSystem_spec.js b/test/spec/modules/trustpidSystem_spec.js deleted file mode 100644 index 97e87e3a303..00000000000 --- a/test/spec/modules/trustpidSystem_spec.js +++ /dev/null @@ -1,232 +0,0 @@ -import { expect } from 'chai'; -import { trustpidSubmodule } from 'modules/trustpidSystem.js'; -import { storage } from 'modules/trustpidSystem.js'; - -describe('trustpid System', () => { - const connectDataKey = 'fcIdConnectData'; - const connectDomainKey = 'fcIdConnectDomain'; - - const getStorageData = (idGraph) => { - if (!idGraph) { - idGraph = {id: 501, domain: ''}; - } - return { - 'connectId': { - 'idGraph': [idGraph], - } - } - }; - - it('should have the correct module name declared', () => { - expect(trustpidSubmodule.name).to.equal('trustpid'); - }); - - describe('trustpid getId()', () => { - afterEach(() => { - storage.removeDataFromLocalStorage(connectDataKey); - storage.removeDataFromLocalStorage(connectDomainKey); - }); - - it('it should return object with key callback', () => { - expect(trustpidSubmodule.getId()).to.have.property('callback'); - }); - - it('should return object with key callback with value type - function', () => { - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData())); - expect(trustpidSubmodule.getId()).to.have.property('callback'); - expect(typeof trustpidSubmodule.getId().callback).to.be.equal('function'); - }); - - it('tests if localstorage & JSON works properly ', () => { - const idGraph = { - 'domain': 'domainValue', - 'umid': 'umidValue', - }; - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - expect(JSON.parse(storage.getDataFromLocalStorage(connectDataKey))).to.have.property('connectId'); - }); - - it('returns {callback: func} if domains don\'t match', () => { - const idGraph = { - 'domain': 'domainValue', - 'umid': 'umidValue', - }; - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('differentDomainValue')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - expect(trustpidSubmodule.getId()).to.have.property('callback'); - }); - - it('returns {id: {trustpid: data.trustpid}} if we have the right data stored in the localstorage ', () => { - const idGraph = { - 'domain': 'uat.mno.link', - 'umid': 'umidValue', - }; - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('uat.mno.link')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - const response = trustpidSubmodule.getId(); - expect(response).to.have.property('id'); - expect(response.id).to.have.property('trustpid'); - expect(response.id.trustpid).to.be.equal('umidValue-xxxx'); - }); - - it('returns {trustpid: data.trustpid} if we have the right data stored in the localstorage right after the callback is called', (done) => { - const idGraph = { - 'domain': 'uat.mno.link', - 'umid': 'umidValue', - }; - const response = trustpidSubmodule.getId(); - expect(response).to.have.property('callback'); - expect(response.callback.toString()).contain('result(callback)'); - - if (typeof response.callback === 'function') { - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('uat.mno.link')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - response.callback(function (result) { - expect(result).to.not.be.null; - expect(result).to.have.property('trustpid'); - expect(result.trustpid).to.be.equal('umidValue-xxxx'); - done() - }) - } - }); - - it('returns null if domains don\'t match', (done) => { - const idGraph = { - 'domain': 'uat.mno.link', - 'umid': 'umidValue', - }; - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('differentDomainValue')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - - const response = trustpidSubmodule.getId(); - expect(response).to.have.property('callback'); - expect(response.callback.toString()).contain('result(callback)'); - - if (typeof response.callback === 'function') { - setTimeout(() => { - expect(JSON.parse(storage.getDataFromLocalStorage(connectDomainKey))).to.be.equal('differentDomainValue'); - }, 100) - response.callback(function (result) { - expect(result).to.be.null; - done() - }) - } - }); - - it('returns {trustpid: data.trustpid} if we have the right data stored in the localstorage right after 500ms delay', (done) => { - const idGraph = { - 'domain': 'uat.mno.link', - 'umid': 'umidValue', - }; - - const response = trustpidSubmodule.getId(); - expect(response).to.have.property('callback'); - expect(response.callback.toString()).contain('result(callback)'); - - if (typeof response.callback === 'function') { - setTimeout(() => { - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('uat.mno.link')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - }, 500); - response.callback(function (result) { - expect(result).to.not.be.null; - expect(result).to.have.property('trustpid'); - expect(result.trustpid).to.be.equal('umidValue-xxxx'); - done() - }) - } - }); - - it('returns null if we have the data stored in the localstorage after 500ms delay and the max (waiting) delay is only 200ms ', (done) => { - const idGraph = { - 'domain': 'uat.mno.link', - 'umid': 'umidValue', - }; - - const response = trustpidSubmodule.getId({params: {maxDelayTime: 200}}); - expect(response).to.have.property('callback'); - expect(response.callback.toString()).contain('result(callback)'); - - if (typeof response.callback === 'function') { - setTimeout(() => { - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('uat.mno.link')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - }, 500); - response.callback(function (result) { - expect(result).to.be.null; - done() - }) - } - }); - }); - - describe('trustpid decode()', () => { - const VALID_API_RESPONSES = [ - { - expected: '32a97f612', - payload: { - trustpid: '32a97f612' - } - }, - { - expected: '32a97f61', - payload: { - trustpid: '32a97f61', - } - }, - ]; - VALID_API_RESPONSES.forEach(responseData => { - it('should return a newly constructed object with the trustpid for a payload with {trustpid: value}', () => { - expect(trustpidSubmodule.decode(responseData.payload)).to.deep.equal( - {trustpid: responseData.expected} - ); - }); - }); - - [{}, '', {foo: 'bar'}].forEach((response) => { - it(`should return null for an invalid response "${JSON.stringify(response)}"`, () => { - expect(trustpidSubmodule.decode(response)).to.be.null; - }); - }); - }); - - describe('trustpid messageHandler for acronyms', () => { - afterEach(() => { - storage.removeDataFromLocalStorage(connectDataKey); - storage.removeDataFromLocalStorage(connectDomainKey); - }); - - const domains = [ - {domain: 'tmi.mno.link', acronym: 'ndye'}, - {domain: 'tmi.vodafone.de', acronym: 'pqnx'}, - {domain: 'tmi.telekom.de', acronym: 'avgw'}, - {domain: 'tmi.tmid.es', acronym: 'kjws'}, - {domain: 'uat.mno.link', acronym: 'xxxx'}, - {domain: 'es.tmiservice.orange.com', acronym: 'aplw'}, - ]; - - domains.forEach(({domain, acronym}) => { - it(`correctly sets trustpid value and acronym to ${acronym} for ${domain} domain`, (done) => { - const idGraph = { - 'domain': domain, - 'umid': 'umidValue', - }; - - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify(domain)); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - - const eventData = { - data: `{\"msgType\":\"MNOSELECTOR\",\"body\":{\"url\":\"https://${domain}/some/path\"}}` - }; - - window.dispatchEvent(new MessageEvent('message', eventData)); - - const response = trustpidSubmodule.getId(); - expect(response).to.have.property('id'); - expect(response.id).to.have.property('trustpid'); - expect(response.id.trustpid).to.be.equal(`umidValue-${acronym}`); - done(); - }); - }); - }); -}); diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index b34813948fc..a8caed3ad0e 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -40,6 +40,229 @@ describe('TrustXAdapter', function () { }); describe('buildRequests', function () { + function parseRequest(url) { + const res = {}; + url.split('&').forEach((it) => { + const couple = it.split('='); + res[couple[0]] = decodeURIComponent(couple[1]); + }); + return res; + } + + const bidderRequest = { + refererInfo: { + referer: 'https://example.com' + } + }; + const referrer = bidderRequest.refererInfo.referer; + + let bidRequests = [ + { + 'bidder': 'trustx', + 'params': { + 'uid': '43' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '43' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90], [300, 250]], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '45' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '42dbe3a7168a6a', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should attach valid params to the tag', function () { + const request = spec.buildRequests([bidRequests[0]], bidderRequest)[0]; + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '43'); + expect(payload).to.have.property('sizes', '300x250,300x600'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('wrapperType', 'Prebid_js'); + expect(payload).to.have.property('wrapperVersion', '$prebid.version$'); + }); + + it('sizes must not be duplicated', function () { + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '43,43,45'); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + }); + + it('pt parameter must be "gross" if params.priceType === "gross"', function () { + bidRequests[1].params.priceType = 'gross'; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'gross'); + expect(payload).to.have.property('auids', '43,43,45'); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + delete bidRequests[1].params.priceType; + }); + + it('pt parameter must be "net" or "gross"', function () { + bidRequests[1].params.priceType = 'some'; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '43,43,45'); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + delete bidRequests[1].params.priceType; + }); + + it('if gdprConsent is present payload must have gdpr params', function () { + const bidderRequestWithGDPR = Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: true}}, bidderRequest); + const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR)[0]; + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('gdpr_consent', 'AAA'); + expect(payload).to.have.property('gdpr_applies', '1'); + }); + + it('if gdprApplies is false gdpr_applies must be 0', function () { + const bidderRequestWithGDPR = Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: false}}, bidderRequest); + const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR)[0]; + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('gdpr_consent', 'AAA'); + expect(payload).to.have.property('gdpr_applies', '0'); + }); + + it('if gdprApplies is undefined gdpr_applies must be 1', function () { + const bidderRequestWithGDPR = Object.assign({gdprConsent: {consentString: 'AAA'}}, bidderRequest); + const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR)[0]; + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('gdpr_consent', 'AAA'); + expect(payload).to.have.property('gdpr_applies', '1'); + }); + + it('if usPrivacy is present payload must have us_privacy param', function () { + const bidderRequestWithUSP = Object.assign({uspConsent: '1YNN'}, bidderRequest); + const request = spec.buildRequests(bidRequests, bidderRequestWithUSP)[0]; + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('us_privacy', '1YNN'); + }); + + it('should convert keyword params to proper form and attaches to request', function () { + const bidRequestWithKeywords = [].concat(bidRequests); + bidRequestWithKeywords[1] = Object.assign({}, + bidRequests[1], + { + params: { + uid: '43', + keywords: { + single: 'val', + singleArr: ['val'], + singleArrNum: [5], + multiValMixed: ['value1', 2, 'value3'], + singleValNum: 123, + emptyStr: '', + emptyArr: [''], + badValue: {'foo': 'bar'} // should be dropped + } + } + } + ); + + const request = spec.buildRequests(bidRequestWithKeywords, bidderRequest)[0]; + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload.keywords).to.be.an('string'); + payload.keywords = JSON.parse(payload.keywords); + + expect(payload.keywords).to.deep.equal([{ + 'key': 'single', + 'value': ['val'] + }, { + 'key': 'singleArr', + 'value': ['val'] + }, { + 'key': 'singleArrNum', + 'value': ['5'] + }, { + 'key': 'multiValMixed', + 'value': ['value1', '2', 'value3'] + }, { + 'key': 'singleValNum', + 'value': ['123'] + }, { + 'key': 'emptyStr' + }, { + 'key': 'emptyArr' + }]); + }); + + it('should attach rtd segments as keywords', function () { + const bidRequestWithKeywords = [].concat(bidRequests); + bidRequestWithKeywords[1] = Object.assign({}, + bidRequests[1], + { + rtd: { + p_standard: { + targeting: { + segments: ['perm_seg_1', 'perm_seg_2'] + } + }, + jwplayer: { + targeting: { + segments: ['jwp_seg_1', 'jwp_seg_2'] + } + } + } + } + ); + + const request = spec.buildRequests(bidRequestWithKeywords, bidderRequest)[0]; + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload.keywords).to.be.an('string'); + payload.keywords = JSON.parse(payload.keywords); + + expect(payload.keywords).to.deep.equal([{ + 'key': 'jwpseg', + 'value': ['jwp_seg_1', 'jwp_seg_2'] + }, { + 'key': 'p_standard', + 'value': ['perm_seg_1', 'perm_seg_2'] + }]); + }); + }); + + describe('buildRequests with new format', function () { function parseRequest(data) { return JSON.parse(data); } @@ -57,6 +280,7 @@ describe('TrustXAdapter', function () { 'params': { 'uid': '43', 'bidFloor': 1.25, + 'useNewFormat': true }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], @@ -73,6 +297,7 @@ describe('TrustXAdapter', function () { 'bidder': 'trustx', 'params': { 'uid': '44', + 'useNewFormat': true }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], @@ -84,6 +309,7 @@ describe('TrustXAdapter', function () { 'bidder': 'trustx', 'params': { 'uid': '45', + 'useNewFormat': true }, 'adUnitCode': 'adunit-code-2', 'sizes': [[728, 90]], @@ -101,6 +327,7 @@ describe('TrustXAdapter', function () { 'bidder': 'trustx', 'params': { 'uid': '41', + 'useNewFormat': true }, 'adUnitCode': 'adunit-code-2', 'sizes': [[728, 90]], @@ -120,7 +347,7 @@ describe('TrustXAdapter', function () { ]; it('should attach valid params to the tag', function () { - const request = spec.buildRequests([bidRequests[0]], bidderRequest); + const request = spec.buildRequests([bidRequests[0]], bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.deep.equal({ @@ -148,7 +375,7 @@ describe('TrustXAdapter', function () { }); it('make possible to process request without mediaTypes', function () { - const request = spec.buildRequests([bidRequests[0], bidRequests[1]], bidderRequest); + const request = spec.buildRequests([bidRequests[0], bidRequests[1]], bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.deep.equal({ @@ -185,7 +412,7 @@ describe('TrustXAdapter', function () { }); it('should attach valid params to the video tag', function () { - const request = spec.buildRequests(bidRequests.slice(0, 3), bidderRequest); + const request = spec.buildRequests(bidRequests.slice(0, 3), bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.deep.equal({ @@ -231,7 +458,7 @@ describe('TrustXAdapter', function () { }); it('should support mixed mediaTypes', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.deep.equal({ @@ -292,7 +519,7 @@ describe('TrustXAdapter', function () { it('if gdprConsent is present payload must have gdpr params', function () { const gdprBidderRequest = Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: true}}, bidderRequest); - const request = spec.buildRequests(bidRequests, gdprBidderRequest); + const request = spec.buildRequests(bidRequests, gdprBidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.have.property('user'); @@ -305,7 +532,7 @@ describe('TrustXAdapter', function () { it('if usPrivacy is present payload must have us_privacy param', function () { const bidderRequestWithUSP = Object.assign({uspConsent: '1YNN'}, bidderRequest); - const request = spec.buildRequests(bidRequests, bidderRequestWithUSP); + const request = spec.buildRequests(bidRequests, bidderRequestWithUSP)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.have.property('regs'); @@ -338,7 +565,7 @@ describe('TrustXAdapter', function () { userIdAsEids: eids }, bid); }); - const request = spec.buildRequests(bidRequestsWithUserIds, bidderRequest); + const request = spec.buildRequests(bidRequestsWithUserIds, bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.have.property('user'); @@ -362,7 +589,7 @@ describe('TrustXAdapter', function () { schain: schain }, bid); }); - const request = spec.buildRequests(bidRequestsWithSChain, bidderRequest); + const request = spec.buildRequests(bidRequestsWithSChain, bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.have.property('source'); @@ -386,7 +613,7 @@ describe('TrustXAdapter', function () { } }, bid); }); - const request = spec.buildRequests(bidRequestsWithJwTargeting, bidderRequest); + const request = spec.buildRequests(bidRequestsWithJwTargeting, bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.have.property('user'); @@ -401,282 +628,60 @@ describe('TrustXAdapter', function () { expect(payload.site.content).to.deep.equal(jsContent); }); - it('should have user.data filled from config ortb2.user.data', function () { - const userData = [ - { - name: 'someName', - segment: [1, 2, { anyKey: 'anyVal' }, 'segVal', { id: 'segId' }, { value: 'segValue' }, { id: 'segId2', name: 'segName' }] - }, - { - name: 'permutive.com', - segment: [1, 2, 'segVal', { id: 'segId' }, { anyKey: 'anyVal' }, { value: 'segValue' }, { id: 'segId2', name: 'segName' }] - }, - { - someKey: 'another data' - } - ]; - - const getConfigStub = sinon.stub(config, 'getConfig').callsFake( - arg => arg === 'ortb2.user.data' ? userData : null); - const request = spec.buildRequests([bidRequests[0]], bidderRequest); - const payload = parseRequest(request.data); - expect(payload.user.data).to.deep.equal(userData); - getConfigStub.restore(); - }); - - it('should have right value in user.data when jwpsegments are present', function () { - const userData = [ - { - name: 'someName', - segment: [1, 2, { anyKey: 'anyVal' }, 'segVal', { id: 'segId' }, { value: 'segValue' }, { id: 'segId2', name: 'segName' }] - }, - { - name: 'permutive.com', - segment: [1, 2, 'segVal', { id: 'segId' }, { anyKey: 'anyVal' }, { value: 'segValue' }, { id: 'segId2', name: 'segName' }] - }, - { - someKey: 'another data' - } - ]; - const getConfigStub = sinon.stub(config, 'getConfig').callsFake( - arg => arg === 'ortb2.user.data' ? userData : null); - - const jsContent = {id: 'test_jw_content_id'}; - const jsSegments = ['test_seg_1', 'test_seg_2']; - const bidRequestsWithJwTargeting = Object.assign({}, bidRequests[0], { - rtd: { - jwplayer: { - targeting: { - segments: jsSegments, - content: jsContent + it('if segment is present in permutive targeting, payload must have right params', function () { + const permSegments = ['test_perm_1', 'test_perm_2']; + const bidRequestsWithPermutiveTargeting = bidRequests.map((bid) => { + return Object.assign({ + rtd: { + p_standard: { + targeting: { + segments: permSegments + } } } - } + }, bid); }); - const request = spec.buildRequests([bidRequestsWithJwTargeting], bidderRequest); + const request = spec.buildRequests(bidRequestsWithPermutiveTargeting, bidderRequest)[0]; + expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); + expect(payload).to.have.property('user'); expect(payload.user.data).to.deep.equal([{ - name: 'iow_labs_pub_data', + name: 'permutive', segment: [ - {name: 'jwpseg', value: jsSegments[0]}, - {name: 'jwpseg', value: jsSegments[1]} + {name: 'p_standard', value: permSegments[0]}, + {name: 'p_standard', value: permSegments[1]} ] - }, ...userData]); - getConfigStub.restore(); + }]); }); it('should contain the keyword values if it present in ortb2.(site/user)', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( - arg => arg === 'ortb2.user' ? {'keywords': 'foo,any'} : (arg === 'ortb2.site' ? {'keywords': 'bar'} : null)); - const keywords = { - 'site': { - 'somePublisher': [ - { - 'name': 'someName', - 'brandsafety': ['disaster'], - 'topic': ['stress', 'fear'] - } - ] - }, - 'user': { - 'formatedPublisher': [ - { - 'name': 'fomatedName', - 'segments': [ - { 'name': 'segName1', 'value': 'segVal1' }, - { 'name': 'segName2', 'value': 'segVal2' } - ] - } - ] - } - }; - const bidRequestWithKW = { ...bidRequests[0], params: { ...bidRequests[0].params, keywords } } - const request = spec.buildRequests([bidRequestWithKW], bidderRequest); + arg => arg === 'ortb2.user' ? {'keywords': 'foo'} : (arg === 'ortb2.site' ? {'keywords': 'bar'} : null)); + const request = spec.buildRequests([bidRequests[0]], bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload.ext.keywords).to.deep.equal({ - 'site': { - 'somePublisher': [ - { - 'name': 'someName', - 'segments': [ - { 'name': 'brandsafety', 'value': 'disaster' }, - { 'name': 'topic', 'value': 'stress' }, - { 'name': 'topic', 'value': 'fear' } - ] - } - ], - 'ortb2': [ - { - 'name': 'keywords', - 'segments': [ - { 'name': 'keywords', 'value': 'bar' } - ] - } - ] - }, - 'user': { - 'formatedPublisher': [ - { - 'name': 'fomatedName', - 'segments': [ - { 'name': 'segName1', 'value': 'segVal1' }, - { 'name': 'segName2', 'value': 'segVal2' } - ] - } - ], - 'ortb2': [ - { - 'name': 'keywords', - 'segments': [ - { 'name': 'keywords', 'value': 'foo' }, - { 'name': 'keywords', 'value': 'any' } - ] - } - ] - } - }); + expect(payload.ext.keywords).to.deep.equal([{'key': 'user', 'value': ['foo']}, {'key': 'context', 'value': ['bar']}]); getConfigStub.restore(); }); - it('should be right tmax when timeout in config is less then timeout in bidderRequest', function() { + it('shold be right tmax when timeout in config is less then timeout in bidderRequest', function() { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'bidderTimeout' ? 2000 : null); - const request = spec.buildRequests([bidRequests[0]], bidderRequest); + const request = spec.buildRequests([bidRequests[0]], bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload.tmax).to.equal(2000); getConfigStub.restore(); }); - it('should be right tmax when timeout in bidderRequest is less then timeout in config', function() { + it('shold be right tmax when timeout in bidderRequest is less then timeout in config', function() { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'bidderTimeout' ? 5000 : null); - const request = spec.buildRequests([bidRequests[0]], bidderRequest); + const request = spec.buildRequests([bidRequests[0]], bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload.tmax).to.equal(3000); getConfigStub.restore(); }); - it('should contain imp[].ext.data.adserver if available', function() { - const ortb2Imp = [{ - ext: { - data: { - adserver: { - name: 'ad_server_name', - adslot: '/111111/slot' - }, - pbadslot: '/111111/slot' - } - } - }, { - ext: { - data: { - adserver: { - name: 'ad_server_name', - adslot: '/222222/slot' - }, - pbadslot: '/222222/slot' - } - } - }]; - const bidRequestsWithOrtb2Imp = bidRequests.slice(0, 3).map((bid, ind) => { - return Object.assign(ortb2Imp[ind] ? { ortb2Imp: ortb2Imp[ind] } : {}, bid); - }); - const request = spec.buildRequests(bidRequestsWithOrtb2Imp, bidderRequest); - expect(request.data).to.be.an('string'); - const payload = parseRequest(request.data); - expect(payload.imp[0].ext).to.deep.equal({ - divid: bidRequests[0].adUnitCode, - data: ortb2Imp[0].ext.data, - gpid: ortb2Imp[0].ext.data.adserver.adslot - }); - expect(payload.imp[1].ext).to.deep.equal({ - divid: bidRequests[1].adUnitCode, - data: ortb2Imp[1].ext.data, - gpid: ortb2Imp[1].ext.data.adserver.adslot - }); - expect(payload.imp[2].ext).to.deep.equal({ - divid: bidRequests[2].adUnitCode - }); - }); - it('should contain imp[].instl if available', function() { - const ortb2Imp = [{ - instl: 1 - }, { - instl: 2, - ext: { - data: { - adserver: { - name: 'ad_server_name', - adslot: '/222222/slot' - }, - pbadslot: '/222222/slot' - } - } - }]; - const bidRequestsWithOrtb2Imp = bidRequests.slice(0, 3).map((bid, ind) => { - return Object.assign(ortb2Imp[ind] ? { ortb2Imp: ortb2Imp[ind] } : {}, bid); - }); - const request = spec.buildRequests(bidRequestsWithOrtb2Imp, bidderRequest); - expect(request.data).to.be.an('string'); - const payload = parseRequest(request.data); - expect(payload.imp[0].instl).to.equal(1); - expect(payload.imp[1].ext).to.deep.equal({ - divid: bidRequests[1].adUnitCode, - data: ortb2Imp[1].ext.data, - gpid: ortb2Imp[1].ext.data.adserver.adslot - }); - expect(payload.imp[1].instl).to.equal(2); - expect(payload.imp[2].ext).to.deep.equal({ - divid: bidRequests[2].adUnitCode - }); - expect(payload.imp[2].instl).to.be.undefined; - }); - it('all id like request fields must be a string', function () { - const bidderRequestWithNumId = Object.assign({}, bidderRequest, { bidderRequestId: 123123, auctionId: 345345543 }); - - let bidRequestWithNumId = { - 'bidder': 'trustx', - 'params': { - 'uid': 43, - }, - 'adUnitCode': 111111, - 'sizes': [[300, 250], [300, 600]], - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250], [300, 600]] - } - }, - 'bidId': 23423423, - 'bidderRequestId': 123123, - 'auctionId': 345345543, - }; - - const request = spec.buildRequests([bidRequestWithNumId], bidderRequestWithNumId); - expect(request.data).to.be.an('string'); - const payload = parseRequest(request.data); - expect(payload).to.deep.equal({ - 'id': '123123', - 'site': { - 'page': referrer - }, - 'tmax': bidderRequest.timeout, - 'source': { - 'tid': '345345543', - 'ext': {'wrapper': 'Prebid_js', 'wrapper_version': '$prebid.version$'} - }, - 'imp': [{ - 'id': '23423423', - 'tagid': '43', - 'ext': {'divid': '111111'}, - 'banner': { - 'w': 300, - 'h': 250, - 'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}] - } - }] - }); - }); describe('floorModule', function () { const floorTestData = { @@ -689,7 +694,7 @@ describe('TrustXAdapter', function () { } }, bidRequests[1]); it('should return the value from getFloor if present', function () { - const request = spec.buildRequests([bidRequest], bidderRequest); + const request = spec.buildRequests([bidRequest], bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload.imp[0].bidfloor).to.equal(floorTestData.floor); @@ -698,7 +703,7 @@ describe('TrustXAdapter', function () { const bidfloor = 0.80; const bidRequestsWithFloor = { ...bidRequest }; bidRequestsWithFloor.params = Object.assign({bidFloor: bidfloor}, bidRequestsWithFloor.params); - const request = spec.buildRequests([bidRequestsWithFloor], bidderRequest); + const request = spec.buildRequests([bidRequestsWithFloor], bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload.imp[0].bidfloor).to.equal(floorTestData.floor); @@ -707,7 +712,7 @@ describe('TrustXAdapter', function () { const bidfloor = 1.80; const bidRequestsWithFloor = { ...bidRequest }; bidRequestsWithFloor.params = Object.assign({bidFloor: bidfloor}, bidRequestsWithFloor.params); - const request = spec.buildRequests([bidRequestsWithFloor], bidderRequest); + const request = spec.buildRequests([bidRequestsWithFloor], bidderRequest)[0]; expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload.imp[0].bidfloor).to.equal(bidfloor); @@ -717,10 +722,10 @@ describe('TrustXAdapter', function () { describe('interpretResponse', function () { const responses = [ - {'bid': [{'impid': '659423fff799cb', 'price': 1.15, 'adm': '
test content 1
', 'auid': 43, 'h': 250, 'w': 300, 'adomain': ['somedomain.com']}], 'seat': '1'}, - {'bid': [{'impid': '4dff80cc4ee346', 'price': 0.5, 'adm': '
test content 2
', 'auid': 44, 'h': 600, 'w': 300}], 'seat': '1'}, - {'bid': [{'impid': '5703af74d0472a', 'price': 0.15, 'adm': '
test content 3
', 'auid': 43, 'h': 90, 'w': 728}], 'seat': '1'}, - {'bid': [{'impid': '659423faac49cb', 'price': 0, 'auid': 45, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 43, 'h': 250, 'w': 300, 'adomain': ['somedomain.com']}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 44, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 43, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 45, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0, 'adm': '
test content 5
', 'h': 250, 'w': 300}], 'seat': '1'}, undefined, {'bid': [], 'seat': '1'}, @@ -741,7 +746,7 @@ describe('TrustXAdapter', function () { 'auctionId': '1cbd2feafe5e8b', } ]; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests)[0]; const expectedResponse = [ { 'requestId': '659423fff799cb', @@ -753,7 +758,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 1
', 'currency': 'USD', 'mediaType': 'banner', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': ['somedomain.com'] @@ -774,7 +779,7 @@ describe('TrustXAdapter', function () { }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], - 'bidId': '659423fff799cb', + 'bidId': '300bfeb0d71a5b', 'bidderRequestId': '2c2bb1972df9a', 'auctionId': '1fa09aee5c8c99', }, @@ -801,10 +806,10 @@ describe('TrustXAdapter', function () { 'auctionId': '1fa09aee5c8c99', } ]; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests)[0]; const expectedResponse = [ { - 'requestId': '659423fff799cb', + 'requestId': '300bfeb0d71a5b', 'cpm': 1.15, 'creativeId': 43, 'dealId': undefined, @@ -813,7 +818,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 1
', 'currency': 'USD', 'mediaType': 'banner', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': ['somedomain.com'] @@ -829,7 +834,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 2
', 'currency': 'USD', 'mediaType': 'banner', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -845,7 +850,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 3
', 'currency': 'USD', 'mediaType': 'banner', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -893,18 +898,18 @@ describe('TrustXAdapter', function () { 'auctionId': '1fa09aee5c84d34', } ]; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests)[0]; const result = spec.interpretResponse({'body': {'seatbid': responses.slice(3)}}, request); expect(result.length).to.equal(0); }); it('complicated case', function () { const fullResponse = [ - {'bid': [{'impid': '2164be6358b9', 'price': 1.15, 'adm': '
test content 1
', 'auid': 43, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'impid': '4e111f1b66e4', 'price': 0.5, 'adm': '
test content 2
', 'auid': 44, 'h': 600, 'w': 300}], 'seat': '1'}, - {'bid': [{'impid': '26d6f897b516', 'price': 0.15, 'adm': '
test content 3
', 'auid': 43, 'h': 90, 'w': 728}], 'seat': '1'}, - {'bid': [{'impid': '326bde7fbf69', 'price': 0.15, 'adm': '
test content 4
', 'auid': 43, 'h': 600, 'w': 300}], 'seat': '1'}, - {'bid': [{'impid': '1751cd90161', 'price': 0.5, 'adm': '
test content 5
', 'auid': 44, 'h': 600, 'w': 350}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 43, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 44, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 43, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 4
', 'auid': 43, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 5
', 'auid': 44, 'h': 600, 'w': 350}], 'seat': '1'}, ]; const bidRequests = [ { @@ -963,7 +968,7 @@ describe('TrustXAdapter', function () { 'auctionId': '32a1f276cb87cb8', } ]; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests)[0]; const expectedResponse = [ { 'requestId': '2164be6358b9', @@ -975,7 +980,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 1
', 'currency': 'USD', 'mediaType': 'banner', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -991,7 +996,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 2
', 'currency': 'USD', 'mediaType': 'banner', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -1007,7 +1012,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 3
', 'currency': 'USD', 'mediaType': 'banner', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -1023,23 +1028,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 4
', 'currency': 'USD', 'mediaType': 'banner', - 'netRevenue': false, - 'ttl': 360, - 'meta': { - 'advertiserDomains': [] - }, - }, - { - 'requestId': '1751cd90161', - 'cpm': 0.5, - 'creativeId': 44, - 'dealId': undefined, - 'width': 350, - 'height': 600, - 'ad': '
test content 5
', - 'currency': 'USD', - 'mediaType': 'banner', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -1053,8 +1042,8 @@ describe('TrustXAdapter', function () { it('dublicate uids and sizes in one slot', function () { const fullResponse = [ - {'bid': [{'impid': '5126e301f4be', 'price': 1.15, 'adm': '
test content 1
', 'auid': 43, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'impid': '57b2ebe70e16', 'price': 0.5, 'adm': '
test content 2
', 'auid': 43, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 43, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 43, 'h': 250, 'w': 300}], 'seat': '1'}, ]; const bidRequests = [ { @@ -1091,7 +1080,7 @@ describe('TrustXAdapter', function () { 'auctionId': '35bcbc0f7e79c', } ]; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests)[0]; const expectedResponse = [ { 'requestId': '5126e301f4be', @@ -1103,7 +1092,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 1
', 'currency': 'USD', 'mediaType': 'banner', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -1119,7 +1108,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 2
', 'currency': 'USD', 'mediaType': 'banner', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -1165,30 +1154,13 @@ describe('TrustXAdapter', function () { 'context': 'instream' } } - }, - { - 'bidder': 'trustx', - 'params': { - 'uid': '52' - }, - 'adUnitCode': 'adunit-code-1', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '23312a43bc42', - 'bidderRequestId': '20394420a762a2', - 'auctionId': '140132d07b031', - 'mediaTypes': { - 'video': { - 'context': 'instream' - } - } } ]; const response = [ - {'bid': [{'impid': '57dfefb80eca', 'price': 1.15, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 50, content_type: 'video', w: 300, h: 600}], 'seat': '2'}, - {'bid': [{'impid': '5126e301f4be', 'price': 1.00, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 51, content_type: 'video'}], 'seat': '2'}, - {'bid': [{'impid': '23312a43bc42', 'price': 2.00, 'nurl': 'https://some_test_vast_url.com', 'auid': 52, content_type: 'video', w: 300, h: 600}], 'seat': '2'}, + {'bid': [{'price': 1.15, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 50, content_type: 'video', w: 300, h: 600}], 'seat': '2'}, + {'bid': [{'price': 1.00, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 51, content_type: 'video'}], 'seat': '2'} ]; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests)[0]; const expectedResponse = [ { 'requestId': '57dfefb80eca', @@ -1199,7 +1171,7 @@ describe('TrustXAdapter', function () { 'height': 600, 'currency': 'USD', 'mediaType': 'video', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -1208,23 +1180,7 @@ describe('TrustXAdapter', function () { 'adResponse': { 'content': '\n<\/Ad>\n<\/VAST>' } - }, - { - 'requestId': '23312a43bc42', - 'cpm': 2.00, - 'creativeId': 52, - 'dealId': undefined, - 'width': 300, - 'height': 600, - 'currency': 'USD', - 'mediaType': 'video', - 'netRevenue': false, - 'ttl': 360, - 'meta': { - 'advertiserDomains': [] - }, - 'vastUrl': 'https://some_test_vast_url.com', - }, + } ]; const result = spec.interpretResponse({'body': {'seatbid': response}}, request); @@ -1282,11 +1238,11 @@ describe('TrustXAdapter', function () { } ]; const response = [ - {'bid': [{'impid': 'e6e65553fc8', 'price': 1.15, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 50, content_type: 'video', w: 300, h: 600}], 'seat': '2'}, - {'bid': [{'impid': 'c8fdcb3f269f', 'price': 1.00, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 51, content_type: 'video', w: 300, h: 250}], 'seat': '2'}, - {'bid': [{'impid': '1de036c37685', 'price': 1.20, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 52, content_type: 'video', w: 300, h: 250}], 'seat': '2'} + {'bid': [{'price': 1.15, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 50, content_type: 'video', w: 300, h: 600}], 'seat': '2'}, + {'bid': [{'price': 1.00, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 51, content_type: 'video', w: 300, h: 250}], 'seat': '2'}, + {'bid': [{'price': 1.20, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 52, content_type: 'video', w: 300, h: 250}], 'seat': '2'} ]; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests)[0]; const expectedResponse = [ { 'requestId': 'e6e65553fc8', @@ -1297,7 +1253,7 @@ describe('TrustXAdapter', function () { 'height': 600, 'currency': 'USD', 'mediaType': 'video', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -1317,7 +1273,7 @@ describe('TrustXAdapter', function () { 'height': 250, 'currency': 'USD', 'mediaType': 'video', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] @@ -1337,7 +1293,7 @@ describe('TrustXAdapter', function () { 'height': 250, 'currency': 'USD', 'mediaType': 'video', - 'netRevenue': false, + 'netRevenue': true, 'ttl': 360, 'meta': { 'advertiserDomains': [] diff --git a/test/spec/modules/ttdBidAdapter_spec.js b/test/spec/modules/ttdBidAdapter_spec.js deleted file mode 100644 index 099e5e56c33..00000000000 --- a/test/spec/modules/ttdBidAdapter_spec.js +++ /dev/null @@ -1,1313 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/ttdBidAdapter'; -import { deepClone } from 'src/utils.js'; -import { config } from 'src/config'; - -describe('ttdBidAdapter', function () { - function testBuildRequests(bidRequests, bidderRequestBase) { - let clonedBidderRequest = deepClone(bidderRequestBase); - clonedBidderRequest.bids = bidRequests; - return spec.buildRequests(bidRequests, clonedBidderRequest); - } - - describe('isBidRequestValid', function() { - function makeBid() { - return { - 'bidder': 'ttd', - 'params': { - 'supplySourceId': 'supplier', - 'publisherId': '22222222', - 'placementId': 'some-PlacementId_1', - 'siteId': 'testSiteId' - }, - 'mediaTypes': { - 'banner': { - 'sizes': [ - [300, 250] - ] - } - }, - 'adUnitCode': 'adunit-code', - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }; - } - - describe('core', function () { - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(makeBid())).to.equal(true); - }); - - it('should return false when publisherId not passed', function () { - let bid = makeBid(); - delete bid.params.publisherId; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when supplySourceId not passed', function () { - let bid = makeBid(); - delete bid.params.supplySourceId; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when publisherId is longer than 64 characters', function () { - let bid = makeBid(); - bid.params.publisherId = '1111111111111111111111111111111111111111111111111111111111111111111111'; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when siteId not passed', function () { - let bid = makeBid(); - delete bid.params.siteId; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when siteId is longer than 50 characters', function () { - let bid = makeBid(); - bid.params.siteId = '1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111' - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when placementId not passed', function () { - let bid = makeBid(); - delete bid.params.placementId; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when the placementId is longer than 128 characters', function () { - let bid = makeBid(); - bid.params.placementId = '1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111'; // 130 characters - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false if neither mediaTypes.banner nor mediaTypes.video is passed', function () { - let bid = makeBid(); - delete bid.mediaTypes - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('banner', function () { - it('should return true if banner.pos is passed correctly', function () { - let bid = makeBid(); - bid.mediaTypes.banner.pos = 1; - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - }); - - describe('video', function () { - function makeBid() { - return { - 'bidder': 'ttd', - 'params': { - 'supplySourceId': 'supplier', - 'publisherId': '22222222', - 'siteId': 'testSiteId123', - 'placementId': 'somePlacementId' - }, - 'mediaTypes': { - 'video': { - 'minduration': 5, - 'maxduration': 30, - 'playerSize': [640, 480], - 'api': [1, 3], - 'mimes': ['video/mp4'], - 'protocols': [2, 3, 5, 6] - } - }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250] - ], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }; - } - - it('should return true if required parameters are passed', function () { - let bid = makeBid(); - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false if maxduration is missing', function () { - let bid = makeBid(); - delete bid.mediaTypes.video.maxduration; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false if api is missing', function () { - let bid = makeBid(); - delete bid.mediaTypes.video.api; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false if mimes is missing', function () { - let bid = makeBid(); - delete bid.mediaTypes.video.mimes; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false if protocols is missing', function () { - let bid = makeBid(); - delete bid.mediaTypes.video.protocols; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - }); - - describe('getUserSyncs', function () { - it('to check the user sync iframe', function () { - const syncOptions = { - pixelEnabled: true - }; - const gdprConsentString = 'BON3G4EON3G4EAAABAENAA____ABl____A'; - const gdprConsent = { - consentString: gdprConsentString, - gdprApplies: true - }; - const uspConsent = '1YYY'; - - let syncs = spec.getUserSyncs(syncOptions, [], gdprConsent, uspConsent); - expect(syncs).to.have.lengthOf(1); - expect(syncs[0].type).to.equal('image'); - - let params = new URLSearchParams(new URL(syncs[0].url).search); - expect(params.get('us_privacy')).to.equal(uspConsent); - expect(params.get('ust')).to.equal('image'); - expect(params.get('gdpr')).to.equal('1'); - expect(params.get('gdpr_consent')).to.equal(gdprConsentString); - }); - }); - - describe('buildRequests-banner', function () { - const baseBannerBidRequests = [{ - 'bidder': 'ttd', - 'params': { - 'supplySourceId': 'supplier', - 'publisherId': '13144370', - 'placementId': '1gaa015', - 'siteId': 'testSiteId123' - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250], [300, 600]] - } - }, - 'sizes': [[300, 250], [300, 600]], - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '8651474f-58b1-4368-b812-84f8c937a099', - 'bidId': '243310435309b5', - 'bidderRequestId': '18084284054531', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'src': 'client', - 'bidRequestsCount': 1 - }]; - - const baseBidderRequest = { - 'bidderCode': 'ttd', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'bidderRequestId': '18084284054531', - 'auctionStart': 1540945362095, - 'timeout': 3000, - 'refererInfo': { - 'referer': 'https://www.example.com/test', - 'reachedTop': true, - 'numIframes': 0, - 'stack': [ - 'https://www.example.com/test' - ] - }, - 'start': 1540945362099, - 'doneCbCallCount': 0 - }; - - it('sends bid request to our endpoint that makes sense', function () { - const request = testBuildRequests(baseBannerBidRequests, baseBidderRequest); - expect(request.method).to.equal('POST'); - expect(request.url).to.be.not.empty; - expect(request.data).to.be.not.null; - }); - - it('sets impression id to ad unit\'s bid id', function () { - const requestBody = testBuildRequests(baseBannerBidRequests, baseBidderRequest).data; - expect(requestBody.imp[0].id).to.equal('243310435309b5'); - }); - - it('sends bid requests to the correct endpoint', function () { - const url = testBuildRequests(baseBannerBidRequests, baseBidderRequest).url; - expect(url).to.equal('https://direct.adsrvr.org/bid/bidder/supplier'); - }); - - it('sends publisher id, site id, and placement id', function () { - const requestBody = testBuildRequests(baseBannerBidRequests, baseBidderRequest).data; - expect(requestBody.site).to.be.not.null; - expect(requestBody.site.publisher).to.be.not.null; - expect(requestBody.imp[0].tagid).to.be.not.null; - expect(requestBody.site.publisher.id).to.equal(baseBannerBidRequests[0].params.publisherId); - expect(requestBody.site.id).to.equal(baseBannerBidRequests[0].params.siteId); - expect(requestBody.imp[0].tagid).to.equal(baseBannerBidRequests[0].params.placementId); - }); - - it('includes the ad size in the bid request', function () { - const requestBody = testBuildRequests(baseBannerBidRequests, baseBidderRequest).data; - expect(requestBody.imp[0].banner.format[0].w).to.equal(300); - expect(requestBody.imp[0].banner.format[0].h).to.equal(250); - expect(requestBody.imp[0].banner.format[1].w).to.equal(300); - expect(requestBody.imp[0].banner.format[1].h).to.equal(600); - }); - - it('includes the detected referer in the bid request', function () { - const requestBody = testBuildRequests(baseBannerBidRequests, baseBidderRequest).data; - expect(requestBody.site.page).to.equal('https://www.example.com/test'); - }); - - it('sets the banner pos correctly if sent', function () { - let clonedBannerRequests = deepClone(baseBannerBidRequests); - clonedBannerRequests[0].mediaTypes.banner.pos = 1; - - const requestBody = testBuildRequests(clonedBannerRequests, baseBidderRequest).data; - expect(requestBody.imp[0].banner.pos).to.equal(1); - }); - - it('sets the banner expansion direction correctly if sent', function () { - let clonedBannerRequests = deepClone(baseBannerBidRequests); - const expdir = [1, 3] - clonedBannerRequests[0].params.banner = { - expdir: expdir - }; - - const requestBody = testBuildRequests(clonedBannerRequests, baseBidderRequest).data; - expect(requestBody.imp[0].banner.expdir).to.equal(expdir); - }); - - it('sets keywords properly if sent', function () { - let clonedBannerRequests = deepClone(baseBannerBidRequests); - - config.setConfig({ortb2: { - site: { - keywords: 'highViewability, clothing, holiday shopping' - } - }}); - const requestBody = testBuildRequests(clonedBannerRequests, baseBidderRequest).data; - config.resetConfig(); - expect(requestBody.ext.ttdprebid.keywords).to.deep.equal(['highViewability', 'clothing', 'holiday shopping']); - }); - - it('sets ext properly', function () { - let clonedBannerRequests = deepClone(baseBannerBidRequests); - - const requestBody = testBuildRequests(clonedBannerRequests, baseBidderRequest).data; - expect(requestBody.ext.ttdprebid.pbjs).to.equal('$prebid.version$'); - }); - - it('adds gdpr consent info to the request', function () { - let consentString = 'BON3G4EON3G4EAAABAENAA____ABl____A'; - let clonedBidderRequest = deepClone(baseBidderRequest); - clonedBidderRequest.gdprConsent = { - consentString: consentString, - gdprApplies: true - }; - - const requestBody = testBuildRequests(baseBannerBidRequests, clonedBidderRequest).data; - expect(requestBody.user.ext.consent).to.equal(consentString); - expect(requestBody.regs.ext.gdpr).to.equal(1); - }); - - it('adds usp consent info to the request', function () { - let consentString = 'BON3G4EON3G4EAAABAENAA____ABl____A'; - let clonedBidderRequest = deepClone(baseBidderRequest); - clonedBidderRequest.uspConsent = consentString; - - const requestBody = testBuildRequests(baseBannerBidRequests, clonedBidderRequest).data; - expect(requestBody.regs.ext.us_privacy).to.equal(consentString); - }); - - it('adds coppa consent info to the request', function () { - let clonedBidderRequest = deepClone(baseBidderRequest); - - config.setConfig({coppa: true}); - const requestBody = testBuildRequests(baseBannerBidRequests, clonedBidderRequest).data; - config.resetConfig(); - expect(requestBody.regs.coppa).to.equal(1); - }); - - it('adds schain info to the request', function () { - const schain = { - 'ver': '1.0', - 'complete': 1, - 'nodes': [{ - 'asi': 'indirectseller.com', - 'sid': '00001', - 'hp': 1 - }, { - 'asi': 'indirectseller-2.com', - 'sid': '00002', - 'hp': 1 - }] - }; - let clonedBannerBidRequests = deepClone(baseBannerBidRequests); - clonedBannerBidRequests[0].schain = schain; - - const requestBody = testBuildRequests(clonedBannerBidRequests, baseBidderRequest).data; - expect(requestBody.source.ext.schain).to.deep.equal(schain); - }); - - it('adds unified ID info to the request', function () { - const TDID = '00000000-0000-0000-0000-000000000000'; - let clonedBannerRequests = deepClone(baseBannerBidRequests); - clonedBannerRequests[0].userId = { - tdid: TDID - }; - - const requestBody = testBuildRequests(clonedBannerRequests, baseBidderRequest).data; - expect(requestBody.user.buyeruid).to.equal(TDID); - }); - - it('adds unified ID and UID2 info to user.ext.eids in the request', function () { - const TDID = '00000000-0000-0000-0000-000000000000'; - const UID2 = '99999999-9999-9999-9999-999999999999'; - let clonedBannerRequests = deepClone(baseBannerBidRequests); - clonedBannerRequests[0].userId = { - tdid: TDID, - uid2: { - id: UID2 - } - }; - const expectedEids = [ - { - source: 'adserver.org', - uids: [ - { - atype: 1, - ext: { - rtiPartner: 'TDID' - }, - id: TDID - } - ] - }, - { - source: 'uidapi.com', - uids: [ - { - atype: 3, - id: UID2 - } - ] - } - ]; - - const requestBody = testBuildRequests(clonedBannerRequests, baseBidderRequest).data; - expect(requestBody.user.ext.eids).to.deep.equal(expectedEids); - }); - - it('adds first party site data to the request', function () { - let clonedBidderRequest = deepClone(baseBidderRequest); - - config.setConfig({ortb2: { - site: { - name: 'example', - domain: 'page.example.com', - cat: ['IAB2'], - sectioncat: ['IAB2-2'], - pagecat: ['IAB2-2'], - page: 'https://page.example.com/here.html', - ref: 'https://ref.example.com', - keywords: 'power tools, drills' - } - }}); - const requestBody = testBuildRequests(baseBannerBidRequests, clonedBidderRequest).data; - config.resetConfig(); - expect(requestBody.site.name).to.equal('example'); - expect(requestBody.site.domain).to.equal('page.example.com'); - expect(requestBody.site.cat[0]).to.equal('IAB2'); - expect(requestBody.site.sectioncat[0]).to.equal('IAB2-2'); - expect(requestBody.site.pagecat[0]).to.equal('IAB2-2'); - expect(requestBody.site.page).to.equal('https://page.example.com/here.html'); - expect(requestBody.site.ref).to.equal('https://ref.example.com'); - expect(requestBody.site.keywords).to.equal('power tools, drills'); - }); - }); - - describe('buildRequests-banner-multiple', function () { - const baseBannerMultipleBidRequests = [{ - 'bidder': 'ttd', - 'params': { - 'supplySourceId': 'supplier', - 'publisherId': '13144370', - 'placementId': 'bottom' - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250], [300, 600]] - } - }, - 'sizes': [[300, 250], [300, 600]], - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '8651474f-58b1-4368-b812-84f8c937a099', - 'bidId': 'small', - 'bidderRequestId': '18084284054531', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'src': 'client', - 'bidRequestsCount': 1 - }, { - 'bidder': 'ttd', - 'params': { - 'publisherId': '13144370', - 'placementId': 'top', - 'siteId': 'testSite123' - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[728, 90]] - } - }, - 'sizes': [[728, 90]], - 'adUnitCode': 'div-gpt-ad-91515710-0', - 'transactionId': '825c1228-ca8c-4657-b40f-2df500621527', - 'bidId': 'large', - 'bidderRequestId': '18084284054531', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'src': 'client', - 'bidRequestsCount': 1 - }]; - - const baseBidderRequest = { - 'bidderCode': 'ttd', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'bidderRequestId': '18084284054531', - 'auctionStart': 1540945362095, - 'timeout': 3000, - 'refererInfo': { - 'referer': 'https://www.test.com', - 'reachedTop': true, - 'numIframes': 0, - 'stack': [ - 'https://www.test.com' - ] - }, - 'start': 1540945362099, - 'doneCbCallCount': 0 - }; - - it('sends multiple impressions', function () { - const requestBody = testBuildRequests(baseBannerMultipleBidRequests, baseBidderRequest).data; - expect(requestBody.imp.length).to.equal(2); - }); - - it('sends the right tag ids for each ad unit', function () { - const requestBody = testBuildRequests(baseBannerMultipleBidRequests, baseBidderRequest).data; - requestBody.imp.forEach(imp => { - if (imp.id === 'small') { - expect(imp.tagid).to.equal('bottom'); - } else if (imp.id === 'large') { - expect(imp.tagid).to.equal('top'); - } else { - assert.fail('no matching impression id found'); - } - }); - }); - - it('sends the sizes for each ad unit', function () { - const requestBody = testBuildRequests(baseBannerMultipleBidRequests, baseBidderRequest).data; - requestBody.imp.forEach(imp => { - if (imp.id === 'small') { - expect(imp.banner.format[0].w).to.equal(300); - expect(imp.banner.format[0].h).to.equal(250); - expect(imp.banner.format[1].w).to.equal(300); - expect(imp.banner.format[1].h).to.equal(600); - } else if (imp.id === 'large') { - expect(imp.banner.format[0].w).to.equal(728); - expect(imp.banner.format[0].h).to.equal(90); - } else { - assert.fail('no matching impression id found'); - } - }); - }); - }); - - describe('buildRequests-display-video-multiformat', function () { - const baseMultiformatBidRequests = [{ - 'bidder': 'ttd', - 'params': { - 'supplySourceId': 'supplier', - 'publisherId': '13144370', - 'placementId': '1gaa015' - }, - 'mediaTypes': { - 'video': { - 'playerSize': [640, 480], - 'api': [1, 3], - 'mimes': ['video/mp4'], - 'protocols': [2, 3, 5, 6], - 'minduration': 5, - 'maxduration': 30 - }, - 'banner': { - 'sizes': [[300, 250], [300, 600]] - } - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '8651474f-58b1-4368-b812-84f8c937a099', - 'bidId': '243310435309b5', - 'bidderRequestId': '18084284054531', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'src': 'client', - 'bidRequestsCount': 1 - }]; - - const baseBidderRequest = { - 'bidderCode': 'ttd', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'bidderRequestId': '18084284054531', - 'auctionStart': 1540945362095, - 'timeout': 3000, - 'refererInfo': { - 'referer': 'https://www.example.com/test', - 'reachedTop': true, - 'numIframes': 0, - 'stack': [ - 'https://www.example.com/test' - ] - }, - 'start': 1540945362099, - 'doneCbCallCount': 0 - }; - - it('includes the video ad size in the bid request', function () { - const requestBody = testBuildRequests(baseMultiformatBidRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.w).to.equal(640); - expect(requestBody.imp[0].video.h).to.equal(480); - }); - - it('includes the banner ad size in the bid request', function () { - const requestBody = testBuildRequests(baseMultiformatBidRequests, baseBidderRequest).data; - expect(requestBody.imp[0].banner.format[0].w).to.equal(300); - expect(requestBody.imp[0].banner.format[0].h).to.equal(250); - expect(requestBody.imp[0].banner.format[1].w).to.equal(300); - expect(requestBody.imp[0].banner.format[1].h).to.equal(600); - }); - }); - - describe('buildRequests-video', function () { - const baseVideoBidRequests = [{ - 'bidder': 'ttd', - 'params': { - 'supplySourceId': 'supplier', - 'publisherId': '13144370', - 'placementId': '1gaa015' - }, - 'mediaTypes': { - 'video': { - 'playerSize': [640, 480], - 'api': [1, 3], - 'mimes': ['video/mp4'], - 'protocols': [2, 3, 5, 6], - 'minduration': 5, - 'maxduration': 30 - } - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '8651474f-58b1-4368-b812-84f8c937a099', - 'bidId': '243310435309b5', - 'bidderRequestId': '18084284054531', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'src': 'client', - 'bidRequestsCount': 1 - }]; - - const baseBidderRequest = { - 'bidderCode': 'ttd', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'bidderRequestId': '18084284054531', - 'auctionStart': 1540945362095, - 'timeout': 3000, - 'refererInfo': { - 'referer': 'https://www.example.com/test', - 'reachedTop': true, - 'numIframes': 0, - 'stack': [ - 'https://www.example.com/test' - ] - }, - 'start': 1540945362099, - 'doneCbCallCount': 0 - }; - - it('includes the ad size in the bid request', function () { - const requestBody = testBuildRequests(baseVideoBidRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.w).to.equal(640); - expect(requestBody.imp[0].video.h).to.equal(480); - }); - - it('includes the mimes in the bid request', function () { - const requestBody = testBuildRequests(baseVideoBidRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.mimes[0]).to.equal('video/mp4'); - }); - - it('includes the min and max duration in the bid request', function () { - const requestBody = testBuildRequests(baseVideoBidRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.minduration).to.equal(5); - expect(requestBody.imp[0].video.maxduration).to.equal(30); - }); - - it('sets the minduration to 0 if missing', function () { - let clonedVideoRequests = deepClone(baseVideoBidRequests); - delete clonedVideoRequests[0].mediaTypes.video.minduration - - const requestBody = testBuildRequests(clonedVideoRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.minduration).to.equal(0); - }); - - it('includes the api frameworks in the bid request', function () { - const requestBody = testBuildRequests(baseVideoBidRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.api[0]).to.equal(1); - expect(requestBody.imp[0].video.api[1]).to.equal(3); - }); - - it('includes the protocols in the bid request', function () { - const requestBody = testBuildRequests(baseVideoBidRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.protocols[0]).to.equal(2); - expect(requestBody.imp[0].video.protocols[1]).to.equal(3); - expect(requestBody.imp[0].video.protocols[2]).to.equal(5); - expect(requestBody.imp[0].video.protocols[3]).to.equal(6); - }); - - it('sets skip correctly if sent', function () { - let clonedVideoRequests = deepClone(baseVideoBidRequests); - clonedVideoRequests[0].mediaTypes.video.skip = 1; - clonedVideoRequests[0].mediaTypes.video.skipmin = 5; - clonedVideoRequests[0].mediaTypes.video.skipafter = 10; - - const requestBody = testBuildRequests(clonedVideoRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.skip).to.equal(1); - expect(requestBody.imp[0].video.skipmin).to.equal(5); - expect(requestBody.imp[0].video.skipafter).to.equal(10); - }); - - it('sets bitrate correctly if sent', function () { - let clonedVideoRequests = deepClone(baseVideoBidRequests); - clonedVideoRequests[0].mediaTypes.video.minbitrate = 100; - clonedVideoRequests[0].mediaTypes.video.maxbitrate = 500; - - const requestBody = testBuildRequests(clonedVideoRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.minbitrate).to.equal(100); - expect(requestBody.imp[0].video.maxbitrate).to.equal(500); - }); - - it('sets pos correctly if sent', function () { - let clonedVideoRequests = deepClone(baseVideoBidRequests); - clonedVideoRequests[0].mediaTypes.video.pos = 1; - - const requestBody = testBuildRequests(clonedVideoRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.pos).to.equal(1); - }); - - it('sets playbackmethod correctly if sent', function () { - let clonedVideoRequests = deepClone(baseVideoBidRequests); - clonedVideoRequests[0].mediaTypes.video.playbackmethod = [1]; - - const requestBody = testBuildRequests(clonedVideoRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.playbackmethod[0]).to.equal(1); - }); - - it('sets startdelay correctly if sent', function () { - let clonedVideoRequests = deepClone(baseVideoBidRequests); - clonedVideoRequests[0].mediaTypes.video.startdelay = -1; - - const requestBody = testBuildRequests(clonedVideoRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.startdelay).to.equal(-1); - }); - - it('sets placement correctly if sent', function () { - let clonedVideoRequests = deepClone(baseVideoBidRequests); - clonedVideoRequests[0].mediaTypes.video.placement = 3; - - const requestBody = testBuildRequests(clonedVideoRequests, baseBidderRequest).data; - expect(requestBody.imp[0].video.placement).to.equal(3); - }); - }); - - describe('interpretResponse-empty', function () { - it('should handle empty response', function () { - let result = spec.interpretResponse({}); - expect(result.length).to.equal(0); - }); - - it('should handle empty seatbid response', function () { - let response = { - body: { - 'id': '5e5c23a5ba71e78', - 'seatbid': [] - } - }; - let result = spec.interpretResponse(response); - expect(result.length).to.equal(0); - }); - }); - - describe('interpretResponse-simple-display', function () { - const incoming = { - body: { - 'id': '5e5c23a5ba71e78', - 'seatbid': [ - { - 'bid': [ - { - 'id': '6vmb3isptf', - 'crid': 'ttdscreative', - 'impid': '322add653672f68', - 'price': 1.22, - 'adm': '', - 'cat': [], - 'h': 90, - 'w': 728, - 'ttl': 60, - 'dealid': 'ttd-dealid-1', - 'adomain': ['advertiser.com'], - 'ext': { - 'mediatype': 1 - } - } - ], - 'seat': 'MOCK' - } - ], - 'cur': 'EUR', - 'bidid': '5e5c23a5ba71e78' - } - }; - - const serverRequest = { - 'method': 'POST', - 'url': 'https://direct.adsrvr.org/bid/bidder/supplier', - 'data': { - 'id': 'c47237df-c108-419f-9c2b-da513dc3c133', - 'imp': [ - { - 'id': '322add653672f68', - 'tagid': 'simple', - 'banner': { - 'w': 728, - 'h': 90, - 'format': [ - { - 'w': 728, - 'h': 90 - } - ] - } - } - ], - 'site': { - 'page': 'http://www.test.com', - 'publisher': { - 'id': '111' - } - }, - 'device': { - 'ua': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36', - 'dnt': 0, - 'language': 'en-US', - 'connectiontype': 0 - }, - 'user': {}, - 'at': 1, - 'cur': [ - 'USD' - ], - 'regs': {}, - 'ext': { - 'ttdprebid': { - 'ver': 'TTD-PREBID-2019.11.12', - 'pbjs': '2.31.0' - } - } - }, - 'options': { - 'withCredentials': true - } - }; - - const expectedBid = { - 'requestId': '322add653672f68', - 'cpm': 1.22, - 'width': 728, - 'height': 90, - 'creativeId': 'ttdscreative', - 'dealId': 'ttd-dealid-1', - 'currency': 'EUR', - 'netRevenue': true, - 'ttl': 60, - 'ad': '', - 'mediaType': 'banner', - 'meta': { - 'advertiserDomains': ['advertiser.com'] - } - }; - - it('should get the correct bid response', function () { - let result = spec.interpretResponse(incoming, serverRequest); - expect(result.length).to.equal(1); - expect(result[0]).to.deep.equal(expectedBid); - }); - }); - - describe('interpretResponse-multiple-display', function () { - const incoming = { - 'body': { - 'id': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'seatbid': [ - { - 'bid': [ - { - 'id': 'small', - 'impid': 'small', - 'price': 4.25, - 'adm': 'Default Test Ad Tag', - 'cid': 'campaignId132', - 'crid': 'creativeId999', - 'adomain': [ - 'http://foo' - ], - 'dealid': null, - 'w': 300, - 'h': 600, - 'cat': [], - 'ext': { - 'mediatype': 1 - } - }, - { - 'id': 'large', - 'impid': 'large', - 'price': 5.25, - 'adm': 'Default Test Ad Tag', - 'cid': 'campaignId132', - 'crid': 'creativeId222', - 'adomain': [ - 'http://foo2' - ], - 'dealid': null, - 'w': 728, - 'h': 90, - 'cat': [], - 'ext': { - 'mediatype': 1 - } - } - ], - 'seat': 'supplyVendorBuyerId132' - } - ], - 'cur': 'USD' - } - }; - - const expectedBids = [ - { - 'requestId': 'small', - 'cpm': 4.25, - 'width': 300, - 'height': 600, - 'creativeId': 'creativeId999', - 'currency': 'USD', - 'dealId': null, - 'netRevenue': true, - 'ttl': 360, - 'ad': 'Default Test Ad Tag', - 'mediaType': 'banner', - 'meta': { - 'advertiserDomains': ['http://foo'] - } - }, - { - 'requestId': 'large', - 'cpm': 5.25, - 'width': 728, - 'height': 90, - 'creativeId': 'creativeId222', - 'currency': 'USD', - 'dealId': null, - 'netRevenue': true, - 'ttl': 360, - 'ad': 'Default Test Ad Tag', - 'mediaType': 'banner', - 'meta': { - 'advertiserDomains': ['http://foo2'] - } - } - ]; - - const serverRequest = { - 'method': 'POST', - 'url': 'https://direct.adsrvr.org/bid/bidder/supplier', - 'data': { - 'id': 'c47237df-c108-419f-9c2b-da513dc3c133', - 'imp': [ - { - 'id': 'small', - 'tagid': 'test1', - 'banner': { - 'w': 300, - 'h': 600, - 'format': [ - { - 'w': 300, - 'h': 600 - } - ] - } - }, - { - 'id': 'large', - 'tagid': 'test2', - 'banner': { - 'w': 728, - 'h': 90, - 'format': [ - { - 'w': 728, - 'h': 90 - } - ] - } - } - ], - 'site': { - 'page': 'http://www.test.com', - 'publisher': { - 'id': '111' - } - }, - 'device': { - 'ua': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36', - 'dnt': 0, - 'language': 'en-US', - 'connectiontype': 0 - }, - 'user': {}, - 'at': 1, - 'cur': [ - 'USD' - ], - 'regs': {}, - 'ext': { - 'ttdprebid': { - 'ver': 'TTD-PREBID-2019.11.12', - 'pbjs': '2.31.0' - } - } - }, - 'options': { - 'withCredentials': true - } - }; - - it('should get the correct bid response', function () { - let result = spec.interpretResponse(incoming, serverRequest); - expect(result.length).to.equal(2); - expect(result).to.deep.equal(expectedBids); - }); - }); - - describe('interpretResponse-simple-video', function () { - const incoming = { - 'body': { - 'cur': 'USD', - 'seatbid': [ - { - 'bid': [ - { - 'crid': 'mokivv6m', - 'ext': { - 'advid': '7ieo6xk', - 'agid': '7q9n3s2', - 'deal': { - 'dealid': '7013542' - }, - 'imptrackers': [], - 'viewabilityvendors': [], - 'mediatype': 2 - }, - 'h': 480, - 'impid': '2eabb87dfbcae4', - 'nurl': 'https://insight.adsrvr.org/enduser/vast?iid=00000000-0000-0000-0000-000000000000&crid=v3pek2eh&wp=${AUCTION_PRICE}&aid=&wpc=&sfe=0&puid=&tdid=00000000-0000-0000-0000-000000000000&pid=&ag=&adv=&sig=AAAAAAAAAAAAAA.&cf=&fq=0&td_s=&rcats=&mcat=&mste=&mfld=4&mssi=&mfsi=&uhow=&agsa=&rgco=&rgre=&rgme=&rgci=&rgz=&svbttd=0&dt=&osf=&os=&br=&rlangs=en&mlang=en&svpid=&did=&rcxt=&lat=&lon=&tmpc=&daid=&vp=0&osi=&osv=&dc=0&vcc=QAFIAVABiAECwAEDyAED0AED6AEG8AEBgAIDigIMCAIIBQgDCAYICwgMmgIECAEIAqACA6gCAsACAA..&sv=noop&pidi=&advi=&cmpi=&agi=&cridi=&svi=&cmp=&skip=1&c=&dur=&crrelr=', - 'price': 13.6, - 'ttl': 500, - 'w': 600 - } - ], - 'seat': 'supplyVendorBuyerId132' - } - ] - }, - 'headers': {} - }; - - const serverRequest = { - 'method': 'POST', - 'url': 'https://direct.bid.adsrvr.org/bid/bidder/supplier', - 'data': { - 'id': 'e94ec12d-ae1d-4ed7-abd1-eb3198ce3b63', - 'imp': [ - { - 'id': '2eabb87dfbcae4', - 'tagid': 'video', - 'video': { - 'api': [ - 1, - 3 - ], - 'mimes': [ - 'video/mp4' - ], - 'minduration': 5, - 'maxduration': 30, - 'w': 640, - 'h': 480, - 'protocols': [ - 2, - 3, - 5, - 6 - ] - } - } - ], - 'site': { - 'page': 'http://www.test.com', - 'publisher': { - 'id': '111' - } - }, - 'device': { - 'ua': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36', - 'dnt': 0, - 'language': 'en-US', - 'connectiontype': 0 - }, - 'user': {}, - 'at': 1, - 'cur': [ - 'USD' - ], - 'regs': {}, - 'ext': { - 'ttdprebid': { - 'ver': 'TTD-PREBID-2019.11.12', - 'pbjs': '3.10.0' - } - } - }, - 'options': { - 'withCredentials': true - } - }; - - const expectedBid = - { - 'requestId': '2eabb87dfbcae4', - 'cpm': 13.6, - 'creativeId': 'mokivv6m', - 'dealId': null, - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 500, - 'width': 640, - 'height': 480, - 'mediaType': 'video', - 'vastUrl': 'https://insight.adsrvr.org/enduser/vast?iid=00000000-0000-0000-0000-000000000000&crid=v3pek2eh&wp=13.6&aid=&wpc=&sfe=0&puid=&tdid=00000000-0000-0000-0000-000000000000&pid=&ag=&adv=&sig=AAAAAAAAAAAAAA.&cf=&fq=0&td_s=&rcats=&mcat=&mste=&mfld=4&mssi=&mfsi=&uhow=&agsa=&rgco=&rgre=&rgme=&rgci=&rgz=&svbttd=0&dt=&osf=&os=&br=&rlangs=en&mlang=en&svpid=&did=&rcxt=&lat=&lon=&tmpc=&daid=&vp=0&osi=&osv=&dc=0&vcc=QAFIAVABiAECwAEDyAED0AED6AEG8AEBgAIDigIMCAIIBQgDCAYICwgMmgIECAEIAqACA6gCAsACAA..&sv=noop&pidi=&advi=&cmpi=&agi=&cridi=&svi=&cmp=&skip=1&c=&dur=&crrelr=', - 'meta': {} - }; - - it('should get the correct bid response if nurl is returned', function () { - let result = spec.interpretResponse(incoming, serverRequest); - expect(result.length).to.equal(1); - expect(result[0]).to.deep.equal(expectedBid); - }); - - it('should get the correct bid response if adm is returned', function () { - const vastXml = "2.0574840600:00:30 \"Click ]]>"; - let admIncoming = deepClone(incoming); - delete admIncoming.body.seatbid[0].bid[0].nurl; - admIncoming.body.seatbid[0].bid[0].adm = vastXml; - - let vastXmlExpectedBid = deepClone(expectedBid); - delete vastXmlExpectedBid.vastUrl; - vastXmlExpectedBid.vastXml = vastXml; - - let result = spec.interpretResponse(admIncoming, serverRequest); - expect(result.length).to.equal(1); - expect(result[0]).to.deep.equal(vastXmlExpectedBid); - }); - }); - - describe('interpretResponse-display-and-video', function () { - const incoming = { - 'body': { - 'id': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', - 'seatbid': [ - { - 'bid': [ - { - 'id': 'small', - 'impid': 'small', - 'price': 4.25, - 'adm': 'Default Test Ad Tag', - 'cid': 'campaignId132', - 'crid': 'creativeId999', - 'adomain': [ - 'http://foo' - ], - 'dealid': null, - 'w': 300, - 'h': 600, - 'cat': [], - 'ext': { - 'mediatype': 1 - } - }, - { - 'crid': 'mokivv6m', - 'ext': { - 'advid': '7ieo6xk', - 'agid': '7q9n3s2', - 'deal': { - 'dealid': '7013542' - }, - 'imptrackers': [], - 'viewabilityvendors': [], - 'mediatype': 2 - }, - 'h': 480, - 'impid': '2eabb87dfbcae4', - 'nurl': 'https://insight.adsrvr.org/enduser/vast?iid=00000000-0000-0000-0000-000000000000&crid=v3pek2eh&wp=${AUCTION_PRICE}&aid=&wpc=&sfe=0&puid=&tdid=00000000-0000-0000-0000-000000000000&pid=&ag=&adv=&sig=AAAAAAAAAAAAAA.&cf=&fq=0&td_s=&rcats=&mcat=&mste=&mfld=4&mssi=&mfsi=&uhow=&agsa=&rgco=&rgre=&rgme=&rgci=&rgz=&svbttd=0&dt=&osf=&os=&br=&rlangs=en&mlang=en&svpid=&did=&rcxt=&lat=&lon=&tmpc=&daid=&vp=0&osi=&osv=&dc=0&vcc=QAFIAVABiAECwAEDyAED0AED6AEG8AEBgAIDigIMCAIIBQgDCAYICwgMmgIECAEIAqACA6gCAsACAA..&sv=noop&pidi=&advi=&cmpi=&agi=&cridi=&svi=&cmp=&skip=1&c=&dur=&crrelr=', - 'price': 13.6, - 'ttl': 500, - 'w': 600 - } - ], - 'seat': 'supplyVendorBuyerId132' - } - ], - 'cur': 'USD' - } - }; - - const expectedBids = [ - { - 'requestId': 'small', - 'cpm': 4.25, - 'width': 300, - 'height': 600, - 'creativeId': 'creativeId999', - 'currency': 'USD', - 'dealId': null, - 'netRevenue': true, - 'ttl': 360, - 'ad': 'Default Test Ad Tag', - 'mediaType': 'banner', - 'meta': { - 'advertiserDomains': ['http://foo'] - } - }, - { - 'requestId': '2eabb87dfbcae4', - 'cpm': 13.6, - 'creativeId': 'mokivv6m', - 'dealId': null, - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 500, - 'width': 640, - 'height': 480, - 'mediaType': 'video', - 'vastUrl': 'https://insight.adsrvr.org/enduser/vast?iid=00000000-0000-0000-0000-000000000000&crid=v3pek2eh&wp=13.6&aid=&wpc=&sfe=0&puid=&tdid=00000000-0000-0000-0000-000000000000&pid=&ag=&adv=&sig=AAAAAAAAAAAAAA.&cf=&fq=0&td_s=&rcats=&mcat=&mste=&mfld=4&mssi=&mfsi=&uhow=&agsa=&rgco=&rgre=&rgme=&rgci=&rgz=&svbttd=0&dt=&osf=&os=&br=&rlangs=en&mlang=en&svpid=&did=&rcxt=&lat=&lon=&tmpc=&daid=&vp=0&osi=&osv=&dc=0&vcc=QAFIAVABiAECwAEDyAED0AED6AEG8AEBgAIDigIMCAIIBQgDCAYICwgMmgIECAEIAqACA6gCAsACAA..&sv=noop&pidi=&advi=&cmpi=&agi=&cridi=&svi=&cmp=&skip=1&c=&dur=&crrelr=', - 'meta': {} - } - ]; - - const serverRequest = { - 'method': 'POST', - 'url': 'https://direct.adsrvr.org/bid/bidder/supplier', - 'data': { - 'id': 'c47237df-c108-419f-9c2b-da513dc3c133', - 'imp': [ - { - 'id': 'small', - 'tagid': 'test1', - 'banner': { - 'w': 300, - 'h': 600, - 'format': [ - { - 'w': 300, - 'h': 600 - } - ] - }, - }, - { - 'id': '2eabb87dfbcae4', - 'tagid': 'video', - 'video': { - 'api': [ - 1, - 3 - ], - 'mimes': [ - 'video/mp4' - ], - 'minduration': 5, - 'maxduration': 30, - 'w': 640, - 'h': 480, - 'protocols': [ - 2, - 3, - 5, - 6 - ] - } - } - ], - 'site': { - 'page': 'http://www.test.com', - 'publisher': { - 'id': '111' - } - }, - 'device': { - 'ua': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36', - 'dnt': 0, - 'language': 'en-US', - 'connectiontype': 0 - }, - 'user': {}, - 'at': 1, - 'cur': [ - 'USD' - ], - 'regs': {}, - 'ext': { - 'ttdprebid': { - 'ver': 'TTD-PREBID-2019.11.12', - 'pbjs': '2.31.0' - } - } - }, - 'options': { - 'withCredentials': true - } - }; - - it('should get the correct bid response', function () { - let result = spec.interpretResponse(incoming, serverRequest); - expect(result.length).to.equal(2); - expect(result).to.deep.equal(expectedBids); - }); - }); -}); diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index c24f63c0b99..0faa321be5f 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -1,7 +1,5 @@ -import {expect} from 'chai'; -import {spec} from 'modules/undertoneBidAdapter.js'; -import {BANNER, VIDEO} from '../../../src/mediaTypes'; -import {deepClone} from '../../../src/utils'; +import { expect } from 'chai'; +import { spec } from 'modules/undertoneBidAdapter.js'; const URL = 'https://hb.undertone.com/hb'; const BIDDER_CODE = 'undertone'; @@ -62,23 +60,6 @@ const videoBidReq = [{ bidId: '263be71e91dd9d', auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' }]; -const schainObj = { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'indirectseller.com', - 'sid': '00001', - 'hp': 1 - }, - - { - 'asi': 'indirectseller-2.com', - 'sid': '00002', - 'hp': 2 - } - ] -}; const bidReq = [{ adUnitCode: 'div-gpt-ad-1460505748561-0', bidder: BIDDER_CODE, @@ -91,29 +72,6 @@ const bidReq = [{ auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' }, { - adUnitCode: 'div-gpt-ad-1460505748561-0', - bidder: BIDDER_CODE, - params: { - publisherId: 12345 - }, - sizes: [[1, 1]], - bidId: '453cf42d72bb3c', - auctionId: '6c22f5a5-59df-4dc6-b92c-f433bcf0a874', - schain: schainObj -}]; - -const supplyChainedBidReqs = [{ - adUnitCode: 'div-gpt-ad-1460505748561-0', - bidder: BIDDER_CODE, - params: { - placementId: '10433394', - publisherId: 12345, - }, - sizes: [[300, 250], [300, 600]], - bidId: '263be71e91dd9d', - auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', - schain: schainObj -}, { adUnitCode: 'div-gpt-ad-1460505748561-0', bidder: BIDDER_CODE, params: { @@ -278,69 +236,6 @@ describe('Undertone Adapter', () => { sandbox.restore(); }); - describe('getFloor', function () { - it('should send 0 floor when getFloor is undefined', function() { - const request = spec.buildRequests(videoBidReq, bidderReq); - const bidReq = JSON.parse(request.data)['x-ut-hb-params'][0]; - expect(bidReq.mediaType).to.deep.equal(VIDEO); - expect(bidReq.bidfloor).to.deep.equal(0); - }); - it('should send mocked floor when defined on video media-type', function() { - const clonedVideoBidReqArr = deepClone(videoBidReq); - const mockedFloorResponse = { - currency: 'USD', - floor: 2.3 - }; - clonedVideoBidReqArr[1].getFloor = () => mockedFloorResponse; - - const request = spec.buildRequests(clonedVideoBidReqArr, bidderReq); - const bidReq1 = JSON.parse(request.data)['x-ut-hb-params'][0]; - const bidReq2 = JSON.parse(request.data)['x-ut-hb-params'][1]; - expect(bidReq1.mediaType).to.deep.equal(VIDEO); - expect(bidReq1.bidfloor).to.deep.equal(0); - - expect(bidReq2.mediaType).to.deep.equal(VIDEO); - expect(bidReq2.bidfloor).to.deep.equal(mockedFloorResponse.floor); - }); - it('should send mocked floor on banner media-type', function() { - const clonedValidBidReqArr = [deepClone(validBidReq)]; - const mockedFloorResponse = { - currency: 'USD', - floor: 2.3 - }; - clonedValidBidReqArr[0].getFloor = () => mockedFloorResponse; - - const request = spec.buildRequests(clonedValidBidReqArr, bidderReq); - const bidReq = JSON.parse(request.data)['x-ut-hb-params'][0]; - expect(bidReq.mediaType).to.deep.equal(BANNER); - expect(bidReq.bidfloor).to.deep.equal(mockedFloorResponse.floor); - }); - it('should send 0 floor on invalid currency', function() { - const clonedValidBidReqArr = [deepClone(validBidReq)]; - const mockedFloorResponse = { - currency: 'EUR', - floor: 2.3 - }; - clonedValidBidReqArr[0].getFloor = () => mockedFloorResponse; - - const request = spec.buildRequests(clonedValidBidReqArr, bidderReq); - const bidReq = JSON.parse(request.data)['x-ut-hb-params'][0]; - expect(bidReq.mediaType).to.deep.equal(BANNER); - expect(bidReq.bidfloor).to.deep.equal(0); - }); - }); - describe('supply chain', function () { - it('should send supply chain if found on first bid', function () { - const request = spec.buildRequests(supplyChainedBidReqs, bidderReq); - const commons = JSON.parse(request.data)['commons']; - expect(commons.schain).to.deep.equal(schainObj); - }); - it('should not send supply chain if not found on first bid', function () { - const request = spec.buildRequests(bidReq, bidderReq); - const commons = JSON.parse(request.data)['commons']; - expect(commons.schain).to.not.exist; - }); - }); it('should send request to correct url via POST not in GDPR or CCPA', function () { const request = spec.buildRequests(bidReq, bidderReq); const domainStart = bidderReq.refererInfo.referer.indexOf('//'); diff --git a/test/spec/modules/unicornBidAdapter_spec.js b/test/spec/modules/unicornBidAdapter_spec.js index 1ab428d58b6..615eac2ecf2 100644 --- a/test/spec/modules/unicornBidAdapter_spec.js +++ b/test/spec/modules/unicornBidAdapter_spec.js @@ -332,14 +332,14 @@ const openRTBRequest = { tagid: 'rectangle-ad-2' } ], - cur: ['JPY'], + cur: 'JPY', ext: { accountId: 12345 }, site: { id: 'example', publisher: { - id: '99999' + id: 99999 }, domain: 'uni-corn.net', page: 'https://uni-corn.net/', @@ -357,7 +357,7 @@ const openRTBRequest = { ext: { stype: 'prebid_uncn', bidder: 'unicorn', - prebid_version: '1.1' + prebid_version: '1.0' } } }; @@ -444,7 +444,7 @@ const serverResponse = { const request = { method: 'POST', url: 'https://ds.uncn.jp/pb/0/bid.json', - data: '{"id":"5ebea288-f13a-4754-be6d-4ade66c68877","at":1,"imp":[{"id":"216255f234b602","banner":{"w":300,"h":250},"format":[{"w":300,"h":250},{"w":336,"h":280}],"secure":1,"bidfloor":0,"tagid":"/19968336/header-bid-tag-0"},{"id":"31e2b28ced2475","banner":{"w":"300","h":"250"},"format":[{"w":"300","h":"250"}],"secure":1,"bidfloor":0"tagid":"/19968336/header-bid-tag-1"},{"id":"40a333e047a9bd","banner":{"w":300,"h":250},"format":[{"w":300,"h":250}],"secure":1,"bidfloor":0,"tagid":"/19968336/header-bid-tag-2"}],"cur":"JPY","site":{"id":"uni-corn.net","publisher":{"id":12345},"domain":"uni-corn.net","page":"https://uni-corn.net/","ref":"https://uni-corn.net/"},"device":{"language":"ja","ua":"Mozilla/5.0 (Linux; Android 8.0.0; ONEPLUS A5000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.93 Mobile Safari/537.36"},"user":{"id":"69d9e1c2-801e-4901-a665-fad467550fec"},"bcat":[],"source":{"ext":{"stype":"prebid_uncn","bidder":"unicorn","prebid_version":"1.1"}}}' + data: '{"id":"5ebea288-f13a-4754-be6d-4ade66c68877","at":1,"imp":[{"id":"216255f234b602","banner":{"w":300,"h":250},"format":[{"w":300,"h":250},{"w":336,"h":280}],"secure":1,"bidfloor":0,"tagid":"/19968336/header-bid-tag-0"},{"id":"31e2b28ced2475","banner":{"w":"300","h":"250"},"format":[{"w":"300","h":"250"}],"secure":1,"bidfloor":0"tagid":"/19968336/header-bid-tag-1"},{"id":"40a333e047a9bd","banner":{"w":300,"h":250},"format":[{"w":300,"h":250}],"secure":1,"bidfloor":0,"tagid":"/19968336/header-bid-tag-2"}],"cur":"JPY","site":{"id":"uni-corn.net","publisher":{"id":12345},"domain":"uni-corn.net","page":"https://uni-corn.net/","ref":"https://uni-corn.net/"},"device":{"language":"ja","ua":"Mozilla/5.0 (Linux; Android 8.0.0; ONEPLUS A5000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.93 Mobile Safari/537.36"},"user":{"id":"69d9e1c2-801e-4901-a665-fad467550fec"},"bcat":[],"source":{"ext":{"stype":"prebid_uncn","bidder":"unicorn","prebid_version":"1.0"}}}' }; const interpretedBids = [ diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 48d7ea6d53e..0190bceca70 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -14,14 +14,16 @@ import { import {createEidsArray} from 'modules/userId/eids.js'; import {config} from 'src/config.js'; import * as utils from 'src/utils.js'; -import * as events from 'src/events.js'; +import events from 'src/events.js'; import CONSTANTS from 'src/constants.json'; import {getGlobal} from 'src/prebidGlobal.js'; import { + requestBidsHook as consentManagementRequestBidsHook, resetConsentData, + setConsentConfig } from 'modules/consentManagement.js'; import {server} from 'test/mocks/xhr.js'; -import {find} from 'src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; import {unifiedIdSubmodule} from 'modules/unifiedIdSystem.js'; import {britepoolIdSubmodule} from 'modules/britepoolIdSystem.js'; import {id5IdSubmodule} from 'modules/id5IdSystem.js'; @@ -34,7 +36,7 @@ import {nextrollIdSubmodule} from 'modules/nextrollIdSystem.js'; import {intentIqIdSubmodule} from 'modules/intentIqIdSystem.js'; import {zeotapIdPlusSubmodule} from 'modules/zeotapIdPlusIdSystem.js'; import {sharedIdSystemSubmodule} from 'modules/sharedIdSystem.js'; -import {hadronIdSubmodule} from 'modules/hadronIdSystem.js'; +import {haloIdSubmodule} from 'modules/haloIdSystem.js'; import {pubProvidedIdSubmodule} from 'modules/pubProvidedIdSystem.js'; import {criteoIdSubmodule} from 'modules/criteoIdSystem.js'; import {mwOpenLinkIdSubModule} from 'modules/mwOpenLinkIdSystem.js'; @@ -47,11 +49,6 @@ import {flocIdSubmodule} from 'modules/flocIdSystem.js' import {amxIdSubmodule} from '../../../modules/amxIdSystem.js'; import {akamaiDAPIdSubmodule} from 'modules/akamaiDAPIdSystem.js' import {kinessoIdSubmodule} from 'modules/kinessoIdSystem.js' -import {adqueryIdSubmodule} from 'modules/adqueryIdSystem.js'; -import * as mockGpt from '../integration/faker/googletag.js'; -import 'src/prebid.js'; -import {hook} from '../../../src/hook.js'; -import {mockGdprConsent} from '../../helpers/consentData.js'; let assert = require('chai').assert; let expect = require('chai').expect; @@ -107,80 +104,25 @@ describe('User ID', function () { }); } - let sandbox, consentData, startDelay, callbackDelay; - - function clearStack() { - return new Promise((resolve) => setTimeout(resolve)); - } - - function delay() { - const stub = sinon.stub().callsFake(() => new Promise((resolve) => { - stub.resolve = () => { - resolve(); - return clearStack(); - }; - })); - return stub; - } - - function runBidsHook(...args) { - startDelay = delay(); - - const result = requestBidsHook(...args, {delay: startDelay}); - return new Promise((resolve) => setTimeout(() => resolve(result))); - } - - function expectImmediateBidHook(...args) { - return runBidsHook(...args).then(() => { - startDelay.calledWith(0); - return startDelay.resolve(); - }) - } - - function initModule(config) { - callbackDelay = delay(); - return init(config, {delay: callbackDelay}); - } - before(function () { - hook.ready(); localStorage.removeItem(PBJS_USER_ID_OPTOUT_NAME); }); beforeEach(function () { - // TODO: this whole suite needs to be redesigned; it is passing by accident - // some tests do not pass if consent data is available - // (there are functions here with signature `getId(config, storedId)`, but storedId is actually consentData) - // also, this file is ginormous; do we really need to test *all* id systems as one? - resetConsentData(); - sandbox = sinon.sandbox.create(); - consentData = null; - mockGdprConsent(sandbox, () => consentData); coreStorage.setCookie(CONSENT_LOCAL_STORAGE_NAME, '', EXPIRED_COOKIE_DATE); }); - afterEach(() => { - sandbox.restore(); - }); - describe('Decorate Ad Units', function () { beforeEach(function () { - // reset mockGpt so nothing else interferes - mockGpt.disable(); - mockGpt.enable(); coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('pubcid_alt', 'altpubcid200000', (new Date(Date.now() + 5000).toUTCString())); - let origSK = coreStorage.setCookie.bind(coreStorage); sinon.spy(coreStorage, 'setCookie'); - sinon.stub(utils, 'logWarn'); }); afterEach(function () { - mockGpt.enable(); $$PREBID_GLOBAL$$.requestBids.removeAll(); config.resetConfig(); coreStorage.setCookie.restore(); - utils.logWarn.restore(); }); after(function () { @@ -197,33 +139,30 @@ describe('User ID', function () { let pubcid = coreStorage.getCookie('pubcid'); expect(pubcid).to.be.null; // there should be no cookie initially - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule]); - + init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); - return expectImmediateBidHook(config => { + requestBidsHook(config => { innerAdUnits1 = config.adUnits - }, {adUnits: adUnits1}).then(() => { - pubcid = coreStorage.getCookie('pubcid'); // cookies is created after requestbidHook - - innerAdUnits1.forEach(unit => { - unit.bids.forEach(bid => { - expect(bid).to.have.deep.nested.property('userId.pubcid'); - expect(bid.userId.pubcid).to.equal(pubcid); - expect(bid.userIdAsEids[0]).to.deep.equal({ - source: 'pubcid.org', - uids: [{id: pubcid, atype: 1}] - }); + }, {adUnits: adUnits1}); + pubcid = coreStorage.getCookie('pubcid'); // cookies is created after requestbidHook + + innerAdUnits1.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal(pubcid); + expect(bid.userIdAsEids[0]).to.deep.equal({ + source: 'pubcid.org', + uids: [{id: pubcid, atype: 1}] }); }); - - return expectImmediateBidHook(config => { - innerAdUnits2 = config.adUnits - }, {adUnits: adUnits2}).then(() => { - assert.deepEqual(innerAdUnits1, innerAdUnits2); - }); }); + + requestBidsHook(config => { + innerAdUnits2 = config.adUnits + }, {adUnits: adUnits2}); + assert.deepEqual(innerAdUnits1, innerAdUnits2); }); it('Check different cookies', function () { @@ -234,78 +173,73 @@ describe('User ID', function () { let pubcid1; let pubcid2; - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule]); - + init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); - return expectImmediateBidHook((config) => { + requestBidsHook((config) => { innerAdUnits1 = config.adUnits - }, {adUnits: adUnits1}).then(() => { - pubcid1 = coreStorage.getCookie('pubcid'); // get first cookie - coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); // erase cookie - - innerAdUnits1.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('userId.pubcid'); - expect(bid.userId.pubcid).to.equal(pubcid1); - expect(bid.userIdAsEids[0]).to.deep.equal({ - source: 'pubcid.org', - uids: [{id: pubcid1, atype: 1}] - }); + }, {adUnits: adUnits1}); + pubcid1 = coreStorage.getCookie('pubcid'); // get first cookie + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); // erase cookie + + innerAdUnits1.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal(pubcid1); + expect(bid.userIdAsEids[0]).to.deep.equal({ + source: 'pubcid.org', + uids: [{id: pubcid1, atype: 1}] }); }); + }); - init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule]); - - config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); - return expectImmediateBidHook((config) => { - innerAdUnits2 = config.adUnits - }, {adUnits: adUnits2}).then(() => { - pubcid2 = coreStorage.getCookie('pubcid'); // get second cookie - - innerAdUnits2.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('userId.pubcid'); - expect(bid.userId.pubcid).to.equal(pubcid2); - expect(bid.userIdAsEids[0]).to.deep.equal({ - source: 'pubcid.org', - uids: [{id: pubcid2, atype: 1}] - }); - }); + setSubmoduleRegistry([sharedIdSystemSubmodule]); + init(config); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); + requestBidsHook((config) => { + innerAdUnits2 = config.adUnits + }, {adUnits: adUnits2}); + + pubcid2 = coreStorage.getCookie('pubcid'); // get second cookie + + innerAdUnits2.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal(pubcid2); + expect(bid.userIdAsEids[0]).to.deep.equal({ + source: 'pubcid.org', + uids: [{id: pubcid2, atype: 1}] }); - - expect(pubcid1).to.not.equal(pubcid2); }); }); + + expect(pubcid1).to.not.equal(pubcid2); }); it('Use existing cookie', function () { let adUnits = [getAdUnitMock()]; let innerAdUnits; - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule]); - + init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie'])); - return expectImmediateBidHook((config) => { + requestBidsHook((config) => { innerAdUnits = config.adUnits - }, {adUnits}).then(() => { - innerAdUnits.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('userId.pubcid'); - expect(bid.userId.pubcid).to.equal('altpubcid200000'); - expect(bid.userIdAsEids[0]).to.deep.equal({ - source: 'pubcid.org', - uids: [{id: 'altpubcid200000', atype: 1}] - }); + }, {adUnits}); + innerAdUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal('altpubcid200000'); + expect(bid.userIdAsEids[0]).to.deep.equal({ + source: 'pubcid.org', + uids: [{id: 'altpubcid200000', atype: 1}] }); }); - // Because the consent cookie doesn't exist yet, we'll have 2 setCookie calls: - // 1) for the consent cookie - // 2) from the getId() call that results in a new call to store the results - expect(coreStorage.setCookie.callCount).to.equal(2); }); + // Because the consent cookie doesn't exist yet, we'll have two setCookie calls: + // 1) for the consent cookie + // 2) from the getId() call that results in a new call to store the results + expect(coreStorage.setCookie.callCount).to.equal(2); }); it('Extend cookie', function () { @@ -314,25 +248,25 @@ describe('User ID', function () { let customConfig = getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie']); customConfig = addConfig(customConfig, 'params', {extend: true}); - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule]); - + init(config); config.setConfig(customConfig); - return expectImmediateBidHook((config) => { + requestBidsHook((config) => { innerAdUnits = config.adUnits - }, {adUnits}).then(() => { - innerAdUnits.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('userId.pubcid'); - expect(bid.userId.pubcid).to.equal('altpubcid200000'); - expect(bid.userIdAsEids[0]).to.deep.equal({ - source: 'pubcid.org', - uids: [{id: 'altpubcid200000', atype: 1}] - }); + }, {adUnits}); + innerAdUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal('altpubcid200000'); + expect(bid.userIdAsEids[0]).to.deep.equal({ + source: 'pubcid.org', + uids: [{id: 'altpubcid200000', atype: 1}] }); }); - expect(coreStorage.setCookie.callCount).to.equal(2); }); + // Because extend is true, the cookie will be updated even if it exists already. The second setCookie call + // is for storing consentData + expect(coreStorage.setCookie.callCount).to.equal(2); }); it('Disable auto create', function () { @@ -341,173 +275,98 @@ describe('User ID', function () { let customConfig = getConfigMock(['pubCommonId', 'pubcid', 'cookie']); customConfig = addConfig(customConfig, 'params', {create: false}); - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule]); - + init(config); config.setConfig(customConfig); - return expectImmediateBidHook((config) => { + requestBidsHook((config) => { innerAdUnits = config.adUnits - }, {adUnits}).then(() => { - innerAdUnits.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.not.have.deep.nested.property('userId.pubcid'); - expect(bid).to.not.have.deep.nested.property('userIdAsEids'); - }); + }, {adUnits}); + innerAdUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.not.have.deep.nested.property('userId.pubcid'); + expect(bid).to.not.have.deep.nested.property('userIdAsEids'); }); - // setCookie is called once in order to store consentData - expect(coreStorage.setCookie.callCount).to.equal(1); }); + // setCookie is called once in order to store consentData + expect(coreStorage.setCookie.callCount).to.equal(1); }); - it('pbjs.getUserIds', function (done) { - init(config); + it('pbjs.getUserIds', function () { setSubmoduleRegistry([sharedIdSystemSubmodule]); - - const ids = {pubcid: '11111'}; + init(config); config.setConfig({ userSync: { - auctionDelay: 10, // with auctionDelay > 0, no auction is needed to complete init + syncDelay: 0, userIds: [{ - name: 'pubCommonId', value: ids + name: 'pubCommonId', value: {'pubcid': '11111'} }] } }); - getGlobal().getUserIdsAsync().then((uids) => { - expect(uids).to.deep.equal(ids); - expect(getGlobal().getUserIds()).to.deep.equal(ids); - done(); - }) + expect(typeof (getGlobal()).getUserIds).to.equal('function'); + expect((getGlobal()).getUserIds()).to.deep.equal({pubcid: '11111'}); }); - it('pbjs.getUserIdsAsEids', function (done) { - init(config); + it('pbjs.getUserIdsAsEids', function () { setSubmoduleRegistry([sharedIdSystemSubmodule]); - - const ids = {'pubcid': '11111'}; + init(config); config.setConfig({ userSync: { - auctionDelay: 10, + syncDelay: 0, userIds: [{ - name: 'pubCommonId', value: ids + name: 'pubCommonId', value: {'pubcid': '11111'} }] } }); - getGlobal().getUserIdsAsync().then((ids) => { - expect(getGlobal().getUserIdsAsEids()).to.deep.equal(createEidsArray(ids)); - done(); - }); + expect(typeof (getGlobal()).getUserIdsAsEids).to.equal('function'); + expect((getGlobal()).getUserIdsAsEids()).to.deep.equal(createEidsArray((getGlobal()).getUserIds())); }); - it('should set googletag ppid correctly', function () { - let adUnits = [getAdUnitMock()]; - init(config); - setSubmoduleRegistry([amxIdSubmodule, sharedIdSystemSubmodule, identityLinkSubmodule]); + it('pbjs.refreshUserIds refreshes', function() { + let sandbox = sinon.createSandbox(); - config.setConfig({ - userSync: { - ppid: 'pubcid.org', - userIds: [ - { name: 'amxId', value: {'amxId': 'amx-id-value-amx-id-value-amx-id-value'} }, - { name: 'pubCommonId', value: {'pubcid': 'pubCommon-id-value-pubCommon-id-value'} }, - { name: 'identityLink', value: {'idl_env': 'identityLink-id-value-identityLink-id-value'} }, - ] - } - }); - // before ppid should not be set - expect(window.googletag._ppid).to.equal(undefined); - return expectImmediateBidHook(() => {}, {adUnits}).then(() => { - // ppid should have been set without dashes and stuff - expect(window.googletag._ppid).to.equal('pubCommonidvaluepubCommonidvalue'); - }); - }); + let mockIdCallback = sandbox.stub().returns({id: {'MOCKID': '1111'}}); - it('should log a warning if PPID too big or small', function () { - let adUnits = [getAdUnitMock()]; + let mockIdSystem = { + name: 'mockId', + decode: function(value) { + return { + 'mid': value['MOCKID'] + }; + }, + getId: mockIdCallback + }; + setSubmoduleRegistry([mockIdSystem]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule]); - config.setConfig({ userSync: { - ppid: 'pubcid.org', - userIds: [ - { name: 'pubCommonId', value: {'pubcid': 'pubcommonIdValue'} }, - ] + syncDelay: 0, + userIds: [{ + name: 'mockId', + value: {id: {mockId: '1111'}} + }] } }); - // before ppid should not be set - expect(window.googletag._ppid).to.equal(undefined); - return expectImmediateBidHook(() => {}, {adUnits}).then(() => { - // ppid should NOT have been set - expect(window.googletag._ppid).to.equal(undefined); - // a warning should have been emmited - expect(utils.logWarn.args[0][0]).to.exist.and.to.contain('User ID - Googletag Publisher Provided ID for pubcid.org is not between 32 and 150 characters - pubcommonIdValue'); - }); - }); - - describe('refreshing before init is complete', () => { - const MOCK_ID = {'MOCKID': '1111'}; - let mockIdCallback; - - beforeEach(() => { - mockIdCallback = sinon.stub(); - let mockIdSystem = { - name: 'mockId', - decode: function(value) { - return { - 'mid': value['MOCKID'] - }; - }, - getId: sinon.stub().returns({callback: mockIdCallback}) - }; - init(config); - setSubmoduleRegistry([mockIdSystem]); - config.setConfig({ - userSync: { - auctionDelay: 10, - userIds: [{ - name: 'mockId', - storage: {name: 'MOCKID', type: 'cookie'} - }] - } - }); - }); + expect(typeof (getGlobal()).refreshUserIds).to.equal('function'); - it('should still resolve promises returned by getUserIdsAsync', () => { - let result = null; - getGlobal().getUserIdsAsync().then((val) => { result = val; }); - return clearStack().then(() => { - expect(result).to.equal(null); // auction has not ended, callback should not have been called - mockIdCallback.callsFake((cb) => cb(MOCK_ID)); - return getGlobal().refreshUserIds().then(clearStack); - }).then(() => { - expect(result).to.deep.equal(getGlobal().getUserIds()) // auction still not over, but refresh was explicitly forced - }); - }); + getGlobal().getUserIds(); // force initialization - it('should not stop auctions', (done) => { - // simulate an infinite `auctionDelay`; refreshing should still allow the auction to continue - // as soon as ID submodules have completed init - requestBidsHook(() => { - done(); - }, {adUnits: [getAdUnitMock()]}, {delay: delay()}); - getGlobal().refreshUserIds(); - clearStack().then(() => { - // simulate init complete - mockIdCallback.callArg(0, {id: {MOCKID: '1111'}}); - }) + // update config so that getId will be called + config.setConfig({ + userSync: { + syncDelay: 0, + userIds: [{ + name: 'mockId', + storage: {name: 'mockid', type: 'cookie'}, + }] + } }); - it('should not get stuck when init fails', () => { - const err = new Error(); - mockIdCallback.callsFake(() => { throw err; }); - return getGlobal().getUserIdsAsync().catch((e) => - expect(e).to.equal(err) - ); - }); + getGlobal().refreshUserIds(); + expect(mockIdCallback.callCount).to.equal(1); }); - it('pbjs.refreshUserIds updates submodules', function(done) { + it('pbjs.refreshUserIds updates submodules', function() { let sandbox = sinon.createSandbox(); let mockIdCallback = sandbox.stub().returns({id: {'MOCKID': '1111'}}); let mockIdSystem = { @@ -519,12 +378,11 @@ describe('User ID', function () { }, getId: mockIdCallback }; - init(config); setSubmoduleRegistry([mockIdSystem]); - + init(config); config.setConfig({ userSync: { - auctionDelay: 10, + syncDelay: 0, userIds: [{ name: 'mockId', value: {id: {mockId: '1111'}} @@ -532,23 +390,20 @@ describe('User ID', function () { } }); - getGlobal().getUserIdsAsync().then((uids) => { - expect(uids.id.mockId).to.equal('1111'); - // update to new config value - config.setConfig({ - userSync: { - auctionDelay: 10, - userIds: [{ - name: 'mockId', - value: {id: {mockId: '1212'}} - }] - } - }); - getGlobal().refreshUserIds({ submoduleNames: ['mockId'] }).then(() => { - expect(getGlobal().getUserIds().id.mockId).to.equal('1212'); - done(); - }); + expect(getGlobal().getUserIds().id.mockId).to.equal('1111'); + + // update to new config value + config.setConfig({ + userSync: { + syncDelay: 0, + userIds: [{ + name: 'mockId', + value: {id: {mockId: '1212'}} + }] + } }); + getGlobal().refreshUserIds({ submoduleNames: ['mockId'] }); + expect(getGlobal().getUserIds().id.mockId).to.equal('1212'); }); it('pbjs.refreshUserIds refreshes single', function() { @@ -581,12 +436,11 @@ describe('User ID', function () { getId: refreshedIdCallback }; - init(config); setSubmoduleRegistry([refreshedIdSystem, mockIdSystem]); - + init(config); config.setConfig({ userSync: { - auctionDelay: 10, + syncDelay: 0, userIds: [ { name: 'mockId', @@ -600,11 +454,13 @@ describe('User ID', function () { } }); - return getGlobal().refreshUserIds({submoduleNames: 'refreshedId'}, refreshUserIdsCallback).then(() => { - expect(refreshedIdCallback.callCount).to.equal(2); - expect(mockIdCallback.callCount).to.equal(1); - expect(refreshUserIdsCallback.callCount).to.equal(1); - }); + getGlobal().getUserIds(); // force initialization + + getGlobal().refreshUserIds({submoduleNames: 'refreshedId'}, refreshUserIdsCallback); + + expect(refreshedIdCallback.callCount).to.equal(2); + expect(mockIdCallback.callCount).to.equal(1); + expect(refreshUserIdsCallback.callCount).to.equal(1); }); }); @@ -626,15 +482,15 @@ describe('User ID', function () { }); it('fails initialization if opt out cookie exists', function () { - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule]); + init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - opt-out cookie found, exit module'); }); it('initializes if no opt out cookie exists', function () { - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule]); + init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.contain('User ID - usersync config updated for 1 submodules'); }); @@ -652,23 +508,23 @@ describe('User ID', function () { }); it('handles config with no usersync object', function () { + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig({}); // usersync is undefined, and no logInfo message for 'User ID - usersync config updated' expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); it('handles config with empty usersync object', function () { + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig({userSync: {}}); expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); it('handles config with usersync and userIds that are empty objs', function () { + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig({ userSync: { userIds: [{}] @@ -678,8 +534,8 @@ describe('User ID', function () { }); it('handles config with usersync and userIds with empty names or that dont match a submodule.name', function () { + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig({ userSync: { userIds: [{ @@ -695,16 +551,16 @@ describe('User ID', function () { }); it('config with 1 configurations should create 1 submodules', function () { + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig(getConfigMock(['unifiedId', 'unifiedid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.contain('User ID - usersync config updated for 1 submodules'); }); it('handles config with name in different case', function () { - init(config); setSubmoduleRegistry([criteoIdSubmodule]); + init(config); config.setConfig({ userSync: { userIds: [{ @@ -716,9 +572,9 @@ describe('User ID', function () { expect(utils.logInfo.args[0][0]).to.exist.and.to.contain('User ID - usersync config updated for 1 submodules'); }); - it('config with 24 configurations should result in 24 submodules add', function () { + it('config with 23 configurations should result in 23 submodules add', function () { + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, liveIntentIdSubmodule, britepoolIdSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, liveIntentIdSubmodule, britepoolIdSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, hadronIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig({ userSync: { syncDelay: 0, @@ -750,8 +606,8 @@ describe('User ID', function () { name: 'intentIqId', storage: {name: 'intentIqId', type: 'cookie'} }, { - name: 'hadronId', - storage: {name: 'hadronId', type: 'cookie'} + name: 'haloId', + storage: {name: 'haloId', type: 'cookie'} }, { name: 'zeotapIdPlus' }, { @@ -782,18 +638,16 @@ describe('User ID', function () { }, { name: 'kpuid', storage: {name: 'kpuid', type: 'cookie'} - }, { - name: 'qid', - storage: {name: 'qid', type: 'html5'} }] } }); - expect(utils.logInfo.args[0][0]).to.exist.and.to.contain('User ID - usersync config updated for 24 submodules'); + expect(utils.logInfo.args[0][0]).to.exist.and.to.contain('User ID - usersync config updated for 23 submodules'); }); it('config syncDelay updates module correctly', function () { + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); + init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, hadronIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig({ userSync: { syncDelay: 99, @@ -807,8 +661,8 @@ describe('User ID', function () { }); it('config auctionDelay updates module correctly', function () { + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, hadronIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig({ userSync: { auctionDelay: 100, @@ -822,8 +676,8 @@ describe('User ID', function () { }); it('config auctionDelay defaults to 0 if not a number', function () { + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, nextrollIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, hadronIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, flocIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig({ userSync: { auctionDelay: '', @@ -844,6 +698,8 @@ describe('User ID', function () { beforeEach(function () { sandbox = sinon.createSandbox(); + sandbox.stub(global, 'setTimeout').returns(2); + sandbox.stub(global, 'clearTimeout'); sandbox.stub(events, 'on'); sandbox.stub(coreStorage, 'getCookie'); @@ -869,7 +725,9 @@ describe('User ID', function () { return {callback: mockIdCallback}; } }; - initModule(config); + + init(config); + attachIdSystem(mockIdSystem, true); }); @@ -890,29 +748,30 @@ describe('User ID', function () { } }); - return runBidsHook(auctionSpy, {adUnits}).then(() => { - // check auction was delayed - startDelay.calledWith(33); - auctionSpy.calledOnce.should.equal(false); + requestBidsHook(auctionSpy, {adUnits}); - // check ids were fetched - mockIdCallback.calledOnce.should.equal(true); + // check auction was delayed + global.clearTimeout.calledOnce.should.equal(false); + global.setTimeout.calledOnce.should.equal(true); + global.setTimeout.calledWith(sinon.match.func, 33); + auctionSpy.calledOnce.should.equal(false); - // mock timeout - return startDelay.resolve(); - }).then(() => { - auctionSpy.calledOnce.should.equal(true); + // check ids were fetched + mockIdCallback.calledOnce.should.equal(true); - // does not call auction again once ids are synced - mockIdCallback.callArgWith(0, {'MOCKID': '1234'}); - auctionSpy.calledOnce.should.equal(true); + // callback to continue auction if timed out + global.setTimeout.callArg(0); + auctionSpy.calledOnce.should.equal(true); - // no sync after auction ends - events.on.called.should.equal(false); - }); + // does not call auction again once ids are synced + mockIdCallback.callArgWith(0, {'MOCKID': '1234'}); + auctionSpy.calledOnce.should.equal(true); + + // no sync after auction ends + events.on.called.should.equal(false); }); - it('delays auction if auctionDelay is set, continuing auction if ids are fetched before timing out', function () { + it('delays auction if auctionDelay is set, continuing auction if ids are fetched before timing out', function (done) { config.setConfig({ userSync: { auctionDelay: 33, @@ -923,32 +782,33 @@ describe('User ID', function () { } }); - return runBidsHook(auctionSpy, {adUnits}).then(() => { - // check auction was delayed - startDelay.calledWith(33); - auctionSpy.calledOnce.should.equal(false); + requestBidsHook(auctionSpy, {adUnits}); - // check ids were fetched - mockIdCallback.calledOnce.should.equal(true); + // check auction was delayed + // global.setTimeout.calledOnce.should.equal(true); + global.clearTimeout.calledOnce.should.equal(false); + global.setTimeout.calledWith(sinon.match.func, 33); + auctionSpy.calledOnce.should.equal(false); - // if ids returned, should continue auction - mockIdCallback.callArgWith(0, {'MOCKID': '1234'}); - return clearStack(); - }).then(() => { - auctionSpy.calledOnce.should.equal(true); + // check ids were fetched + mockIdCallback.calledOnce.should.equal(true); - // check ids were copied to bids - adUnits.forEach(unit => { - unit.bids.forEach(bid => { - expect(bid).to.have.deep.nested.property('userId.mid'); - expect(bid.userId.mid).to.equal('1234'); - expect(bid.userIdAsEids.length).to.equal(0);// "mid" is an un-known submodule for USER_IDS_CONFIG in eids.js - }); - }); + // if ids returned, should continue auction + mockIdCallback.callArgWith(0, {'MOCKID': '1234'}); + auctionSpy.calledOnce.should.equal(true); - // no sync after auction ends - events.on.called.should.equal(false); + // check ids were copied to bids + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.mid'); + expect(bid.userId.mid).to.equal('1234'); + expect(bid.userIdAsEids.length).to.equal(0);// "mid" is an un-known submodule for USER_IDS_CONFIG in eids.js + }); + done(); }); + + // no sync after auction ends + events.on.called.should.equal(false); }); it('does not delay auction if not set, delays id fetch after auction ends with syncDelay', function () { @@ -965,26 +825,26 @@ describe('User ID', function () { expect(auctionDelay).to.equal(0); expect(syncDelay).to.equal(77); - return expectImmediateBidHook(auctionSpy, {adUnits}) - .then(() => { - // should not delay auction - auctionSpy.calledOnce.should.equal(true); - - // check user sync is delayed after auction is ended - mockIdCallback.calledOnce.should.equal(false); - events.on.calledOnce.should.equal(true); - events.on.calledWith(CONSTANTS.EVENTS.AUCTION_END, sinon.match.func); - - // once auction is ended, sync user ids after delay - events.on.callArg(1); - callbackDelay.calledWith(77); - mockIdCallback.calledOnce.should.equal(false); - - return callbackDelay.resolve(); - }).then(() => { - // once sync delay is over, ids should be fetched - mockIdCallback.calledOnce.should.equal(true); - }); + requestBidsHook(auctionSpy, {adUnits}); + + // should not delay auction + global.setTimeout.calledOnce.should.equal(false); + auctionSpy.calledOnce.should.equal(true); + + // check user sync is delayed after auction is ended + mockIdCallback.calledOnce.should.equal(false); + events.on.calledOnce.should.equal(true); + events.on.calledWith(CONSTANTS.EVENTS.AUCTION_END, sinon.match.func); + + // once auction is ended, sync user ids after delay + events.on.callArg(1); + global.setTimeout.calledOnce.should.equal(true); + global.setTimeout.calledWith(sinon.match.func, 77); + mockIdCallback.calledOnce.should.equal(false); + + // once sync delay is over, ids should be fetched + global.setTimeout.callArg(0); + mockIdCallback.calledOnce.should.equal(true); }); it('does not delay user id sync after auction ends if set to 0', function () { @@ -999,23 +859,21 @@ describe('User ID', function () { expect(syncDelay).to.equal(0); - return expectImmediateBidHook(auctionSpy, {adUnits}) - .then(() => { - // auction should not be delayed - auctionSpy.calledOnce.should.equal(true); - - // sync delay after auction is ended - mockIdCallback.calledOnce.should.equal(false); - events.on.calledOnce.should.equal(true); - events.on.calledWith(CONSTANTS.EVENTS.AUCTION_END, sinon.match.func); - - // once auction is ended, if no sync delay, fetch ids - events.on.callArg(1); - callbackDelay.calledWith(0); - return callbackDelay.resolve(); - }).then(() => { - mockIdCallback.calledOnce.should.equal(true); - }); + requestBidsHook(auctionSpy, {adUnits}); + + // auction should not be delayed + global.setTimeout.calledOnce.should.equal(false); + auctionSpy.calledOnce.should.equal(true); + + // sync delay after auction is ended + mockIdCallback.calledOnce.should.equal(false); + events.on.calledOnce.should.equal(true); + events.on.calledWith(CONSTANTS.EVENTS.AUCTION_END, sinon.match.func); + + // once auction is ended, if no sync delay, fetch ids + events.on.callArg(1); + global.setTimeout.calledOnce.should.equal(false); + mockIdCallback.calledOnce.should.equal(true); }); it('does not delay auction if there are no ids to fetch', function () { @@ -1030,13 +888,14 @@ describe('User ID', function () { } }); - return runBidsHook(auctionSpy, {adUnits}).then(() => { - auctionSpy.calledOnce.should.equal(true); - mockIdCallback.calledOnce.should.equal(false); + requestBidsHook(auctionSpy, {adUnits}); - // no sync after auction ends - events.on.called.should.equal(false); - }); + global.setTimeout.calledOnce.should.equal(false); + auctionSpy.calledOnce.should.equal(true); + mockIdCallback.calledOnce.should.equal(false); + + // no sync after auction ends + events.on.called.should.equal(false); }); }); @@ -1050,8 +909,8 @@ describe('User ID', function () { it('test hook from pubcommonid cookie', function (done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 100000).toUTCString())); - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule]); + init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook(function () { @@ -1075,8 +934,8 @@ describe('User ID', function () { localStorage.setItem('pubcid', 'testpubcid'); localStorage.setItem('pubcid_exp', new Date(Date.now() + 100000).toUTCString()); - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule]); + init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'html5'])); requestBidsHook(function () { @@ -1097,8 +956,8 @@ describe('User ID', function () { }); it('test hook from pubcommonid config value object', function (done) { - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule]); + init(config); config.setConfig(getConfigValueMock('pubCommonId', {'pubcidvalue': 'testpubcidvalue'})); requestBidsHook(function () { @@ -1118,8 +977,8 @@ describe('User ID', function () { localStorage.setItem('unifiedid_alt', JSON.stringify({'TDID': 'testunifiedid_alt'})); localStorage.setItem('unifiedid_alt_exp', ''); - init(config); setSubmoduleRegistry([unifiedIdSubmodule]); + init(config); config.setConfig(getConfigMock(['unifiedId', 'unifiedid_alt', 'html5'])); requestBidsHook(function () { @@ -1144,8 +1003,8 @@ describe('User ID', function () { localStorage.setItem('amxId', 'test_amxid_id'); localStorage.setItem('amxId_exp', ''); - init(config); setSubmoduleRegistry([amxIdSubmodule]); + init(config); config.setConfig(getConfigMock(['amxId', 'amxId', 'html5'])); requestBidsHook(() => { @@ -1175,8 +1034,8 @@ describe('User ID', function () { localStorage.setItem('idl_env', 'AiGNC8Z5ONyZKSpIPf'); localStorage.setItem('idl_env_exp', ''); - init(config); setSubmoduleRegistry([identityLinkSubmodule]); + init(config); config.setConfig(getConfigMock(['identityLink', 'idl_env', 'html5'])); requestBidsHook(function () { adUnits.forEach(unit => { @@ -1198,8 +1057,8 @@ describe('User ID', function () { it('test hook from identityLink cookie', function (done) { coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 100000).toUTCString())); - init(config); setSubmoduleRegistry([identityLinkSubmodule]); + init(config); config.setConfig(getConfigMock(['identityLink', 'idl_env', 'cookie'])); requestBidsHook(function () { @@ -1221,8 +1080,8 @@ describe('User ID', function () { it('test hook from criteoIdModule cookie', function (done) { coreStorage.setCookie('storage_bidid', JSON.stringify({'criteoId': 'test_bidid'}), (new Date(Date.now() + 100000).toUTCString())); - init(config); setSubmoduleRegistry([criteoIdSubmodule]); + init(config); config.setConfig(getConfigMock(['criteo', 'storage_bidid', 'cookie'])); requestBidsHook(function () { @@ -1244,8 +1103,8 @@ describe('User ID', function () { it('test hook from tapadIdModule cookie', function (done) { coreStorage.setCookie('tapad_id', 'test-tapad-id', (new Date(Date.now() + 100000).toUTCString())); - init(config); setSubmoduleRegistry([tapadIdSubmodule]); + init(config); config.setConfig(getConfigMock(['tapadId', 'tapad_id', 'cookie'])); requestBidsHook(function () { @@ -1269,10 +1128,9 @@ describe('User ID', function () { localStorage.setItem('_li_pbid', JSON.stringify({'unifiedId': 'random-ls-identifier'})); localStorage.setItem('_li_pbid_exp', ''); - init(config); setSubmoduleRegistry([liveIntentIdSubmodule]); + init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'html5'])); - requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { @@ -1294,8 +1152,8 @@ describe('User ID', function () { // simulate existing browser local storage values coreStorage.setCookie('kpuid', 'KINESSO_ID', (new Date(Date.now() + 5000).toUTCString())); - init(config); setSubmoduleRegistry([kinessoIdSubmodule]); + init(config); config.setConfig(getConfigMock(['kpuid', 'kpuid', 'cookie'])); requestBidsHook(function () { @@ -1319,8 +1177,8 @@ describe('User ID', function () { localStorage.setItem('kpuid', 'KINESSO_ID'); localStorage.setItem('kpuid_exp', ''); - init(config); setSubmoduleRegistry([kinessoIdSubmodule]); + init(config); config.setConfig(getConfigMock(['kpuid', 'kpuid', 'html5'])); requestBidsHook(function () { @@ -1343,8 +1201,8 @@ describe('User ID', function () { it('test hook from liveIntentId cookie', function (done) { coreStorage.setCookie('_li_pbid', JSON.stringify({'unifiedId': 'random-cookie-identifier'}), (new Date(Date.now() + 100000).toUTCString())); - init(config); setSubmoduleRegistry([liveIntentIdSubmodule]); + init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'cookie'])); requestBidsHook(function () { @@ -1366,12 +1224,12 @@ describe('User ID', function () { it('eidPermissions fun with bidders', function (done) { coreStorage.setCookie('pubcid', 'test222', (new Date(Date.now() + 5000).toUTCString())); - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule]); let eidPermissions; getPrebidInternal().setEidPermissions = function (newEidPermissions) { eidPermissions = newEidPermissions; } + init(config); config.setConfig({ userSync: { syncDelay: 0, @@ -1432,12 +1290,12 @@ describe('User ID', function () { it('eidPermissions fun without bidders', function (done) { coreStorage.setCookie('pubcid', 'test222', new Date(Date.now() + 5000).toUTCString()); - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule]); let eidPermissions; getPrebidInternal().setEidPermissions = function (newEidPermissions) { eidPermissions = newEidPermissions; } + init(config); config.setConfig({ userSync: { syncDelay: 0, @@ -1479,8 +1337,8 @@ describe('User ID', function () { }); it('test hook from pubProvidedId config params', function (done) { - init(config); setSubmoduleRegistry([pubProvidedIdSubmodule]); + init(config); config.setConfig({ userSync: { syncDelay: 0, @@ -1580,8 +1438,8 @@ describe('User ID', function () { localStorage.setItem('_li_pbid', JSON.stringify({'unifiedId': 'random-ls-identifier', 'segments': ['123']})); localStorage.setItem('_li_pbid_exp', ''); - init(config); setSubmoduleRegistry([liveIntentIdSubmodule]); + init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'html5'])); requestBidsHook(function () { adUnits.forEach(unit => { @@ -1608,8 +1466,8 @@ describe('User ID', function () { 'segments': ['123'] }), (new Date(Date.now() + 100000).toUTCString())); - init(config); setSubmoduleRegistry([liveIntentIdSubmodule]); + init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'cookie'])); requestBidsHook(function () { @@ -1634,8 +1492,8 @@ describe('User ID', function () { // simulate existing browser local storage values coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': '279c0161-5152-487f-809e-05d7f7e653fd'}), (new Date(Date.now() + 5000).toUTCString())); - init(config); setSubmoduleRegistry([britepoolIdSubmodule]); + init(config); config.setConfig(getConfigMock(['britepoolId', 'britepoolid', 'cookie'])); requestBidsHook(function () { @@ -1658,8 +1516,8 @@ describe('User ID', function () { // simulate existing browser local storage values coreStorage.setCookie('dmdId', 'testdmdId', (new Date(Date.now() + 5000).toUTCString())); - init(config); setSubmoduleRegistry([dmdIdSubmodule]); + init(config); config.setConfig(getConfigMock(['dmdId', 'dmdId', 'cookie'])); requestBidsHook(function () { @@ -1682,8 +1540,8 @@ describe('User ID', function () { // simulate existing browser local storage values coreStorage.setCookie('netId', JSON.stringify({'netId': 'fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg'}), (new Date(Date.now() + 5000).toUTCString())); - init(config); setSubmoduleRegistry([netIdSubmodule]); + init(config); config.setConfig(getConfigMock(['netId', 'netId', 'cookie'])); requestBidsHook(function () { @@ -1706,8 +1564,8 @@ describe('User ID', function () { // simulate existing browser local storage values coreStorage.setCookie('intentIqId', 'abcdefghijk', (new Date(Date.now() + 5000).toUTCString())); - init(config); setSubmoduleRegistry([intentIqIdSubmodule]); + init(config); config.setConfig(getConfigMock(['intentIqId', 'intentIqId', 'cookie'])); requestBidsHook(function () { @@ -1726,28 +1584,28 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from hadronId html5', function (done) { + it('test hook from haloId html5', function (done) { // simulate existing browser local storage values - localStorage.setItem('hadronId', JSON.stringify({'hadronId': 'random-ls-identifier'})); - localStorage.setItem('hadronId_exp', ''); + localStorage.setItem('haloId', JSON.stringify({'haloId': 'random-ls-identifier'})); + localStorage.setItem('haloId_exp', ''); + setSubmoduleRegistry([haloIdSubmodule]); init(config); - setSubmoduleRegistry([hadronIdSubmodule]); - config.setConfig(getConfigMock(['hadronId', 'hadronId', 'html5'])); + config.setConfig(getConfigMock(['haloId', 'haloId', 'html5'])); requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { - expect(bid).to.have.deep.nested.property('userId.hadronId'); - expect(bid.userId.hadronId).to.equal('random-ls-identifier'); + expect(bid).to.have.deep.nested.property('userId.haloId'); + expect(bid.userId.haloId).to.equal('random-ls-identifier'); expect(bid.userIdAsEids[0]).to.deep.equal({ source: 'audigent.com', uids: [{id: 'random-ls-identifier', atype: 1}] }); }); }); - localStorage.removeItem('hadronId'); - localStorage.removeItem('hadronId_exp', ''); + localStorage.removeItem('haloId'); + localStorage.removeItem('haloId_exp', ''); done(); }, {adUnits}); }); @@ -1756,8 +1614,8 @@ describe('User ID', function () { // simulate existing browser local storage values coreStorage.setCookie('merkleId', JSON.stringify({'pam_id': {'id': 'testmerkleId', 'keyID': 1}}), (new Date(Date.now() + 5000).toUTCString())); - init(config); setSubmoduleRegistry([merkleIdSubmodule]); + init(config); config.setConfig(getConfigMock(['merkleId', 'merkleId', 'cookie'])); requestBidsHook(function () { @@ -1780,8 +1638,8 @@ describe('User ID', function () { // simulate existing browser local storage values coreStorage.setCookie('IDP', btoa(JSON.stringify('abcdefghijk')), (new Date(Date.now() + 5000).toUTCString())); - init(config); setSubmoduleRegistry([zeotapIdPlusSubmodule]); + init(config); config.setConfig(getConfigMock(['zeotapIdPlus', 'IDP', 'cookie'])); requestBidsHook(function () { @@ -1804,8 +1662,8 @@ describe('User ID', function () { // simulate existing browser local storage values coreStorage.setCookie('mwol', JSON.stringify({eid: 'XX-YY-ZZ-123'}), (new Date(Date.now() + 5000).toUTCString())); - init(config); setSubmoduleRegistry([mwOpenLinkIdSubModule]); + init(config); config.setConfig(getConfigMock(['mwOpenLinkId', 'mwol', 'cookie'])); requestBidsHook(function () { @@ -1825,8 +1683,8 @@ describe('User ID', function () { localStorage.setItem('admixerId', 'testadmixerId'); localStorage.setItem('admixerId_exp', ''); - init(config); setSubmoduleRegistry([admixerIdSubmodule]); + init(config); config.setConfig(getConfigMock(['admixerId', 'admixerId', 'html5'])); requestBidsHook(function () { adUnits.forEach(unit => { @@ -1847,8 +1705,8 @@ describe('User ID', function () { it('test hook from admixerId cookie', function (done) { coreStorage.setCookie('admixerId', 'testadmixerId', (new Date(Date.now() + 100000).toUTCString())); - init(config); setSubmoduleRegistry([admixerIdSubmodule]); + init(config); config.setConfig(getConfigMock(['admixerId', 'admixerId', 'cookie'])); requestBidsHook(function () { @@ -1871,8 +1729,8 @@ describe('User ID', function () { // simulate existing browser local storage values coreStorage.setCookie('deepintentId', 'testdeepintentId', (new Date(Date.now() + 5000).toUTCString())); - init(config); setSubmoduleRegistry([deepintentDpesSubmodule]); + init(config); config.setConfig(getConfigMock(['deepintentId', 'deepintentId', 'cookie'])); requestBidsHook(function () { @@ -1896,8 +1754,8 @@ describe('User ID', function () { localStorage.setItem('deepintentId', 'testdeepintentId'); localStorage.setItem('deepintentId_exp', ''); - init(config); setSubmoduleRegistry([deepintentDpesSubmodule]); + init(config); config.setConfig(getConfigMock(['deepintentId', 'deepintentId', 'html5'])); requestBidsHook(function () { adUnits.forEach(unit => { @@ -1914,38 +1772,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from qid html5', (done) => { - // simulate existing localStorage values - localStorage.setItem('qid', 'testqid'); - localStorage.setItem('qid_exp', ''); - - init(config); - setSubmoduleRegistry([adqueryIdSubmodule]); - config.setConfig(getConfigMock(['qid', 'qid', 'html5'])); - - requestBidsHook(() => { - adUnits.forEach((adUnit) => { - adUnit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('userId.qid'); - expect(bid.userId.qid).to.equal('testqid'); - expect(bid.userIdAsEids[0]).to.deep.equal({ - source: 'adquery.io', - uids: [{ - id: 'testqid', - atype: 1, - }] - }); - }); - }); - - // clear LS - localStorage.removeItem('qid'); - localStorage.removeItem('qid_exp'); - done(); - }, {adUnits}); - }); - - it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId, intentIqId, zeotapIdPlus, netId, hadronId, Criteo, UID 2.0, admixerId, amxId, dmdId, kpuid, qid and mwOpenLinkId have data to pass', function (done) { + it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId, intentIqId, zeotapIdPlus, netId, haloId, Criteo, UID 2.0, admixerId, amxId, dmdId, kpuid and mwOpenLinkId have data to pass', function (done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('id5id', JSON.stringify({'universal_uid': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); @@ -1955,21 +1782,20 @@ describe('User ID', function () { coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('intentIqId', 'testintentIqId', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('IDP', btoa(JSON.stringify('zeotapId')), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('hadronId', JSON.stringify({'hadronId': 'testHadronId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('haloId', JSON.stringify({'haloId': 'testHaloId'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('storage_criteo', JSON.stringify({'criteoId': 'test_bidid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('mwol', JSON.stringify({eid: 'XX-YY-ZZ-123'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('uid2id', 'Sample_AD_Token', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('admixerId', 'testadmixerId', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('deepintentId', 'testdeepintentId', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('kpuid', 'KINESSO_ID', (new Date(Date.now() + 5000).toUTCString())); + // amxId only supports localStorage localStorage.setItem('amxId', 'test_amxid_id'); localStorage.setItem('amxId_exp', (new Date(Date.now() + 5000)).toUTCString()); - // qid only supports localStorage - localStorage.setItem('qid', 'testqid'); - localStorage.setItem('qid_exp', (new Date(Date.now() + 5000)).toUTCString()); + + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, hadronIdSubmodule, criteoIdSubmodule, mwOpenLinkIdSubModule, tapadIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', 'cookie'], ['id5Id', 'id5id', 'cookie'], @@ -1979,7 +1805,7 @@ describe('User ID', function () { ['netId', 'netId', 'cookie'], ['intentIqId', 'intentIqId', 'cookie'], ['zeotapIdPlus', 'IDP', 'cookie'], - ['hadronId', 'hadronId', 'cookie'], + ['haloId', 'haloId', 'cookie'], ['criteo', 'storage_criteo', 'cookie'], ['mwOpenLinkId', 'mwol', 'cookie'], ['tapadId', 'tapad_id', 'cookie'], @@ -1987,8 +1813,7 @@ describe('User ID', function () { ['admixerId', 'admixerId', 'cookie'], ['amxId', 'amxId', 'html5'], ['deepintentId', 'deepintentId', 'cookie'], - ['kpuid', 'kpuid', 'cookie'], - ['qid', 'qid', 'html5'])); + ['kpuid', 'kpuid', 'cookie'])); requestBidsHook(function () { adUnits.forEach(unit => { @@ -2020,9 +1845,9 @@ describe('User ID', function () { // also check that zeotapIdPlus id data was copied to bid expect(bid).to.have.deep.nested.property('userId.IDP'); expect(bid.userId.IDP).to.equal('zeotapId'); - // also check that hadronId id was copied to bid - expect(bid).to.have.deep.nested.property('userId.hadronId'); - expect(bid.userId.hadronId).to.equal('testHadronId'); + // also check that haloId id was copied to bid + expect(bid).to.have.deep.nested.property('userId.haloId'); + expect(bid.userId.haloId).to.equal('testHaloId'); // also check that criteo id was copied to bid expect(bid).to.have.deep.nested.property('userId.criteoId'); expect(bid.userId.criteoId).to.equal('test_bidid'); @@ -2046,10 +1871,7 @@ describe('User ID', function () { expect(bid).to.have.deep.nested.property('userId.kpuid'); expect(bid.userId.kpuid).to.equal('KINESSO_ID'); - expect(bid).to.have.deep.nested.property('userId.qid'); - expect(bid.userId.qid).to.equal('testqid'); - - expect(bid.userIdAsEids.length).to.equal(18); + expect(bid.userIdAsEids.length).to.equal(17); }); }); coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); @@ -2061,7 +1883,7 @@ describe('User ID', function () { coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('intentIqId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('IDP', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('hadronId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('haloId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('storage_criteo', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('mwol', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('uid2id', '', EXPIRED_COOKIE_DATE); @@ -2070,17 +1892,154 @@ describe('User ID', function () { coreStorage.setCookie('kpuid', EXPIRED_COOKIE_DATE); localStorage.removeItem('amxId'); localStorage.removeItem('amxId_exp'); - localStorage.removeItem('qid'); - localStorage.removeItem('qid_exp'); done(); }, {adUnits}); }); - it('test hook from UID2 cookie', function (done) { + it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, dmdId, intentIqId, zeotapIdPlus, criteo, netId, haloId, UID 2.0, admixerId, kpuid and mwOpenLinkId have their modules added before and after init', function (done) { + coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('id5id', JSON.stringify({'universal_uid': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('intentIqId', 'testintentIqId', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('IDP', btoa(JSON.stringify('zeotapId')), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('haloId', JSON.stringify({'haloId': 'testHaloId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('dmdId', 'testdmdId', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('storage_criteo', JSON.stringify({'criteoId': 'test_bidid'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('mwol', JSON.stringify({eid: 'XX-YY-ZZ-123'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('uid2id', 'Sample_AD_Token', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('admixerId', 'testadmixerId', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('deepintentId', 'testdeepintentId', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('kpuid', 'KINESSO_ID', (new Date(Date.now() + 5000).toUTCString())); + + setSubmoduleRegistry([]); + + // attaching before init + attachIdSystem(sharedIdSystemSubmodule); init(config); + + // attaching after init + attachIdSystem(unifiedIdSubmodule); + attachIdSystem(id5IdSubmodule); + attachIdSystem(identityLinkSubmodule); + attachIdSystem(britepoolIdSubmodule); + attachIdSystem(netIdSubmodule); + attachIdSystem(intentIqIdSubmodule); + attachIdSystem(zeotapIdPlusSubmodule); + attachIdSystem(haloIdSubmodule); + attachIdSystem(dmdIdSubmodule); + attachIdSystem(criteoIdSubmodule); + attachIdSystem(mwOpenLinkIdSubModule); + attachIdSystem(tapadIdSubmodule); + attachIdSystem(uid2IdSubmodule); + attachIdSystem(admixerIdSubmodule); + attachIdSystem(deepintentDpesSubmodule); + attachIdSystem(kinessoIdSubmodule); + + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], + ['unifiedId', 'unifiedid', 'cookie'], + ['id5Id', 'id5id', 'cookie'], + ['identityLink', 'idl_env', 'cookie'], + ['britepoolId', 'britepoolid', 'cookie'], + ['netId', 'netId', 'cookie'], + ['intentIqId', 'intentIqId', 'cookie'], + ['zeotapIdPlus', 'IDP', 'cookie'], + ['haloId', 'haloId', 'cookie'], + ['dmdId', 'dmdId', 'cookie'], + ['criteo', 'storage_criteo', 'cookie'], + ['mwOpenLinkId', 'mwol', 'cookie'], + ['tapadId', 'tapad_id', 'cookie'], + ['uid2', 'uid2id', 'cookie'], + ['admixerId', 'admixerId', 'cookie'], + ['deepintentId', 'deepintentId', 'cookie'], + ['kpuid', 'kpuid', 'cookie'])); + + requestBidsHook(function () { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + // verify that the PubCommonId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal('testpubcid'); + // also check that UnifiedId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.tdid'); + expect(bid.userId.tdid).to.equal('cookie-value-add-module-variations'); + // also check that Id5Id id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.id5id.uid'); + expect(bid.userId.id5id.uid).to.equal('testid5id'); + // also check that identityLink id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.idl_env'); + expect(bid.userId.idl_env).to.equal('AiGNC8Z5ONyZKSpIPf'); + // also check that britepoolId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.britepoolid'); + expect(bid.userId.britepoolid).to.equal('testbritepoolid'); + // also check that britepoolId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.netId'); + expect(bid.userId.netId).to.equal('testnetId'); + // also check that intentIqId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.intentIqId'); + expect(bid.userId.intentIqId).to.equal('testintentIqId'); + + // also check that zeotapIdPlus id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.IDP'); + expect(bid.userId.IDP).to.equal('zeotapId'); + // also check that haloId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.haloId'); + expect(bid.userId.haloId).to.equal('testHaloId'); + // also check that dmdId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.dmdId'); + expect(bid.userId.dmdId).to.equal('testdmdId'); + + // also check that criteo id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.criteoId'); + expect(bid.userId.criteoId).to.equal('test_bidid'); + + // also check that mwOpenLink id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.mwOpenLinkId'); + expect(bid.userId.mwOpenLinkId).to.equal('XX-YY-ZZ-123') + expect(bid.userId.uid2).to.deep.equal({ + id: 'Sample_AD_Token' + }); + + // also check that admixerId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.admixerId'); + expect(bid.userId.admixerId).to.equal('testadmixerId'); + // also check that deepintentId was copied to bid + expect(bid).to.have.deep.nested.property('userId.deepintentId'); + expect(bid.userId.deepintentId).to.equal('testdeepintentId'); + expect(bid).to.have.deep.nested.property('userId.kpuid'); + expect(bid.userId.kpuid).to.equal('KINESSO_ID'); + + expect(bid.userIdAsEids.length).to.equal(16); + }); + }); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('intentIqId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('IDP', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('haloId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('dmdId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('storage_criteo', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('mwol', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('uid2id', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('admixerId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('deepintentId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('kpuid', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); + }); + + it('test hook from UID2 cookie', function (done) { + coreStorage.setCookie('uid2id', 'Sample_AD_Token', (new Date(Date.now() + 5000).toUTCString())); + setSubmoduleRegistry([uid2IdSubmodule]); + init(config); config.setConfig(getConfigMock(['uid2', 'uid2id', 'cookie'])); requestBidsHook(function () { @@ -2114,7 +2073,7 @@ describe('User ID', function () { coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('intentIqId', 'testintentIqId', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('IDP', btoa(JSON.stringify('zeotapId')), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('hadronId', JSON.stringify({'hadronId': 'testHadronId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('haloId', JSON.stringify({'haloId': 'testHaloId'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('admixerId', 'testadmixerId', new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('deepintentId', 'testdeepintentId', new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); @@ -2122,11 +2081,9 @@ describe('User ID', function () { localStorage.setItem('amxId', 'test_amxid_id'); localStorage.setItem('amxId_exp', new Date(Date.now() + 5000).toUTCString()) coreStorage.setCookie('kpuid', 'KINESSO_ID', (new Date(Date.now() + 5000).toUTCString())); - localStorage.setItem('qid', 'testqid'); - localStorage.setItem('qid_exp', new Date(Date.now() + 5000).toUTCString()) + setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule]); init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, hadronIdSubmodule, uid2IdSubmodule, admixerIdSubmodule, deepintentDpesSubmodule, dmdIdSubmodule, akamaiDAPIdSubmodule, amxIdSubmodule, kinessoIdSubmodule, adqueryIdSubmodule]); config.setConfig({ userSync: { @@ -2150,7 +2107,7 @@ describe('User ID', function () { }, { name: 'zeotapIdPlus' }, { - name: 'hadronId', storage: {name: 'hadronId', type: 'cookie'} + name: 'haloId', storage: {name: 'haloId', type: 'cookie'} }, { name: 'admixerId', storage: {name: 'admixerId', type: 'cookie'} }, { @@ -2163,8 +2120,6 @@ describe('User ID', function () { name: 'amxId', storage: {name: 'amxId', type: 'html5'} }, { name: 'kpuid', storage: {name: 'kpuid', type: 'cookie'} - }, { - name: 'qid', storage: {name: 'qid', type: 'html5'} }] } }); @@ -2216,9 +2171,9 @@ describe('User ID', function () { // also check that zeotapIdPlus id data was copied to bid expect(bid).to.have.deep.nested.property('userId.IDP'); expect(bid.userId.IDP).to.equal('zeotapId'); - // also check that hadronId id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.hadronId'); - expect(bid.userId.hadronId).to.equal('testHadronId'); + // also check that haloId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.haloId'); + expect(bid.userId.haloId).to.equal('testHaloId'); expect(bid.userId.uid2).to.deep.equal({ id: 'Sample_AD_Token' }); @@ -2236,10 +2191,7 @@ describe('User ID', function () { expect(bid).to.have.deep.nested.property('userId.kpuid'); expect(bid.userId.kpuid).to.equal('KINESSO_ID'); - - expect(bid).to.have.deep.nested.property('userId.qid'); - expect(bid.userId.qid).to.equal('testqid'); - expect(bid.userIdAsEids.length).to.equal(16); + expect(bid.userIdAsEids.length).to.equal(15); }); }); coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); @@ -2250,7 +2202,7 @@ describe('User ID', function () { coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('intentIqId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('IDP', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('hadronId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('haloId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('dmdId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('admixerId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('deepintentId', '', EXPIRED_COOKIE_DATE); @@ -2283,28 +2235,22 @@ describe('User ID', function () { delete window.__tcfapi; }); - function endAuction() { - events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); - return new Promise((resolve) => setTimeout(resolve)); - } - it('pubcid callback with url', function () { let adUnits = [getAdUnitMock()]; let innerAdUnits; let customCfg = getConfigMock(['pubCommonId', 'pubcid', 'cookie']); customCfg = addConfig(customCfg, 'params', {pixelUrl: '/any/pubcid/url'}); - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule]); + init(config); config.setConfig(customCfg); - return runBidsHook((config) => { + requestBidsHook((config) => { innerAdUnits = config.adUnits - }, {adUnits}).then(() => { - expect(utils.triggerPixel.called).to.be.false; - return endAuction(); - }).then(() => { - expect(utils.triggerPixel.getCall(0).args[0]).to.include('/any/pubcid/url'); - }); + }, {adUnits}); + + expect(utils.triggerPixel.called).to.be.false; + events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); + expect(utils.triggerPixel.getCall(0).args[0]).to.include('/any/pubcid/url'); }); it('unifiedid callback with url', function () { @@ -2313,17 +2259,16 @@ describe('User ID', function () { let customCfg = getConfigMock(['unifiedId', 'unifiedid', 'cookie']); addConfig(customCfg, 'params', {url: '/any/unifiedid/url'}); - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule]); + init(config); config.setConfig(customCfg); - return runBidsHook((config) => { + requestBidsHook((config) => { innerAdUnits = config.adUnits - }, {adUnits}).then(() => { - expect(server.requests).to.be.empty; - return endAuction(); - }).then(() => { - expect(server.requests[0].url).to.equal('/any/unifiedid/url'); - }); + }, {adUnits}); + + expect(server.requests).to.be.empty; + events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); + expect(server.requests[0].url).to.equal('/any/unifiedid/url'); }); it('unifiedid callback with partner', function () { @@ -2332,17 +2277,16 @@ describe('User ID', function () { let customCfg = getConfigMock(['unifiedId', 'unifiedid', 'cookie']); addConfig(customCfg, 'params', {partner: 'rubicon'}); - init(config); setSubmoduleRegistry([sharedIdSystemSubmodule, unifiedIdSubmodule]); + init(config); config.setConfig(customCfg); - return runBidsHook((config) => { + requestBidsHook((config) => { innerAdUnits = config.adUnits - }, {adUnits}).then(() => { - expect(server.requests).to.be.empty; - return endAuction(); - }).then(() => { - expect(server.requests[0].url).to.equal('https://match.adsrvr.org/track/rid?ttd_pid=rubicon&fmt=json'); - }); + }, {adUnits}); + + expect(server.requests).to.be.empty; + events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); + expect(server.requests[0].url).to.equal('https://match.adsrvr.org/track/rid?ttd_pid=rubicon&fmt=json'); }); }); @@ -2390,44 +2334,40 @@ describe('User ID', function () { describe('Consent changes determine getId refreshes', function () { let expStr; let adUnits; - let mockGetId; - let mockDecode; - let mockExtendId; - let mockIdSystem; - let userIdConfig; const mockIdCookieName = 'MOCKID'; + let mockGetId = sinon.stub(); + let mockDecode = sinon.stub(); + let mockExtendId = sinon.stub(); + const mockIdSystem = { + name: 'mockId', + getId: mockGetId, + decode: mockDecode, + extendId: mockExtendId + }; + const userIdConfig = { + userSync: { + userIds: [{ + name: 'mockId', + storage: { + name: 'MOCKID', + type: 'cookie', + refreshInSeconds: 30 + } + }], + auctionDelay: 5 + } + }; - beforeEach(function () { - mockGetId = sinon.stub(); - mockDecode = sinon.stub(); - mockExtendId = sinon.stub(); - mockIdSystem = { - name: 'mockId', - getId: mockGetId, - decode: mockDecode, - extendId: mockExtendId - }; - userIdConfig = { - userSync: { - userIds: [{ - name: 'mockId', - storage: { - name: 'MOCKID', - type: 'cookie', - refreshInSeconds: 30 - } - }], - auctionDelay: 5 - } - }; + let cmpStub; + let testConsentData; + const consentConfig = { + cmpApi: 'iab', + timeout: 7500, + allowAuctionWithoutConsent: false + }; - consentData = { - gdprApplies: true, - consentString: 'mockString', - apiVersion: 1, - hasValidated: true // mock presence of GPDR enforcement module - } + const sharedBeforeFunction = function () { // clear cookies expStr = (new Date(Date.now() + 25000).toUTCString()); coreStorage.setCookie(mockIdCookieName, '', EXPIRED_COOKIE_DATE); @@ -2441,237 +2381,177 @@ describe('User ID', function () { // init id system attachIdSystem(mockIdSystem); config.setConfig(userIdConfig); - }); - - afterEach(function () { + } + const sharedAfterFunction = function () { config.resetConfig(); - }); + mockGetId.reset(); + mockDecode.reset(); + mockExtendId.reset(); + cmpStub.restore(); + resetConsentData(); + delete window.__cmp; + delete window.__tcfapi; + }; - it('calls getId if no stored consent data and refresh is not needed', function () { - coreStorage.setCookie(mockIdCookieName, JSON.stringify({id: '1234'}), expStr); - coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); + describe('TCF v1', function () { + testConsentData = { + gdprApplies: true, + consentData: 'xyz', + apiVersion: 1 + }; + + beforeEach(function () { + sharedBeforeFunction(); + + // init v1 consent management + window.__cmp = function () { + }; + delete window.__tcfapi; + cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { + args[2](testConsentData); + }); + setConsentConfig(consentConfig); + }); + + afterEach(function () { + sharedAfterFunction(); + }); + + it('calls getId if no stored consent data and refresh is not needed', function () { + coreStorage.setCookie(mockIdCookieName, JSON.stringify({id: '1234'}), expStr); + coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); + + let innerAdUnits; + consentManagementRequestBidsHook(() => { + }, {}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); - let innerAdUnits; - return runBidsHook((config) => { - innerAdUnits = config.adUnits - }, {adUnits}).then(() => { sinon.assert.calledOnce(mockGetId); sinon.assert.calledOnce(mockDecode); sinon.assert.notCalled(mockExtendId); }); - }); - it('calls getId if no stored consent data but refresh is needed', function () { - coreStorage.setCookie(mockIdCookieName, JSON.stringify({id: '1234'}), expStr); - coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 60 * 1000).toUTCString()), expStr); + it('calls getId if no stored consent data but refresh is needed', function () { + coreStorage.setCookie(mockIdCookieName, JSON.stringify({id: '1234'}), expStr); + coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 60 * 1000).toUTCString()), expStr); + + let innerAdUnits; + consentManagementRequestBidsHook(() => { + }, {}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); - let innerAdUnits; - return runBidsHook((config) => { - innerAdUnits = config.adUnits - }, {adUnits}).then(() => { sinon.assert.calledOnce(mockGetId); sinon.assert.calledOnce(mockDecode); sinon.assert.notCalled(mockExtendId); }); - }); - it('calls getId if empty stored consent and refresh not needed', function () { - coreStorage.setCookie(mockIdCookieName, JSON.stringify({id: '1234'}), expStr); - coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); + it('calls getId if empty stored consent and refresh not needed', function () { + coreStorage.setCookie(mockIdCookieName, JSON.stringify({id: '1234'}), expStr); + coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); - setStoredConsentData(); + setStoredConsentData(); + + let innerAdUnits; + consentManagementRequestBidsHook(() => { + }, {}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); - let innerAdUnits; - return runBidsHook((config) => { - innerAdUnits = config.adUnits - }, {adUnits}).then(() => { sinon.assert.calledOnce(mockGetId); sinon.assert.calledOnce(mockDecode); sinon.assert.notCalled(mockExtendId); }); - }); - it('calls getId if stored consent does not match current consent and refresh not needed', function () { - coreStorage.setCookie(mockIdCookieName, JSON.stringify({id: '1234'}), expStr); - coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); + it('calls getId if stored consent does not match current consent and refresh not needed', function () { + coreStorage.setCookie(mockIdCookieName, JSON.stringify({id: '1234'}), expStr); + coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); - setStoredConsentData({...consentData, consentString: 'different'}); + setStoredConsentData({ + gdprApplies: testConsentData.gdprApplies, + consentString: 'abc', + apiVersion: testConsentData.apiVersion + }); + + let innerAdUnits; + consentManagementRequestBidsHook(() => { + }, {}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); - let innerAdUnits; - return runBidsHook((config) => { - innerAdUnits = config.adUnits - }, {adUnits}).then(() => { sinon.assert.calledOnce(mockGetId); sinon.assert.calledOnce(mockDecode); sinon.assert.notCalled(mockExtendId); }); - }); - it('does not call getId if stored consent matches current consent and refresh not needed', function () { - coreStorage.setCookie(mockIdCookieName, JSON.stringify({id: '1234'}), expStr); - coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); + it('does not call getId if stored consent matches current consent and refresh not needed', function () { + coreStorage.setCookie(mockIdCookieName, JSON.stringify({id: '1234'}), expStr); + coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); - setStoredConsentData({...consentData}); + setStoredConsentData({ + gdprApplies: testConsentData.gdprApplies, + consentString: testConsentData.consentData, + apiVersion: testConsentData.apiVersion + }); + + let innerAdUnits; + consentManagementRequestBidsHook(() => { + }, {}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); - let innerAdUnits; - return runBidsHook((config) => { - innerAdUnits = config.adUnits - }, {adUnits}).then(() => { sinon.assert.notCalled(mockGetId); sinon.assert.calledOnce(mockDecode); sinon.assert.calledOnce(mockExtendId); }); }); - }); - - describe('findRootDomain', function () { - let sandbox; - beforeEach(function () { - init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule]); - config.setConfig({ - userSync: { - syncDelay: 0, - userIds: [ - { - name: 'pubCommonId', - value: { pubcid: '11111' }, - }, - ], - }, - }); - sandbox = sinon.createSandbox(); - sandbox - .stub(coreStorage, 'getCookie') - .onFirstCall() - .returns(null) // .co.uk - .onSecondCall() - .returns('writeable'); // realdomain.co.uk; - }); - - afterEach(function () { - sandbox.restore(); - }); - - it('should just find the root domain', function () { - var domain = findRootDomain('sub.realdomain.co.uk'); - expect(domain).to.be.eq('realdomain.co.uk'); - }); - - it('should find the full domain when no subdomain is present', function () { - var domain = findRootDomain('realdomain.co.uk'); - expect(domain).to.be.eq('realdomain.co.uk'); - }); - }); - }); - - describe('handles config with ESP configuration in user sync object', function() { - describe('Call registerSignalSources to register signal sources with gtag', function () { - it('pbjs.registerSignalSources should be defined', () => { - expect(typeof (getGlobal()).registerSignalSources).to.equal('function'); - }); - }) - - describe('Call getEncryptedEidsForSource to get encrypted Eids for source', function() { - const signalSources = ['pubcid.org']; - - it('pbjs.getEncryptedEidsForSource should be defined', () => { - expect(typeof (getGlobal()).getEncryptedEidsForSource).to.equal('function'); - }); - - it('pbjs.getEncryptedEidsForSource should return the string without encryption if encryption is false', (done) => { - init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule]); - config.setConfig({ - userSync: { - auctionDelay: 10, - userIds: [ - { - 'name': 'sharedId', - 'storage': { - 'type': 'cookie', - 'name': '_pubcid', - 'expires': 365 - } - }, - { - 'name': 'pubcid.org' - } - ] - }, - }); - const encrypt = false; - (getGlobal()).getEncryptedEidsForSource(signalSources[0], encrypt).then((data) => { - let users = (getGlobal()).getUserIdsAsEids(); - expect(data).to.equal(users[0].uids[0].id); - done(); - }).catch(done); - }); + describe('findRootDomain', function () { + let sandbox; - describe('pbjs.getEncryptedEidsForSource', () => { - beforeEach(() => { - init(config); + beforeEach(function () { setSubmoduleRegistry([sharedIdSystemSubmodule]); + init(config); config.setConfig({ userSync: { - auctionDelay: 10, - userIds: [{ - name: 'pubCommonId', value: {'pubcid': '11111'} - }] - } + syncDelay: 0, + userIds: [ + { + name: 'pubCommonId', + value: { pubcid: '11111' }, + }, + ], + }, }); + sandbox = sinon.createSandbox(); + sandbox + .stub(coreStorage, 'getCookie') + .onFirstCall() + .returns(null) // .co.uk + .onSecondCall() + .returns('writeable'); // realdomain.co.uk; }); - it('should return the string base64 encryption if encryption is true', (done) => { - const encrypt = true; - (getGlobal()).getEncryptedEidsForSource(signalSources[0], encrypt).then((result) => { - expect(result.startsWith('1||')).to.true; - done(); - }).catch(done); + afterEach(function () { + sandbox.restore(); }); - it('pbjs.getEncryptedEidsForSource should return string if custom function is defined', () => { - const getCustomSignal = () => { - return '{"keywords":["tech","auto"]}'; - } - const expectedString = '1||eyJrZXl3b3JkcyI6WyJ0ZWNoIiwiYXV0byJdfQ=='; - const encrypt = false; - const source = 'pubmatic.com'; - return (getGlobal()).getEncryptedEidsForSource(source, encrypt, getCustomSignal).then((result) => { - expect(result).to.equal(expectedString); - }); + it('should just find the root domain', function () { + var domain = findRootDomain('sub.realdomain.co.uk'); + expect(domain).to.be.eq('realdomain.co.uk'); }); - }); - it('pbjs.getUserIdsAsEidBySource', (done) => { - const users = { - 'source': 'pubcid.org', - 'uids': [ - { - 'id': '11111', - 'atype': 1 - } - ] - } - init(config); - setSubmoduleRegistry([sharedIdSystemSubmodule, amxIdSubmodule]); - config.setConfig({ - userSync: { - auctionDelay: 10, - userIds: [{ - name: 'pubCommonId', value: {'pubcid': '11111'} - }, { - name: 'amxId', value: {'amxId': 'amx-id-value-amx-id-value-amx-id-value'} - }] - } - }); - expect(typeof (getGlobal()).getUserIdsAsEidBySource).to.equal('function'); - (getGlobal()).getUserIdsAsync().then(() => { - expect(getGlobal().getUserIdsAsEidBySource(signalSources[0])).to.deep.equal(users); - done(); + it('should find the full domain when no subdomain is present', function () { + var domain = findRootDomain('realdomain.co.uk'); + expect(domain).to.be.eq('realdomain.co.uk'); }); }); - }) - }); + }); + }) }); diff --git a/test/spec/modules/validationFpdModule_spec.js b/test/spec/modules/validationFpdModule_spec.js index b60360733d6..9e8072cb9ed 100644 --- a/test/spec/modules/validationFpdModule_spec.js +++ b/test/spec/modules/validationFpdModule_spec.js @@ -309,87 +309,5 @@ describe('the first party data validation module', function () { validated = validateFpd(duplicate); expect(validated).to.deep.equal(expected); }); - - it('filters bcat, badv for invalid data type', function () { - const duplicate = utils.deepClone(ortb2); - duplicate.badv = 'adadadbcd.com'; - duplicate.bcat = ['IAB25', 'IAB7-39']; - - const expected = { - device: { - h: 911, - w: 1733 - }, - user: { - data: [{ - segment: [{ - id: 'foo' - }], - name: 'bar' - }] - }, - site: { - content: { - data: [{ - segment: [{ - id: 'test' - }], - name: 'content', - ext: { - foo: 'bar' - } - }] - } - }, - bcat: ['IAB25', 'IAB7-39'] - }; - - const validated = validateFpd(duplicate); - expect(validated).to.deep.equal(expected); - }); - - it('filters site.publisher object properties for invalid data type', function () { - const duplicate = utils.deepClone(ortb2); - duplicate.site.publisher = { - id: '1', - domain: ['xyz.com'], - name: 'xyz', - }; - - const expected = { - device: { - h: 911, - w: 1733 - }, - user: { - data: [{ - segment: [{ - id: 'foo' - }], - name: 'bar' - }] - }, - site: { - content: { - data: [{ - segment: [{ - id: 'test' - }], - name: 'content', - ext: { - foo: 'bar' - } - }] - }, - publisher: { - id: '1', - name: 'xyz', - } - } - }; - - const validated = validateFpd(duplicate); - expect(validated).to.deep.equal(expected); - }); }); }); diff --git a/test/spec/modules/ventesBidAdapter_spec.js b/test/spec/modules/ventesBidAdapter_spec.js deleted file mode 100644 index 219c24deced..00000000000 --- a/test/spec/modules/ventesBidAdapter_spec.js +++ /dev/null @@ -1,845 +0,0 @@ -import { expect } from 'chai'; -import * as utils from 'src/utils.js'; -import { spec } from 'modules/ventesBidAdapter.js'; - -const BIDDER_URL = 'http://13.234.201.146:8088/va/ad'; - -describe('Ventes Adapter', function () { - const examples = { - adUnit_banner: { - adUnitCode: 'ad_unit_banner', - bidder: 'ventes', - bidderRequestId: 'bid_request_id', - bidId: 'bid_id', - params: { - publisherId: 'agltb3B1Yi1pbmNyDAsSA0FwcBiJkfTUCV', - placementId: 'VA-062-0013-0183', - device: { - ip: '123.145.167.189', - ifa: 'AEBE52E7-03EE-455A-B3C4-E57283966239', - } - }, - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - } - }, - - adUnitContext: { - refererInfo: { - referer: 'https://ventesavenues.in', - } - }, - - serverRequest_banner: { - method: 'POST', - url: 'http://13.234.201.146:8088/va/ad', - data: { - id: 'bid_request_id', - imp: [ - { - id: 'imp_id_banner', - banner: { - format: [{ - w: 300, - h: 200 - }] - } - } - ], - site: { - page: 'https://ventesavenues.in', - domain: 'ventesavenues.in', - name: 'ventesavenues.in' - }, - device: { - ua: '', - ip: '123.145.167.189', - ifa: 'AEBE52E7-03EE-455A-B3C4-E57283966239', - language: 'en' - }, - user: null, - regs: null, - at: 1 - } - }, - serverResponse_banner: { - body: { - cur: 'USD', - seatbid: [ - { - seat: '4', - bid: [ - { - id: 'id', - impid: 'imp_id_banner', - cid: 'campaign_id', - crid: 'creative_id', - adm: '..', - price: 1.5, - w: 300, - h: 200 - } - ] - } - ] - } - } - }; - - describe('isBidRequestValid', function () { - describe('General', function () { - it('should return false when not given an ad unit', function () { - const adUnit = undefined; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an invalid ad unit', function () { - const adUnit = 'bad_bid'; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit without bidder code', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.bidder = undefined; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with a bad bidder code', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.bidder = 'unknownBidder'; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit without ad unit code', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.adUnitCode = undefined; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with an invalid ad unit code', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.adUnitCode = {}; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit without bid request identifier', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.bidderRequestId = undefined; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with an invalid bid request identifier', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.bidderRequestId = {}; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit without impression identifier', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.bidId = undefined; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with an invalid impression identifier', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.bidId = {}; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit without media types', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes = undefined; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with empty media types', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes = {}; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with invalid media types', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes = 'bad_media_types'; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - }); - - describe('Banner', function () { - it('should return true when given a valid ad unit', function () { - const adUnit = examples.adUnit_banner; - - expect(spec.isBidRequestValid(adUnit)).to.equal(true); - }); - - it('should return true when given a valid ad unit with invalid publisher id', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.params = {}; - adUnit.params.publisherId = undefined; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return true when given a valid ad unit without placement id', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.params = {}; - adUnit.params.publisherId = 'agltb3B1Yi1pbmNyDAsSA0FwcBiJkfTUCV'; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return true when given a valid ad unit with invalid placement id', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.params = {}; - adUnit.params.publisherId = 'agltb3B1Yi1pbmNyDAsSA0FwcBiJkfTUCV'; - adUnit.params.placementId = undefined; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit without size', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes.banner.sizes = undefined; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with an invalid size', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes.banner.sizes = 'bad_banner_size'; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with an empty size', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes.banner.sizes = []; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with an invalid size value', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes.banner.sizes = ['bad_banner_size_value']; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with a size value with less than 2 dimensions', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes.banner.sizes = [[300]]; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with a size value with more than 2 dimensions', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes.banner.sizes = [[300, 250, 30]]; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with a negative width value', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes.banner.sizes = [[-300, 250]]; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with a negative height value', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes.banner.sizes = [[300, -250]]; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with an invalid width value', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes.banner.sizes = [[false, 250]]; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - - it('should return false when given an ad unit with an invalid height value', function () { - const adUnit = utils.deepClone(examples.adUnit_banner); - adUnit.mediaTypes.banner.sizes = [[300, {}]]; - - expect(spec.isBidRequestValid(adUnit)).to.equal(false); - }); - }); - }); - - describe('buildRequests', function () { - describe('ServerRequest', function () { - it('should return a server request when given a valid ad unit and a valid ad unit context', function () { - const adUnits = [examples.adUnit_banner]; - const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); - expect(serverRequests).to.be.an('array').and.to.have.length(1); - expect(serverRequests[0].method).to.exist.and.to.be.a('string').and.to.equal('POST'); - expect(serverRequests[0].url).to.exist.and.to.be.a('string').and.to.equal(BIDDER_URL); - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - }); - - it('should return an empty server request list when given an empty ad unit list and a valid ad unit context', function () { - const adUnits = []; - const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); - expect(serverRequests).to.be.an('array').and.to.have.length(0); - }); - - it('should not return a server request when given no ad unit and a valid ad unit context', function () { - const serverRequests = spec.buildRequests(null, examples.adUnitContext); - expect(serverRequests).to.equal(null); - }); - - it('should not return a server request when given a valid ad unit and no ad unit context', function () { - const adUnits = [examples.adUnit_banner]; - const serverRequests = spec.buildRequests(adUnits, null); - expect(serverRequests).to.be.an('array').and.to.have.length(1); - }); - - it('should not return a server request when given a valid ad unit and an invalid ad unit context', function () { - const adUnits = [examples.adUnit_banner]; - const serverRequests = spec.buildRequests(adUnits, {}); - expect(serverRequests).to.be.an('array').and.to.have.length(1); - }); - }); - - describe('BidRequest', function () { - it('should return a valid server request when given a valid ad unit', function () { - const adUnits = [examples.adUnit_banner]; - const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data.id).to.exist.and.to.be.a('string').and.to.equal(adUnits[0].bidderRequestId); - expect(serverRequests[0].data.at).to.exist.and.to.be.a('number').and.to.equal(1); - }); - - it('should return one server request when given one valid ad unit', function () { - const adUnits = [examples.adUnit_banner]; - const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data.id).to.exist.and.to.be.a('string').and.to.equal(adUnits[0].bidderRequestId); - }); - }); - - describe('Impression', function () { - describe('Banner', function () { - it('should return a server request with one impression when given a valid ad unit', function () { - const adUnits = [examples.adUnit_banner]; - - const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); - - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.imp).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data.imp[0]).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.imp[0].id).to.exist.and.to.be.a('string').and.to.equal(`${adUnits[0].bidId}`); - expect(serverRequests[0].data.imp[0].banner).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.imp[0].banner.w).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.banner.sizes[0][0]); - expect(serverRequests[0].data.imp[0].banner.h).to.exist.and.to.be.a('number').and.to.equal(adUnits[0].mediaTypes.banner.sizes[0][1]); - expect(serverRequests[0].data.imp[0].banner.format).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data.imp[0].banner.format[0]).to.exist.and.to.be.an('object').and.to.deep.equal({ - w: adUnits[0].mediaTypes.banner.sizes[0][0], - h: adUnits[0].mediaTypes.banner.sizes[0][1] - }); - }); - }); - }); - - describe('Site', function () { - it('should return a server request with site information when given a valid ad unit and a valid ad unit context', function () { - const adUnits = [examples.adUnit_banner]; - - const adUnitContext = examples.adUnitContext; - - const serverRequests = spec.buildRequests(adUnits, adUnitContext); - - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); - expect(serverRequests[0].data.site).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.site.page).to.exist.and.to.be.an('string').and.to.equal(adUnitContext.refererInfo.referer); - expect(serverRequests[0].data.site.domain).to.exist.and.to.be.an('string').and.to.equal('ventesavenues.in'); - expect(serverRequests[0].data.site.name).to.exist.and.to.be.an('string').and.to.equal('ventesavenues.in'); - }); - - it('should return a server request without site information when given an ad unit context without referer information', function () { - const adUnits = [examples.adUnit_banner]; - - const adUnitContext = utils.deepClone(examples.adUnitContext); - adUnitContext.refererInfo = undefined; - - const serverRequests = spec.buildRequests(adUnits, adUnitContext); - - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); - }); - - it('should return a server request without site information when given an ad unit context with invalid referer information', function () { - const adUnits = [examples.adUnit_banner]; - - const adUnitContext = utils.deepClone(examples.adUnitContext); - adUnitContext.refererInfo = 'bad_referer_information'; - - const serverRequests = spec.buildRequests(adUnits, adUnitContext); - - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); - }); - - it('should return a server request without site information when given an ad unit context without referer', function () { - const adUnits = [examples.adUnit_banner]; - - const adUnitContext = utils.deepClone(examples.adUnitContext); - adUnitContext.refererInfo.referer = undefined; - - const serverRequests = spec.buildRequests(adUnits, adUnitContext); - - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); - }); - - it('should return a server request without site information when given an ad unit context with an invalid referer', function () { - const adUnits = [examples.adUnit_banner]; - - const adUnitContext = utils.deepClone(examples.adUnitContext); - adUnitContext.refererInfo.referer = {}; - - const serverRequests = spec.buildRequests(adUnits, adUnitContext); - - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); - }); - - it('should return a server request without site information when given an ad unit context with a misformatted referer', function () { - const adUnits = [examples.adUnit_banner]; - - const adUnitContext = utils.deepClone(examples.adUnitContext); - adUnitContext.refererInfo.referer = 'we-are-adot'; - - const serverRequests = spec.buildRequests(adUnits, adUnitContext); - - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); - }); - }); - - describe('Device', function () { - it('should return a server request with device information when given a valid ad unit and a valid ad unit context', function () { - const adUnits = [examples.adUnit_banner]; - - const serverRequests = spec.buildRequests(adUnits, examples.adUnitContext); - - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); - expect(serverRequests[0].data.device).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.device.ua).to.exist.and.to.be.a('string'); - expect(serverRequests[0].data.device.language).to.exist.and.to.be.a('string'); - }); - }); - - describe('User', function () { - it('should return a server request with user information when given a valid ad unit and a valid ad unit context', function () { - const adUnits = [examples.adUnit_banner]; - - const adUnitContext = examples.adUnitContext; - - const serverRequests = spec.buildRequests(adUnits, adUnitContext); - - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); - expect(serverRequests[0].data.user).to.exist.and.to.be.an('object'); - }); - - it('should return a server request without user information when not given an ad unit context', function () { - const adUnits = [examples.adUnit_banner]; - - const adUnitContext = undefined; - - const serverRequests = spec.buildRequests(adUnits, adUnitContext); - - expect(serverRequests).to.be.an('array').and.to.have.lengthOf(1); - expect(serverRequests[0].data).to.exist.and.to.be.an('object'); - expect(serverRequests[0].data.id).to.exist.and.to.be.an('string').and.to.equal(adUnits[0].bidderRequestId); - }); - }); - }); - - describe('interpretResponse', function () { - describe('General', function () { - it('should return an ad when given a valid server response with one bid with USD currency', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.cur = 'USD'; - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(1); - expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); - expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); - expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); - expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); - expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); - expect(ads[0].height).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].h); - expect(ads[0].width).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].w); - expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('banner'); - }); - - it('should return no ad when not given a server response', function () { - const ads = spec.interpretResponse(null); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when not given a server response body', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body = undefined; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given an invalid server response body', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body = 'invalid_body'; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response without seat bids', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid = undefined; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with invalid seat bids', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid = 'invalid_seat_bids'; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with an empty seat bids array', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid = []; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with an invalid seat bid', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid = 'invalid_bids'; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with an empty bids array', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid = []; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with an invalid bid', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid = ['invalid_bid']; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid without currency', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.cur = undefined; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid with an invalid currency', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.cur = {}; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid without impression identifier', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].impid = undefined; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid with an invalid impression identifier', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].impid = {}; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid without creative identifier', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].crid = undefined; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid with an invalid creative identifier', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].crid = {}; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid without ad markup and ad serving URL', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].adm = undefined; - serverResponse.body.seatbid[0].bid[0].nurl = undefined; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid with an invalid ad markup', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].adm = {}; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid without bid price', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].price = undefined; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid with an invalid bid price', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].price = {}; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a valid server response and no server request', function () { - const serverRequest = undefined; - - const serverResponse = examples.serverResponse_banner; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a valid server response and an invalid server request', function () { - const serverRequest = 'bad_server_request'; - - const serverResponse = examples.serverResponse_banner; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a valid server response and a server request without bid request', function () { - const serverRequest = utils.deepClone(examples.serverRequest_banner); - serverRequest.data = undefined; - - const serverResponse = examples.serverResponse_banner; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a valid server response and a server request with an invalid bid request', function () { - const serverRequest = utils.deepClone(examples.serverRequest_banner); - serverRequest.data = 'bad_bid_request'; - - const serverResponse = examples.serverResponse_banner; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a valid server response and a server request without impression', function () { - const serverRequest = utils.deepClone(examples.serverRequest_banner); - serverRequest.data.imp = undefined; - - const serverResponse = examples.serverResponse_banner; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a valid server response and a server request with an invalid impression field', function () { - const serverRequest = utils.deepClone(examples.serverRequest_banner); - serverRequest.data.imp = 'invalid_impressions'; - - const serverResponse = examples.serverResponse_banner; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - }); - - describe('Banner', function () { - it('should return an ad when given a valid server response with one bid', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = examples.serverResponse_banner; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(1); - expect(ads[0].adUrl).to.equal(null); - expect(ads[0].creativeId).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.seatbid[0].bid[0].crid); - expect(ads[0].cpm).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].price); - expect(ads[0].currency).to.exist.and.to.be.a('string').and.to.equal(serverResponse.body.cur); - expect(ads[0].netRevenue).to.exist.and.to.be.a('boolean').and.to.equal(true); - expect(ads[0].ttl).to.exist.and.to.be.a('number').and.to.equal(10); - expect(ads[0].height).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].h); - expect(ads[0].width).to.exist.and.to.be.a('number').and.to.equal(serverResponse.body.seatbid[0].bid[0].w); - expect(ads[0].mediaType).to.exist.and.to.be.a('string').and.to.equal('banner'); - }); - - it('should return no ad when given a server response with a bid without height', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].h = undefined; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid with an invalid height', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].h = {}; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid without width', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].w = undefined; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - - it('should return no ad when given a server response with a bid with an invalid width', function () { - const serverRequest = examples.serverRequest_banner; - - const serverResponse = utils.deepClone(examples.serverResponse_banner); - serverResponse.body.seatbid[0].bid[0].w = {}; - - const ads = spec.interpretResponse(serverResponse, serverRequest); - - expect(ads).to.be.an('array').and.to.have.length(0); - }); - }); - }); -}); diff --git a/test/spec/modules/vibrantmediaBidAdapter_spec.js b/test/spec/modules/vibrantmediaBidAdapter_spec.js deleted file mode 100644 index c6ce7d52fb3..00000000000 --- a/test/spec/modules/vibrantmediaBidAdapter_spec.js +++ /dev/null @@ -1,1237 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/vibrantmediaBidAdapter.js'; -import {newBidder} from 'src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from 'src/mediaTypes.js'; -import {INSTREAM, OUTSTREAM} from 'src/video.js'; - -const EXPECTED_PREBID_SERVER_URL = 'https://prebid.intellitxt.com/prebid'; - -const BANNER_AD = - 'Test Banner Ad UnitHello!'; -const VIDEO_AD = 'Test Video Ad Unit' + - ''; - -const VALID_BANNER_BID_PARAMS = Object.freeze({ - member: '1234', - invCode: 'ABCD', - placementId: '10433394' -}); - -const VALID_VIDEO_BID_PARAMS = Object.freeze({ - member: '1234', - invCode: 'ABCD', - placementId: '10433394', - video: { - skippable: false, - playback_method: 'auto_play_sound_off' - } -}); - -const VALID_NATIVE_BID_PARAMS = VALID_BANNER_BID_PARAMS; - -const DEFAULT_BID_SIZES = [[300, 250], [600, 240]]; - -const VALID_CONSENT_STRING = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; - -const getValidBidderRequest = (bidRequests) => { - return Object.freeze({ - bidderCode: 'vibrantmedia', - auctionId: '1d1a030790a475', - bidderRequestId: '22edbae2733bf6', - timeout: 3000, - gdprConsent: { - consentString: VALID_CONSENT_STRING, - vendorData: {}, - gdprApplies: true, - }, - bids: bidRequests, - }); -}; - -describe('VibrantMediaBidAdapter', function () { - const adapter = newBidder(spec); - - describe('constants', function () { - expect(spec.code).to.equal('vibrantmedia'); - expect(spec.supportedMediaTypes).to.deep.equal([BANNER, NATIVE, VIDEO]); - }); - - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('transformBidParams', function () { - it('transforms bid params correctly', function () { - expect(spec.transformBidParams(VALID_VIDEO_BID_PARAMS)).to.deep.equal(VALID_VIDEO_BID_PARAMS); - }); - }) - - let bidRequest; - - beforeEach(function () { - bidRequest = { - bidder: 'vibrantmedia', - params: { - // Filled in by individual tests - }, - mediaTypes: { - // Filled in by individual tests - }, - adUnitCode: 'test-div', - transactionId: '13579acef87623', - placementId: '7623587623857', - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475' - }; - }); - - describe('isBidRequestValid', function () { - describe('with banner bid requests', function () { - beforeEach(function () { - bidRequest.mediaTypes.banner = { - sizes: DEFAULT_BID_SIZES, - }; - }); - - it('should return true for a valid banner bid request', function () { - bidRequest.params = VALID_BANNER_BID_PARAMS; - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return true for a valid banner bid request with a member id and inventory code', function () { - bidRequest.params = { - member: '1234', - invCode: 'ABCD', - }; - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return true for a valid banner bid request with a placement id', function () { - bidRequest.params = { - placementId: '10433394', - }; - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return false for a valid banner bid request but with a member id and no inventory code', function () { - bidRequest.params = { - member: '1234', - }; - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a valid banner bid request but with no member id and an inventory code', function () { - bidRequest.params = { - invCode: 'ABCD', - }; - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a valid banner bid request but with no supported media types', function () { - bidRequest.params = { - placementId: '10433394', - }; - delete bidRequest.mediaTypes.banner; - bidRequest.mediaTypes.unsupported = { - sizes: DEFAULT_BID_SIZES, - } - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a valid banner bid request but with no params', function () { - bidRequest.params = {}; - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - }); - - describe('with video bid requests', function () { - describe('with sizes attribute', function () { - const validVideoMediaTypes = { - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES, - minduration: 1, - maxduration: 60, - skip: 0, - skipafter: 5, - playbackmethod: [2], - protocols: [1, 2, 3] - }; - - it('should return true for a valid video bid request', function () { - bidRequest.params = VALID_VIDEO_BID_PARAMS; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return false for an instream video bid request', function () { - bidRequest.params = VALID_VIDEO_BID_PARAMS; - bidRequest.mediaTypes.video = { - context: INSTREAM, - sizes: DEFAULT_BID_SIZES, - }; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a video bid request with an unknown context', function () { - bidRequest.params = VALID_VIDEO_BID_PARAMS; - bidRequest.mediaTypes.video = { - context: 'fake', - sizes: DEFAULT_BID_SIZES, - }; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a video bid request with no context', function () { - bidRequest.params = VALID_VIDEO_BID_PARAMS; - bidRequest.mediaTypes.video = { - sizes: DEFAULT_BID_SIZES, - }; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return true for a valid video bid request with a member id and inventory code', function () { - bidRequest.params = { - member: '1234', - invCode: 'ABCD', - }; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return true for a valid video bid request with a placement id', function () { - bidRequest.params = { - placementId: '10433394', - }; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return false for a valid video bid request but with a member id and no inventory code', function () { - bidRequest.params = { - member: '1234', - }; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a valid video bid request but with no member id and an inventory code', function () { - bidRequest.params = { - invCode: 'ABCD', - }; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a valid video bid request but with no params', function () { - bidRequest.params = {}; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - }); - - describe('with playerSize attribute', function () { - const validVideoMediaTypes = { - context: OUTSTREAM, - playerSize: DEFAULT_BID_SIZES, - minduration: 1, - maxduration: 60, - skip: 0, - skipafter: 5, - playbackmethod: [2], - protocols: [1, 2, 3] - }; - - beforeEach(function () { - bidRequest.mediaTypes.video = { - // Filled in by individual tests - }; - }); - - it('should return true for a valid video bid request', function () { - bidRequest.params = VALID_VIDEO_BID_PARAMS; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return false for an instream video bid request', function () { - bidRequest.params = VALID_VIDEO_BID_PARAMS; - bidRequest.mediaTypes.video = { - context: INSTREAM, - playerSize: DEFAULT_BID_SIZES, - }; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a video bid request with an unknown context', function () { - bidRequest.params = VALID_VIDEO_BID_PARAMS; - bidRequest.mediaTypes.video = { - context: 'fake', - playerSize: DEFAULT_BID_SIZES, - }; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a video bid request with no context', function () { - bidRequest.params = VALID_VIDEO_BID_PARAMS; - bidRequest.mediaTypes.video = { - playerSize: DEFAULT_BID_SIZES, - }; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return true for a valid video bid request with a member id and inventory code', function () { - bidRequest.params = { - member: '1234', - invCode: 'ABCD', - }; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return true for a valid video bid request with a placement id', function () { - bidRequest.params = { - placementId: '10433394', - }; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return false for a valid video bid request but with a member id and no inventory code', function () { - bidRequest.params = { - member: '1234', - }; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a valid video bid request but with no member id and an inventory code', function () { - bidRequest.params = { - invCode: 'ABCD', - }; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a valid video bid request but with no params', function () { - bidRequest.params = {}; - bidRequest.mediaTypes.video = validVideoMediaTypes; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - }); - }); - - describe('with native bid requests', function () { - beforeEach(function () { - bidRequest.mediaTypes.native = { - image: { - required: true, - // Sizes is filled in by individual tests - }, - title: { - required: true - }, - sponsoredBy: { - required: true - }, - clickUrl: { - required: true - } - }; - }); - - it('should return true for a valid native bid request with a single size', function () { - bidRequest.params = VALID_NATIVE_BID_PARAMS; - bidRequest.mediaTypes.native.image.sizes = [300, 250]; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return true for a valid native bid request with multiple sizes', function () { - bidRequest.params = VALID_NATIVE_BID_PARAMS; - bidRequest.mediaTypes.native.image.sizes = [[300, 250], [300, 600]]; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return true for a valid native bid request with a member id and inventory code', function () { - bidRequest.params = { - member: '1234', - invCode: 'ABCD', - }; - bidRequest.mediaTypes.native.image.sizes = [300, 250]; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return true for a valid native bid request with a placement id', function () { - bidRequest.params = { - placementId: '10433394', - }; - bidRequest.mediaTypes.native.image.sizes = [300, 250]; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return false for a valid native bid request but with a member id and no inventory code', function () { - bidRequest.params = { - member: '1234', - }; - bidRequest.mediaTypes.native.image.sizes = [300, 250]; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a valid native bid request but with no member id and an inventory code', function () { - bidRequest.params = { - invCode: 'ABCD', - }; - bidRequest.mediaTypes.native.image.sizes = [300, 250]; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a valid native bid request but with no params', function () { - bidRequest.params = {}; - bidRequest.mediaTypes.native.image.sizes = [300, 250]; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - - it('should return false for a native bid request with no image property', function () { - bidRequest.params = VALID_NATIVE_BID_PARAMS; - delete bidRequest.mediaTypes.native.image; - - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - }); - }); - - describe('buildRequests', function () { - let bidRequests; - - beforeEach(function () { - bidRequests = [bidRequest]; - - bidRequests[0].params = VALID_BANNER_BID_PARAMS; - bidRequests[0].mediaTypes.banner = { - sizes: DEFAULT_BID_SIZES, - }; - }); - - it('should use HTTP POST', function () { - const request = spec.buildRequests(bidRequests, {}); - expect(request.method).to.equal('POST'); - }); - - it('should use the correct prebid server URL', function () { - const request = spec.buildRequests(bidRequests, {}); - expect(request.url).to.equal(EXPECTED_PREBID_SERVER_URL); - }); - - it('should add the page URL to the server request', function () { - const request = spec.buildRequests(bidRequests, {}); - const payload = JSON.parse(request.data); - - expect(payload.url).to.exist; - expect(payload.url).to.be.a('string'); - }); - - it('should add GDPR consent to the server request, where present', function () { - const bidderRequest = { - bidderCode: 'vibrantmedia', - auctionId: '1d1a030790a475', - bidderRequestId: '22edbae2733bf6', - timeout: 3000, - gdprConsent: { - consentString: VALID_CONSENT_STRING, - gdprApplies: true, - }, - bids: bidRequests, - }; - - const request = spec.buildRequests(bidRequests, bidderRequest); - // TODO: Check that we should not be implementing withCredentials - // expect(request.options).to.deep.equal({withCredentials: true}); - - const payload = JSON.parse(request.data); - expect(payload.gdpr).to.exist; - expect(payload.gdpr.consentString).to.exist.and.to.equal(VALID_CONSENT_STRING); - expect(payload.gdpr.gdprApplies).to.exist.and.to.be.true; - }); - - it('should add USP consent to the server request, where present', function () { - const bidderRequest = { - bidderCode: 'vibrantmedia', - auctionId: '1d1a030790a475', - bidderRequestId: '22edbae2733bf6', - timeout: 3000, - uspConsent: { - cmpApi: 'iab', - timeout: 10000, - consentData: { - testDatum: true - } - }, - bids: bidRequests - }; - - const request = spec.buildRequests(bidRequests, bidderRequest); - // TODO: Check that we should not be implementing withCredentials - // expect(request.options).to.deep.equal({withCredentials: true}); - - const payload = JSON.parse(request.data); - expect(payload.usp).to.exist; - expect(payload.usp.cmpApi).to.exist.and.to.equal('iab'); - expect(payload.usp.timeout).to.exist.and.to.equal(10000); - expect(payload.usp.consentData).to.exist.and.to.deep.equal({ - testDatum: true - }); - }); - - it('should add GDPR and USP consent to the server request, where both present', function () { - const bidderRequest = { - bidderCode: 'vibrantmedia', - auctionId: '1d1a030790a475', - bidderRequestId: '22edbae2733bf6', - timeout: 3000, - gdprConsent: { - consentString: VALID_CONSENT_STRING, - gdprApplies: true, - }, - uspConsent: { - cmpApi: 'iab', - timeout: 10000, - consentData: { - testDatum: true - } - }, - bids: bidRequests, - }; - - const request = spec.buildRequests(bidRequests, bidderRequest); - // TODO: Check that we should not be implementing withCredentials - // expect(request.options).to.deep.equal({withCredentials: true}); - - const payload = JSON.parse(request.data); - - expect(payload.gdpr).to.exist; - expect(payload.gdpr.consentString).to.exist.and.to.equal(VALID_CONSENT_STRING); - expect(payload.gdpr.gdprApplies).to.exist.and.to.be.true; - - expect(payload.usp).to.exist; - expect(payload.usp.cmpApi).to.exist.and.to.equal('iab'); - expect(payload.usp.timeout).to.exist.and.to.equal(10000); - expect(payload.usp.consentData).to.exist.and.to.deep.equal({ - testDatum: true - }); - }); - - it('should add window dimensions to the server request', function () { - const request = spec.buildRequests(bidRequests, {}); - const payload = JSON.parse(request.data); - - expect(payload.window).to.exist; - expect(payload.window.width).to.equal(window.innerWidth); - expect(payload.window.height).to.equal(window.innerHeight); - }); - - it('should add the top-level sizes to the bid request, if present', function () { - bidRequest.params = VALID_BANNER_BID_PARAMS; - bidRequest.sizes = DEFAULT_BID_SIZES; - bidRequest.mediaTypes = { - banner: {}, - }; - - const request = spec.buildRequests(bidRequests, {}, true); - const payload = JSON.parse(request.data); - - expect(payload.biddata).to.exist; - expect(payload.biddata.length).to.equal(1); - expect(payload.biddata[0]).to.exist; - expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode); - expect(payload.biddata[0].id).to.equal(bidRequest.placementId); - expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder); - expect(payload.biddata[0].sizes).to.deep.equal(DEFAULT_BID_SIZES); - expect(payload.biddata[0].mediaTypes).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({}); - }); - - it('should add the list of bids to the bid request, if present', function () { - const testBid = { - bidder: 'testBidder', - params: { - placement: '12345' - } - }; - - bidRequest.params = VALID_BANNER_BID_PARAMS; - bidRequest.bids = [testBid]; - bidRequest.mediaTypes = { - banner: {}, - }; - - // These will be present in the list of bids instead - delete bidRequest.bidId; - delete bidRequest.transactionId; - delete bidRequest.bidder; - - const request = spec.buildRequests(bidRequests, {}, true); - const payload = JSON.parse(request.data); - - expect(payload.biddata).to.exist; - expect(payload.biddata.length).to.equal(1); - expect(payload.biddata[0]).to.exist; - expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode); - expect(payload.biddata[0].id).to.equal(bidRequest.placementId); - expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder); - expect(payload.biddata[0].bids.length).to.equal(1); - expect(payload.biddata[0].bids[0]).to.deep.equal(testBid); - expect(payload.biddata[0].mediaTypes).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({}); - }); - - it('should add the correct bid data to the server request for one bid request', function () { - bidRequest.params = VALID_BANNER_BID_PARAMS; - bidRequest.mediaTypes = { - banner: { - sizes: DEFAULT_BID_SIZES, - }, - }; - - const request = spec.buildRequests(bidRequests, {}, true); - const payload = JSON.parse(request.data); - - expect(payload.biddata).to.exist; - expect(payload.biddata.length).to.equal(1); - expect(payload.biddata[0]).to.exist; - expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode); - expect(payload.biddata[0].id).to.equal(bidRequest.placementId); - expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder); - expect(payload.biddata[0].sizes).to.be.undefined; - expect(payload.biddata[0].mediaTypes).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({ - sizes: DEFAULT_BID_SIZES, - }); - }); - - it('should add the correct bid data to the server request for multiple bid requests', function () { - bidRequest.params = VALID_BANNER_BID_PARAMS; - bidRequest.mediaTypes = { - banner: { - sizes: DEFAULT_BID_SIZES, - }, - }; - const bid2 = { - bidder: 'vibrantmedia', - params: VALID_VIDEO_BID_PARAMS, - mediaTypes: { - video: { - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES, - } - }, - adUnitCode: 'video-div', - bidId: '30b31c1838de1f', - placementId: '135797531abcdef', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - }; - const bid3 = { - bidder: 'vibrantmedia', - params: VALID_NATIVE_BID_PARAMS, - mediaTypes: { - native: { - image: { - required: true, - sizes: [300, 250] - }, - title: { - required: true - }, - sponsoredBy: { - required: true - }, - clickUrl: { - required: true - } - } - }, - adUnitCode: 'native-div', - bidId: '30b31c1838de14', - placementId: '918273645abcdef', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - }; - - bidRequests.push(bid2, bid3); - - const request = spec.buildRequests(bidRequests, {}, true); - const payload = JSON.parse(request.data); - - expect(payload.biddata).to.exist; - expect(payload.biddata.length).to.equal(3); - expect(payload.biddata[0]).to.exist; - expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode); - expect(payload.biddata[0].id).to.equal(bidRequest.placementId); - expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder); - expect(payload.biddata[0].mediaTypes).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({ - sizes: DEFAULT_BID_SIZES, - }); - expect(payload.biddata[1]).to.exist; - expect(payload.biddata[1].code).to.equal(bid2.adUnitCode); - expect(payload.biddata[1].id).to.equal(bid2.placementId); - expect(payload.biddata[1].bidder).to.equal(bid2.bidder); - expect(payload.biddata[1].mediaTypes).to.exist; - expect(payload.biddata[1].mediaTypes[VIDEO]).to.exist; - expect(payload.biddata[1].mediaTypes[VIDEO]).to.deep.equal({ - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES, - }); - expect(payload.biddata[2]).to.exist; - expect(payload.biddata[2].code).to.equal(bid3.adUnitCode); - expect(payload.biddata[2].id).to.equal(bid3.placementId); - expect(payload.biddata[2].bidder).to.equal(bid3.bidder); - expect(payload.biddata[2].mediaTypes[NATIVE]).to.exist; - expect(payload.biddata[2].mediaTypes[NATIVE]).to.deep.equal(bid3.mediaTypes.native); - }); - - it('should add the correct bid data to the bid request where a bid has multiple media types', function () { - bidRequest.params = VALID_VIDEO_BID_PARAMS; - bidRequest.mediaTypes = { - banner: { - sizes: DEFAULT_BID_SIZES, - }, - video: { - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES, - }, - native: { - image: { - required: true, - sizes: [300, 250] - }, - title: { - required: true - }, - sponsoredBy: { - required: true - }, - clickUrl: { - required: true - } - } - }; - bidRequest.adUnitCode = 'mixed-div'; - - const bid2 = { - bidder: 'vibrantmedia', - params: VALID_VIDEO_BID_PARAMS, - mediaTypes: { - video: { - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES, - } - }, - adUnitCode: 'video-div', - bidId: '30b31c1838de1a', - bidderRequestId: '22edbae2733bf6', - placementId: '293857832abfef', - auctionId: '1d1a030790a475', - }; - - bidRequests.push(bid2); - - const request = spec.buildRequests(bidRequests, {}, true); - const payload = JSON.parse(request.data); - - expect(payload.biddata).to.exist; - expect(payload.biddata.length).to.equal(2); - expect(payload.biddata[0]).to.exist; - expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode); - expect(payload.biddata[0].id).to.equal(bidRequest.placementId); - expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder); - expect(payload.biddata[0].mediaTypes).to.exist; - expect(Object.keys(payload.biddata[0].mediaTypes).length).to.equal(3); - expect(payload.biddata[0].mediaTypes[BANNER]).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({ - sizes: DEFAULT_BID_SIZES, - }); - expect(payload.biddata[0].mediaTypes[VIDEO]).to.exist; - expect(payload.biddata[0].mediaTypes[VIDEO]).to.deep.equal({ - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES, - }); - expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode); - expect(payload.biddata[0].id).to.equal(bidRequest.placementId); - expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder); - expect(payload.biddata[0].mediaTypes[NATIVE]).to.exist; - expect(payload.biddata[0].mediaTypes[NATIVE]).to.deep.equal(bidRequest.mediaTypes.native); - expect(payload.biddata[1]).to.exist; - expect(payload.biddata[1].code).to.equal(bid2.adUnitCode); - expect(payload.biddata[1].id).to.equal(bid2.placementId); - expect(payload.biddata[1].bidder).to.equal(bid2.bidder); - expect(payload.biddata[1].mediaTypes).to.exist; - expect(Object.keys(payload.biddata[1].mediaTypes).length).to.equal(1); - expect(payload.biddata[1].mediaTypes[VIDEO]).to.exist; - expect(payload.biddata[1].mediaTypes[VIDEO]).to.deep.equal({ - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES, - }); - }); - }); - - describe('interpretResponse', function () { - it('returns a valid Prebid API response object for a banner Prebid Server response', function () { - const prebidServerResponse = { - body: [{ - mediaType: 'banner', - requestId: '12345', - cpm: 1, - currency: 'USD', - width: 640, - height: 240, - ad: BANNER_AD, - ttl: 300, - creativeId: '86f4aef9-2f17-421d-84db-5c9814bf4a79', - netRevenue: false, - meta: Object.freeze({ - advertiser: '105600', - width: 300, - height: 250, - isCustom: '1', - progressBar: false, - mpuSrc: '//images.intellitxt.com/a/105600/Genpact/genpact.jpg', - clickURL: '{{click}}' - }) - }] - }; - - const interpretedResponse = spec.interpretResponse(prebidServerResponse, {}); - - expect(interpretedResponse).to.be.a('array'); - expect(interpretedResponse.length).to.equal(1); - - const interpretedBid = interpretedResponse[0]; - - expect(interpretedBid.mediaType).to.equal('banner'); - expect(interpretedBid.requestId).to.equal('12345'); - expect(interpretedBid.cpm).to.equal(1); - expect(interpretedBid.currency).to.equal('USD'); - expect(interpretedBid.width).to.equal(640); - expect(interpretedBid.height).to.equal(240); - expect(interpretedBid.ad).to.equal(BANNER_AD); - expect(interpretedBid.ttl).to.equal(300); - expect(interpretedBid.creativeId).to.equal('86f4aef9-2f17-421d-84db-5c9814bf4a79'); - expect(interpretedBid.netRevenue).to.be.false; - expect(interpretedBid.meta).to.deep.equal(prebidServerResponse.body[0].meta); - expect(interpretedBid.renderer).to.be.undefined; - expect(interpretedBid.adResponse).to.deep.equal(prebidServerResponse); - }); - - it('returns a valid Prebid API response object for a video Prebid Server response', function () { - const prebidServerResponse = Object.freeze({ - body: [{ - mediaType: 'video', - requestId: '67890', - cpm: 2, - currency: 'USD', - width: 600, - height: 300, - ad: VIDEO_AD, - ttl: 300, - creativeId: '248e8e0c-2f17-421d-84db-5c9814bf4a79', - netRevenue: false, - meta: { - advertiser: '105600', - width: 300, - height: 250, - isCustom: '1', - progressBar: false, - mpuSrc: '//images.intellitxt.com/a/105600/Genpact/genpact.jpg', - clickURL: '{{click}}' - }, - vastUrl: 'https://www.example.com/myVastVideo' - }] - }); - - const interpretedResponse = spec.interpretResponse(prebidServerResponse, {}); - - expect(interpretedResponse).to.be.a('array'); - expect(interpretedResponse.length).to.equal(1); - - const interpretedBid = interpretedResponse[0]; - - expect(interpretedBid.mediaType).to.equal('video'); - expect(interpretedBid.requestId).to.equal('67890'); - expect(interpretedBid.cpm).to.equal(2); - expect(interpretedBid.currency).to.equal('USD'); - expect(interpretedBid.width).to.equal(600); - expect(interpretedBid.height).to.equal(300); - expect(interpretedBid.ad).to.equal(VIDEO_AD); - expect(interpretedBid.ttl).to.equal(300); - expect(interpretedBid.creativeId).to.equal('248e8e0c-2f17-421d-84db-5c9814bf4a79'); - expect(interpretedBid.netRevenue).to.be.false; - expect(interpretedBid.meta).to.deep.equal(prebidServerResponse.body[0].meta); - expect(interpretedBid.renderer).to.be.undefined; - expect(interpretedBid.adResponse).to.deep.equal(prebidServerResponse); - }); - - it('returns a valid Prebid API response object for a native Prebid Server response', function () { - const prebidServerResponse = Object.freeze({ - body: [{ - mediaType: 'native', - requestId: '13579', - cpm: 3, - currency: 'USD', - width: 240, - height: 300, - ad: 'https://www.example.com/native-display.html', - ttl: 300, - creativeId: 'd28e8e0c-2f17-421d-84db-5c9814bf4a81', - netRevenue: false, - meta: {}, - title: 'Test native ad bid for 13579', - sponsoredBy: 'Vibrant Media Ltd', - clickUrl: 'https://www.example.com/native-ct.html', - image: { - url: 'https://www.example.com/native-display.html', - width: 240, - height: 300 - } - }] - }); - - const interpretedResponse = spec.interpretResponse(prebidServerResponse, {}); - - expect(interpretedResponse).to.be.a('array'); - expect(interpretedResponse.length).to.equal(1); - - const interpretedBid = interpretedResponse[0]; - - expect(interpretedBid.mediaType).to.equal('native'); - expect(interpretedBid.requestId).to.equal('13579'); - expect(interpretedBid.cpm).to.equal(3); - expect(interpretedBid.currency).to.equal('USD'); - expect(interpretedBid.width).to.equal(240); - expect(interpretedBid.height).to.equal(300); - expect(interpretedBid.ad).to.equal('https://www.example.com/native-display.html'); - expect(interpretedBid.ttl).to.equal(300); - expect(interpretedBid.creativeId).to.equal('d28e8e0c-2f17-421d-84db-5c9814bf4a81'); - expect(interpretedBid.netRevenue).to.be.false; - expect(interpretedBid.meta).to.deep.equal(prebidServerResponse.body[0].meta); - expect(interpretedBid.renderer).to.be.undefined; - expect(interpretedBid.adResponse).to.deep.equal(prebidServerResponse); - }); - - it('returns a valid Prebid API response object for a multi-bid Prebid Server response', function () { - const prebidServerResponse = Object.freeze({ - body: [ - { - mediaType: 'banner', - requestId: '12345', - cpm: 3, - currency: 'USD', - width: 640, - height: 240, - ad: BANNER_AD, - ttl: 300, - creativeId: '86f4aef9-2f17-421d-84db-5c9814bf4a79', - netRevenue: false, - meta: { - advertiser: '105600', - width: 300, - height: 250, - isCustom: '1', - progressBar: false, - mpuSrc: '//images.intellitxt.com/a/105600/Genpact/genpact.jpg', - clickURL: '{{click}}' - } - }, - { - mediaType: 'video', - requestId: '67890', - cpm: 4, - currency: 'USD', - width: 300, - height: 300, - ad: VIDEO_AD, - ttl: 300, - creativeId: 'd28e8e0c-2f17-421d-84db-5c9814bf4a79', - netRevenue: false, - meta: { - advertiser: '105600', - width: 300, - height: 250, - isCustom: '1', - progressBar: false, - mpuSrc: '//images.intellitxt.com/a/105600/Genpact/genpact.jpg', - clickURL: '{{click}}' - }, - vastUrl: 'https://www.example.com/myVastVideo' - }, - { - mediaType: 'native', - requestId: '13579', - cpm: 5, - currency: 'USD', - width: 640, - height: 240, - ad: 'https://www.example.com/native-display.html', - ttl: 300, - creativeId: '888e8e0c-2f17-421d-84db-5c9814bf4a81', - netRevenue: false, - meta: {}, - title: 'Test native ad bid for 13579', - sponsoredBy: 'Vibrant Media Ltd', - clickUrl: 'https://www.example.com/native-ct.html', - image: { - url: 'https://www.example.com/native-display.html', - width: 640, - height: 240 - } - } - ] - }); - - const interpretedResponse = spec.interpretResponse(prebidServerResponse, {}); - - expect(interpretedResponse).to.be.a('array'); - expect(interpretedResponse.length).to.equal(3); - - const interpretedBannerBid = interpretedResponse[0]; - - expect(interpretedBannerBid.mediaType).to.equal('banner'); - expect(interpretedBannerBid.requestId).to.equal('12345'); - expect(interpretedBannerBid.cpm).to.equal(3); - expect(interpretedBannerBid.currency).to.equal('USD'); - expect(interpretedBannerBid.width).to.equal(640); - expect(interpretedBannerBid.height).to.equal(240); - expect(interpretedBannerBid.ad).to.equal(BANNER_AD); - expect(interpretedBannerBid.ttl).to.equal(300); - expect(interpretedBannerBid.creativeId).to.equal('86f4aef9-2f17-421d-84db-5c9814bf4a79'); - expect(interpretedBannerBid.netRevenue).to.be.false; - expect(interpretedBannerBid.meta).to.deep.equal(prebidServerResponse.body[0].meta); - expect(interpretedBannerBid.renderer).to.be.undefined; - expect(interpretedBannerBid.adResponse).to.deep.equal(prebidServerResponse); - - const interpretedVideoBid = interpretedResponse[1]; - - expect(interpretedVideoBid.mediaType).to.equal('video'); - expect(interpretedVideoBid.requestId).to.equal('67890'); - expect(interpretedVideoBid.cpm).to.equal(4); - expect(interpretedVideoBid.currency).to.equal('USD'); - expect(interpretedVideoBid.width).to.equal(300); - expect(interpretedVideoBid.height).to.equal(300); - expect(interpretedVideoBid.ad).to.equal(VIDEO_AD); - expect(interpretedVideoBid.ttl).to.equal(300); - expect(interpretedVideoBid.creativeId).to.equal('d28e8e0c-2f17-421d-84db-5c9814bf4a79'); - expect(interpretedVideoBid.netRevenue).to.be.false; - expect(interpretedVideoBid.meta).to.deep.equal(prebidServerResponse.body[1].meta); - expect(interpretedVideoBid.renderer).to.be.undefined; - expect(interpretedVideoBid.adResponse).to.deep.equal(prebidServerResponse); - - const interpretedNativeBid = interpretedResponse[2]; - - expect(interpretedNativeBid.mediaType).to.equal('native'); - expect(interpretedNativeBid.requestId).to.equal('13579'); - expect(interpretedNativeBid.cpm).to.equal(5); - expect(interpretedNativeBid.currency).to.equal('USD'); - expect(interpretedNativeBid.width).to.equal(640); - expect(interpretedNativeBid.height).to.equal(240); - expect(interpretedNativeBid.ad).to.equal('https://www.example.com/native-display.html'); - expect(interpretedNativeBid.ttl).to.equal(300); - expect(interpretedNativeBid.creativeId).to.equal('888e8e0c-2f17-421d-84db-5c9814bf4a81'); - expect(interpretedNativeBid.netRevenue).to.be.false; - expect(interpretedNativeBid.meta).to.deep.equal(prebidServerResponse.body[2].meta); - expect(interpretedNativeBid.renderer).to.be.undefined; - expect(interpretedNativeBid.adResponse).to.deep.equal(prebidServerResponse); - }); - }); - - describe('Flow tests', function () { - describe('For successive API calls to the public functions', function () { - it('should succeed with one media type per bid', function () { - const transformedBannerBidParams = spec.transformBidParams(VALID_BANNER_BID_PARAMS); - const transformedVideoBidParams = spec.transformBidParams(VALID_VIDEO_BID_PARAMS); - const transformedNativeBidParams = spec.transformBidParams(VALID_NATIVE_BID_PARAMS); - - const bannerBid = { - bidder: 'vibrantmedia', - params: transformedBannerBidParams, - mediaTypes: { - banner: { - sizes: DEFAULT_BID_SIZES, - }, - }, - adUnitCode: 'banner-div', - bidId: '30b31c1838de11', - bidderRequestId: '22edbae2733bf6', - placementId: '293857832abfef', - auctionId: '1d1a030790a475', - }; - const videoBid = { - bidder: 'vibrantmedia', - params: transformedVideoBidParams, - mediaTypes: { - video: { - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES, - }, - }, - adUnitCode: 'video-div', - bidId: '30b31c1838de15', - bidderRequestId: '22edbae2733bf6', - placementId: '293857832abfef', - auctionId: '1d1a030790a475', - }; - const nativeBid = { - bidder: 'vibrantmedia', - params: transformedNativeBidParams, - mediaTypes: { - native: { - image: { - required: true, - sizes: [300, 250] - }, - title: { - required: true - }, - sponsoredBy: { - required: true - }, - clickUrl: { - required: true - } - } - }, - adUnitCode: 'native-div', - bidId: '30b31c1838de12', - bidderRequestId: '22edbae2733bf6', - placementId: '293857832abfef', - auctionId: '1d1a030790a475', - }; - - expect(spec.isBidRequestValid(bannerBid)).to.be.true; - expect(spec.isBidRequestValid(videoBid)).to.be.true; - expect(spec.isBidRequestValid(nativeBid)).to.be.true; - - const bidRequests = [bannerBid, videoBid, nativeBid]; - const validBidderRequest = getValidBidderRequest(bidRequests); - const serverRequest = spec.buildRequests(bidRequests, validBidderRequest); - expect(serverRequest.method).to.equal('POST'); - expect(serverRequest.url).to.equal(EXPECTED_PREBID_SERVER_URL); - - const payload = JSON.parse(serverRequest.data); - expect(payload.biddata).to.exist; - expect(payload.biddata.length).to.equal(3); - expect(payload.biddata[0]).to.exist; - expect(payload.biddata[0].code).to.equal(bannerBid.adUnitCode); - expect(payload.biddata[0].id).to.equal(bannerBid.placementId); - expect(payload.biddata[0].bidder).to.equal(bannerBid.bidder); - expect(payload.biddata[0].mediaTypes[BANNER]).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({ - sizes: DEFAULT_BID_SIZES, - }); - expect(payload.biddata[1]).to.exist; - expect(payload.biddata[1].code).to.equal(videoBid.adUnitCode); - expect(payload.biddata[1].id).to.equal(videoBid.placementId); - expect(payload.biddata[1].bidder).to.equal(videoBid.bidder); - expect(payload.biddata[1].mediaTypes[VIDEO]).to.exist; - expect(payload.biddata[1].mediaTypes[VIDEO]).to.deep.equal({ - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES - }); - expect(payload.biddata[2]).to.exist; - expect(payload.biddata[2].code).to.equal(nativeBid.adUnitCode); - expect(payload.biddata[2].id).to.equal(nativeBid.placementId); - expect(payload.biddata[2].bidder).to.equal(nativeBid.bidder); - expect(payload.biddata[2].mediaTypes[NATIVE]).to.exist; - expect(payload.biddata[2].mediaTypes[NATIVE]).to.deep.equal(nativeBid.mediaTypes.native); - - // From here, the API would call the Prebid Server and call interpretResponse, which is covered by tests elsewhere - }); - - it('should succeed with multiple media types for a single bid', function () { - const bidParams = spec.transformBidParams(VALID_VIDEO_BID_PARAMS); - const bid = { - bidder: 'vibrantmedia', - params: bidParams, - mediaTypes: { - banner: { - sizes: DEFAULT_BID_SIZES - }, - video: { - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES - }, - native: { - sizes: DEFAULT_BID_SIZES - } - }, - adUnitCode: 'test-div', - bidId: '30b31c1838de13', - bidderRequestId: '22edbae2733bf6', - placementId: '293857832abfef', - auctionId: '1d1a030790a475', - }; - - expect(spec.isBidRequestValid(bid)).to.be.true; - - const bidRequests = [bid]; - const validBidderRequest = getValidBidderRequest(bidRequests); - const serverRequest = spec.buildRequests(bidRequests, validBidderRequest); - expect(serverRequest.method).to.equal('POST'); - expect(serverRequest.url).to.equal(EXPECTED_PREBID_SERVER_URL); - - const payload = JSON.parse(serverRequest.data); - expect(payload.biddata).to.exist; - expect(payload.biddata.length).to.equal(1); - expect(payload.biddata[0]).to.exist; - expect(payload.biddata[0].code).to.equal(bid.adUnitCode); - expect(payload.biddata[0].id).to.equal(bid.placementId); - expect(payload.biddata[0].bidder).to.equal(bid.bidder); - expect(payload.biddata[0].mediaTypes[BANNER]).to.exist; - expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({ - sizes: DEFAULT_BID_SIZES, - }); - expect(payload.biddata[0].mediaTypes[VIDEO]).to.exist; - expect(payload.biddata[0].mediaTypes[VIDEO]).to.deep.equal({ - context: OUTSTREAM, - sizes: DEFAULT_BID_SIZES, - }); - expect(payload.biddata[0].mediaTypes[NATIVE]).to.exist; - expect(payload.biddata[0].mediaTypes[NATIVE]).to.deep.equal({ - sizes: DEFAULT_BID_SIZES, - }); - - // From here, the API would call the Prebid Server and call interpretResponse, which is covered by tests elsewhere - }); - }); - }); -}); diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js index 0b5dadce09f..35f510fd6ee 100644 --- a/test/spec/modules/vidazooBidAdapter_spec.js +++ b/test/spec/modules/vidazooBidAdapter_spec.js @@ -37,8 +37,7 @@ const BID = { 'transactionId': 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf', 'sizes': [[300, 250], [300, 600]], 'bidderRequestId': '1fdb5ff1b6eaa7', - 'requestId': 'b0777d85-d061-450e-9bc7-260dd54bbb7a', - 'schain': 'a0819c69-005b-41ed-af06-1be1e0aefefc' + 'requestId': 'b0777d85-d061-450e-9bc7-260dd54bbb7a' }; const BIDDER_REQUEST = { @@ -164,7 +163,6 @@ describe('VidazooBidAdapter', function () { uniqueDealId: `${hashUrl}_${Date.now().toString()}`, bidderVersion: adapter.version, prebidVersion: version, - schain: BID.schain, res: `${window.top.screen.width}x${window.top.screen.height}`, 'ext.param1': 'loremipsum', 'ext.param2': 'dolorsitamet', diff --git a/test/spec/modules/videobyteBidAdapter_spec.js b/test/spec/modules/videobyteBidAdapter_spec.js index f7ea0698956..b8e41829031 100644 --- a/test/spec/modules/videobyteBidAdapter_spec.js +++ b/test/spec/modules/videobyteBidAdapter_spec.js @@ -153,7 +153,7 @@ describe('VideoByteBidAdapter', function () { it('should create a POST request for every bid', function () { const requests = spec.buildRequests([bidRequest], bidderRequest); expect(requests[0].method).to.equal('POST'); - expect(requests[0].url).to.equal(spec.ENDPOINT + '?pid=' + bidRequest.params.pubId); + expect(requests[0].url).to.equal(spec.ENDPOINT + bidRequest.params.pubId); }); it('should attach request data', function () { @@ -172,7 +172,7 @@ describe('VideoByteBidAdapter', function () { bidRequest.params.video.e2etest = true; const requests = spec.buildRequests([bidRequest], bidderRequest); expect(requests[0].method).to.equal('POST'); - expect(requests[0].url).to.equal(spec.ENDPOINT + '?pid=e2etest'); + expect(requests[0].url).to.equal(spec.ENDPOINT + 'e2etest'); }); it('should attach End 2 End test data', function () { diff --git a/test/spec/modules/vidoomyBidAdapter_spec.js b/test/spec/modules/vidoomyBidAdapter_spec.js index 8aa127faef2..37452914e79 100644 --- a/test/spec/modules/vidoomyBidAdapter_spec.js +++ b/test/spec/modules/vidoomyBidAdapter_spec.js @@ -4,7 +4,6 @@ import { newBidder } from 'src/adapters/bidderFactory.js'; import { INSTREAM } from '../../../src/video'; const ENDPOINT = `https://d.vidoomy.com/api/rtbserver/prebid/`; -const PIXELS = ['/test.png', '/test2.png?gdpr={{GDPR}}&gdpr_consent={{GDPR_CONSENT}}'] describe('vidoomyBidAdapter', function() { const adapter = newBidder(spec); @@ -16,8 +15,7 @@ describe('vidoomyBidAdapter', function() { 'bidder': 'vidoomy', 'params': { pid: '123123', - id: '123123', - bidfloor: 0.5 + id: '123123' }, 'adUnitCode': 'code', 'sizes': [[300, 250]] @@ -33,11 +31,6 @@ describe('vidoomyBidAdapter', function() { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when bidfloor is invalid', function () { - bid.params.bidfloor = 'not a number'; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - it('should return false when id is empty', function () { bid.params.id = ''; expect(spec.isBidRequestValid(bid)).to.equal(false); @@ -108,24 +101,24 @@ describe('vidoomyBidAdapter', function() { }); it('attaches source and version to endpoint URL as query params', function () { - expect(request[0].url).to.equal(ENDPOINT); - expect(request[1].url).to.equal(ENDPOINT); + expect(request[0].url).to.include(ENDPOINT); + expect(request[1].url).to.include(ENDPOINT); }); it('only accepts first width and height sizes', function () { - expect('' + request[0].data.w).to.equal('300'); - expect('' + request[0].data.h).to.equal('250'); - expect('' + request[0].data.w).to.not.equal('200'); - expect('' + request[0].data.h).to.not.equal('100'); - expect('' + request[1].data.w).to.equal('400'); - expect('' + request[1].data.h).to.equal('225'); + expect(request[0].url).to.include('w=300'); + expect(request[0].url).to.include('h=250'); + expect(request[0].url).to.not.include('w=200'); + expect(request[0].url).to.not.include('h=100'); + expect(request[1].url).to.include('w=400'); + expect(request[1].url).to.include('h=225'); }); it('should send id and pid parameters', function () { - expect('' + request[0].data.id).to.equal('123123'); - expect('' + request[0].data.pid).to.equal('123123'); - expect('' + request[1].data.id).to.equal('456456'); - expect('' + request[1].data.pid).to.equal('456456'); + expect(request[0].url).to.include('id=123123'); + expect(request[0].url).to.include('pid=123123'); + expect(request[1].url).to.include('id=456456'); + expect(request[1].url).to.include('pid=456456'); }); }); @@ -189,8 +182,7 @@ describe('vidoomyBidAdapter', function() { 'networkName': null, 'primaryCatId': 'IAB3-1', 'secondaryCatIds': null - }, - 'pixels': PIXELS + } } } @@ -214,22 +206,5 @@ describe('vidoomyBidAdapter', function() { expect(result[0].requestId).to.equal(serverResponseBanner.body.requestId); }); - - it('should sync user cookies', function () { - const GDPR_CONSENT = 'GDPR_TEST' - const result = spec.getUserSyncs({ - pixelEnabled: true - }, [serverResponseBanner], { consentString: GDPR_CONSENT, gdprApplies: 1 }, null) - expect(result).to.eql([ - { - type: 'image', - url: PIXELS[0] - }, - { - type: 'image', - url: `/test2.png?gdpr=1&gdpr_consent=${GDPR_CONSENT}` - } - ]) - }); }); }); diff --git a/test/spec/modules/viewability_spec.js b/test/spec/modules/viewability_spec.js deleted file mode 100644 index ab2753daf53..00000000000 --- a/test/spec/modules/viewability_spec.js +++ /dev/null @@ -1,280 +0,0 @@ -import { expect } from 'chai'; -import * as sinon from 'sinon'; -import * as utils from 'src/utils.js'; -import * as viewability from 'modules/viewability.js'; - -describe('viewability test', () => { - describe('start measurement', () => { - let sandbox; - let intersectionObserverStub; - let setTimeoutStub; - let observeCalled; - let unobserveCalled; - let ti = 1; - beforeEach(() => { - observeCalled = false; - unobserveCalled = false; - sandbox = sinon.sandbox.create(); - - let fakeIntersectionObserver = (stateChange, options) => { - return { - observe: (element) => { - observeCalled = true; - stateChange([{ isIntersecting: true }]); - }, - unobserve: (element) => { - unobserveCalled = true; - }, - }; - }; - - intersectionObserverStub = sandbox.stub(window, 'IntersectionObserver').callsFake(fakeIntersectionObserver); - setTimeoutStub = sandbox.stub(window, 'setTimeout').callsFake((callback, timeout) => { - callback(); - return ti++; - }); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('should trigger appropriate callbacks', () => { - viewability.startMeasurement('0', {}, { method: 'img', value: 'http://my.tracker/123' }, { inViewThreshold: 0.5, timeInView: 1000 }); - - sinon.assert.called(intersectionObserverStub); - sinon.assert.called(setTimeoutStub); - expect(observeCalled).to.equal(true); - expect(unobserveCalled).to.equal(true); - }); - - it('should trigger img tracker', () => { - let triggerPixelSpy = sandbox.spy(utils, ['triggerPixel']); - viewability.startMeasurement('1', {}, { method: 'img', value: 'http://my.tracker/123' }, { inViewThreshold: 0.5, timeInView: 1000 }); - expect(triggerPixelSpy.callCount).to.equal(1); - }); - - it('should trigger js tracker', () => { - let insertHtmlIntoIframeSpy = sandbox.spy(utils, ['insertHtmlIntoIframe']); - viewability.startMeasurement('2', {}, { method: 'js', value: 'http://my.tracker/123.js' }, { inViewThreshold: 0.5, timeInView: 1000 }); - expect(insertHtmlIntoIframeSpy.callCount).to.equal(1); - }); - - it('should trigger callback tracker', () => { - let callbackFired = false; - viewability.startMeasurement('3', {}, { method: 'callback', value: () => { callbackFired = true; } }, { inViewThreshold: 0.5, timeInView: 1000 }); - expect(callbackFired).to.equal(true); - }); - - it('should check for vid uniqueness', () => { - let logWarnSpy = sandbox.spy(utils, 'logWarn'); - viewability.startMeasurement('4', {}, { method: 'js', value: 'http://my.tracker/123.js' }, { inViewThreshold: 0.5, timeInView: 1000 }); - expect(logWarnSpy.callCount).to.equal(0); - - viewability.startMeasurement('4', {}, { method: 'js', value: 'http://my.tracker/123.js' }, { inViewThreshold: 0.5, timeInView: 1000 }); - expect(logWarnSpy.callCount).to.equal(1); - expect(logWarnSpy.calledWith(`${viewability.MODULE_NAME}: must provide an unregistered vid`, '4')).to.equal(true); - }); - - it('should check for valid criteria', () => { - let logWarnSpy = sandbox.spy(utils, 'logWarn'); - viewability.startMeasurement('5', {}, { method: 'js', value: 'http://my.tracker/123.js' }, { timeInView: 1000 }); - expect(logWarnSpy.callCount).to.equal(1); - expect(logWarnSpy.calledWith(`${viewability.MODULE_NAME}: missing criteria`, { timeInView: 1000 })).to.equal(true); - }); - - it('should check for valid tracker', () => { - let logWarnSpy = sandbox.spy(utils, 'logWarn'); - viewability.startMeasurement('6', {}, { method: 'callback', value: 'string' }, { inViewThreshold: 0.5, timeInView: 1000 }); - expect(logWarnSpy.callCount).to.equal(1); - expect(logWarnSpy.calledWith(`${viewability.MODULE_NAME}: invalid tracker`, { method: 'callback', value: 'string' })).to.equal(true); - }); - - it('should check if element provided', () => { - let logWarnSpy = sandbox.spy(utils, 'logWarn'); - viewability.startMeasurement('7', undefined, { method: 'js', value: 'http://my.tracker/123.js' }, { timeInView: 1000 }); - expect(logWarnSpy.callCount).to.equal(1); - expect(logWarnSpy.calledWith(`${viewability.MODULE_NAME}: no html element provided`)).to.equal(true); - }); - }); - - describe('stop measurement', () => { - let sandbox; - let intersectionObserverStub; - let setTimeoutStub; - let clearTimeoutStub; - let observeCalled; - let unobserveCalled; - let stateChangeBackup; - let ti = 1; - beforeEach(() => { - observeCalled = false; - unobserveCalled = false; - sandbox = sinon.sandbox.create(); - - let fakeIntersectionObserver = (stateChange, options) => { - return { - observe: (element) => { - stateChangeBackup = stateChange; - observeCalled = true; - stateChange([{ isIntersecting: true }]); - }, - unobserve: (element) => { - unobserveCalled = true; - }, - }; - }; - - intersectionObserverStub = sandbox.stub(window, 'IntersectionObserver').callsFake(fakeIntersectionObserver); - setTimeoutStub = sandbox.stub(window, 'setTimeout').callsFake((callback, timeout) => { - // skipping the callback - return ti++; - }); - clearTimeoutStub = sandbox.stub(window, 'clearTimeout').callsFake((timeoutId) => { }); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('should clear the timeout', () => { - viewability.startMeasurement('10', {}, { method: 'img', value: 'http://my.tracker/123' }, { inViewThreshold: 0.5, timeInView: 1000 }); - stateChangeBackup([{ isIntersecting: false }]); - sinon.assert.called(intersectionObserverStub); - sinon.assert.called(setTimeoutStub); - sinon.assert.called(clearTimeoutStub); - expect(observeCalled).to.equal(true); - }); - - it('should unobserve', () => { - viewability.startMeasurement('11', {}, { method: 'img', value: 'http://my.tracker/123' }, { inViewThreshold: 0.5, timeInView: 1000 }); - sinon.assert.called(intersectionObserverStub); - sinon.assert.called(setTimeoutStub); - expect(observeCalled).to.equal(true); - expect(unobserveCalled).to.equal(false); - - viewability.stopMeasurement('11'); - expect(unobserveCalled).to.equal(true); - sinon.assert.called(clearTimeoutStub); - }); - - it('should check for vid existence', () => { - let logWarnSpy = sandbox.spy(utils, 'logWarn'); - viewability.stopMeasurement('100'); - expect(logWarnSpy.callCount).to.equal(1); - expect(logWarnSpy.calledWith(`${viewability.MODULE_NAME}: must provide a registered vid`, '100')).to.equal(true); - }); - }); - - describe('handle creative messages', () => { - let sandbox; - let intersectionObserverStub; - let setTimeoutStub; - let observeCalled; - let unobserveCalled; - let ti = 1; - let getElementsByTagStub; - let getElementByIdStub; - - let fakeContentWindow = {}; - beforeEach(() => { - observeCalled = false; - unobserveCalled = false; - sandbox = sinon.sandbox.create(); - - let fakeIntersectionObserver = (stateChange, options) => { - return { - observe: (element) => { - observeCalled = true; - stateChange([{ isIntersecting: true }]); - }, - unobserve: (element) => { - unobserveCalled = true; - }, - }; - }; - - intersectionObserverStub = sandbox.stub(window, 'IntersectionObserver').callsFake(fakeIntersectionObserver); - setTimeoutStub = sandbox.stub(window, 'setTimeout').callsFake((callback, timeout) => { - callback(); - return ti++; - }); - - getElementsByTagStub = sandbox.stub(document, 'getElementsByTagName').callsFake((tagName) => { - return [{ - contentWindow: fakeContentWindow, - }]; - }); - getElementByIdStub = sandbox.stub(document, 'getElementById').callsFake((id) => { - return {}; - }); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('should find element by contentWindow', () => { - let viewabilityRecord = { - vid: 1000, - tracker: { - value: 'http://my.tracker/123', - method: 'img', - }, - criteria: { inViewThreshold: 0.5, timeInView: 1000 }, - message: 'Prebid Viewability', - action: 'startMeasurement', - }; - let data = JSON.stringify(viewabilityRecord); - - viewability.receiveMessage({ - data: data, - source: fakeContentWindow, - }); - - sinon.assert.called(getElementsByTagStub); - sinon.assert.called(intersectionObserverStub); - sinon.assert.called(setTimeoutStub); - expect(observeCalled).to.equal(true); - expect(unobserveCalled).to.equal(true); - }); - - it('should find element by id', () => { - let viewabilityRecord = { - vid: 1001, - tracker: { - value: 'http://my.tracker/123', - method: 'img', - }, - criteria: { inViewThreshold: 0.5, timeInView: 1000 }, - message: 'Prebid Viewability', - action: 'startMeasurement', - elementId: '1', - }; - let data = JSON.stringify(viewabilityRecord); - viewability.receiveMessage({ - data: data, - }); - - sinon.assert.called(getElementByIdStub); - sinon.assert.called(intersectionObserverStub); - sinon.assert.called(setTimeoutStub); - expect(observeCalled).to.equal(true); - expect(unobserveCalled).to.equal(true); - }); - - it('should stop measurement', () => { - let viewabilityRecord = { - vid: 1001, - message: 'Prebid Viewability', - action: 'stopMeasurement', - }; - let data = JSON.stringify(viewabilityRecord); - viewability.receiveMessage({ - data: data, - }); - - expect(unobserveCalled).to.equal(true); - }); - }); -}); diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 4aaaf996f58..4a8207768ab 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -3,7 +3,6 @@ import { spec } from 'modules/visxBidAdapter.js'; import { config } from 'src/config.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import * as utils from 'src/utils.js'; -import { makeSlot } from '../integration/faker/googletag.js'; describe('VisxAdapter', function () { const adapter = newBidder(spec); @@ -18,7 +17,7 @@ describe('VisxAdapter', function () { let bid = { 'bidder': 'visx', 'params': { - 'uid': 903536 + 'uid': '903536' }, 'adUnitCode': 'adunit-code', 'sizes': [[300, 250], [300, 600]], @@ -40,22 +39,12 @@ describe('VisxAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when uid can not be parsed as number', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - 'uid': 'sdvsdv' - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - it('it should fail on invalid video bid', function () { let videoBid = Object.assign({}, bid); videoBid.mediaTypes = { video: { context: 'instream', - mimes: ['video/mp4'], - protocols: [3, 6] + playerSize: [400, 300] } }; expect(spec.isBidRequestValid(videoBid)).to.equal(false); @@ -66,7 +55,9 @@ describe('VisxAdapter', function () { videoBid.mediaTypes = { video: { context: 'instream', - playerSize: [[400, 300]] + playerSize: [400, 300], + mimes: ['video/mp4'], + protocols: [3, 6] } }; expect(spec.isBidRequestValid(videoBid)).to.equal(true); @@ -74,16 +65,7 @@ describe('VisxAdapter', function () { }); describe('buildRequests', function () { - function parseRequest(url) { - const res = {}; - (url.split('?')[1] || '').split('&').forEach((it) => { - const couple = it.split('='); - res[couple[0]] = decodeURIComponent(couple[1]); - }); - return res; - } const bidderRequest = { - timeout: 3000, refererInfo: { referer: 'https://example.com' } @@ -96,11 +78,12 @@ describe('VisxAdapter', function () { {asi: 'exchange1.com', sid: '1234!abcd', hp: 1, name: 'publisher, Inc.', domain: 'publisher.com'} ] }; + const schainString = JSON.stringify(schainObject); let bidRequests = [ { 'bidder': 'visx', 'params': { - 'uid': 903535 + 'uid': '903535' }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], @@ -122,7 +105,7 @@ describe('VisxAdapter', function () { { 'bidder': 'visx', 'params': { - 'uid': 903536 + 'uid': '903536' }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], @@ -133,13 +116,13 @@ describe('VisxAdapter', function () { { 'bidder': 'visx', 'params': { - 'uid': 903537 + 'uid': '903537' }, 'adUnitCode': 'adunit-code-video-3', 'mediaTypes': { 'video': { 'context': 'instream', - 'playerSize': [[400, 300]], + 'playerSize': [400, 300], 'mimes': ['video/mp4', 'video/mpeg'], 'protocols': [3, 6], 'minduration': 5, @@ -152,91 +135,83 @@ describe('VisxAdapter', function () { } ]; - const expectedFullImps = [{ - 'id': '30b31c1838de1e', - 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, - 'ext': {'bidder': {'uid': 903535, 'adslotExists': false}} - }, - { - 'id': '3150ccb55da321', - 'banner': {'format': [{'w': 728, 'h': 90}, {'w': 300, 'h': 250}]}, - 'ext': {'bidder': {'uid': 903535, 'adslotExists': false}} - }, - { - 'id': '42dbe3a7168a6a', - 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, - 'ext': {'bidder': {'uid': 903536, 'adslotExists': false}} - }, - { - 'id': '39a4e3a7168a6a', - 'video': { - 'w': 400, - 'h': 300, - 'mimes': ['video/mp4', 'video/mpeg'], - 'protocols': [3, 6], - 'minduration': 5, - 'maxduration': 30 - }, - 'ext': {'bidder': {'uid': 903537}} - }]; - it('should attach valid params to the tag', function () { - const firstBid = bidRequests[0]; - const bids = [firstBid]; - const request = spec.buildRequests(bids, bidderRequest); - const payload = parseRequest(request.url); - expect(request.url).to.be.an('string'); + const request = spec.buildRequests([bidRequests[0]], bidderRequest); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535'); + expect(payload).to.have.property('sizes', '300x250,300x600'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'EUR'); + }); - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': [expectedFullImps[0]], - 'tmax': 3000, - 'cur': ['EUR'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, - 'site': {'page': referrer} - }); + it('sizes must not be duplicated', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '903535,903535,903536,903537'); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'EUR'); }); - it('should attach valid params to the tag with multiformat request', function () { + it('pt parameter must be "net" if params.priceType === "gross"', function () { + bidRequests[1].params.priceType = 'gross'; + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '903535,903535,903536,903537'); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'EUR'); + delete bidRequests[1].params.priceType; + }); + it('pt parameter must be "net" if params.priceType === "net"', function () { + bidRequests[1].params.priceType = 'net'; const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = parseRequest(request.url); + const payload = request.data; expect(payload).to.be.an('object'); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536,903537'); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'EUR'); + delete bidRequests[1].params.priceType; + }); - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': expectedFullImps, - 'tmax': 3000, - 'cur': ['EUR'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, - 'site': {'page': referrer} - }); + it('pt parameter must be "net" if params.priceType === "undefined"', function () { + bidRequests[1].params.priceType = 'undefined'; + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '903535,903535,903536,903537'); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'EUR'); + delete bidRequests[1].params.priceType; }); it('should add currency from currency.bidderCurrencyDefault', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'GBP' : 'USD'); const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = parseRequest(request.url); + const payload = request.data; expect(payload).to.be.an('object'); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536,903537'); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': expectedFullImps, - 'tmax': 3000, - 'cur': ['GBP'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, - 'site': {'page': referrer} - }); - + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'GBP'); getConfigStub.restore(); }); @@ -244,73 +219,39 @@ describe('VisxAdapter', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? '' : 'USD'); const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = parseRequest(request.url); + const payload = request.data; expect(payload).to.be.an('object'); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536,903537'); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': expectedFullImps, - 'tmax': 3000, - 'cur': ['USD'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, - 'site': {'page': referrer} - }); - + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'USD'); getConfigStub.restore(); }); it('if gdprConsent is present payload must have gdpr params', function () { - const request = spec.buildRequests(bidRequests, Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: true}}, bidderRequest)); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': expectedFullImps, - 'tmax': 3000, - 'cur': ['EUR'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, - 'site': {'page': referrer}, - 'user': {'ext': {'consent': 'AAA'}}, - 'regs': {'ext': {'gdpr': 1}} - }); + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('gdpr_consent', 'AAA'); + expect(payload).to.have.property('gdpr_applies', 1); }); it('if gdprApplies is false gdpr_applies must be 0', function () { - const request = spec.buildRequests(bidRequests, Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: false}}, bidderRequest)); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': expectedFullImps, - 'tmax': 3000, - 'cur': ['EUR'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, - 'site': {'page': referrer}, - 'user': {'ext': {'consent': 'AAA'}}, - 'regs': {'ext': {'gdpr': 0}} - }); + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('gdpr_consent', 'AAA'); + expect(payload).to.have.property('gdpr_applies', 0); }); it('if gdprApplies is undefined gdpr_applies must be 1', function () { - const request = spec.buildRequests(bidRequests, Object.assign({gdprConsent: {consentString: 'AAA'}}, bidderRequest)); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': expectedFullImps, - 'tmax': 3000, - 'cur': ['EUR'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, - 'site': {'page': referrer}, - 'user': {'ext': {'consent': 'AAA'}}, - 'regs': {'ext': {'gdpr': 1}} - }); + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('gdpr_consent', 'AAA'); + expect(payload).to.have.property('gdpr_applies', 1); }); it('if schain is present payload must have schain param', function () { @@ -320,110 +261,49 @@ describe('VisxAdapter', function () { bidRequests[2] ]; const request = spec.buildRequests(schainBidRequests, bidderRequest); - const payload = parseRequest(request.url); + const payload = request.data; expect(payload).to.be.an('object'); + expect(payload).to.have.property('schain', schainString); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': expectedFullImps.slice(0, -1), - 'tmax': 3000, - 'cur': ['EUR'], - 'source': { - 'ext': { - 'wrapperType': 'Prebid_js', - 'wrapperVersion': '$prebid.version$', - 'schain': schainObject - } - }, - 'site': {'page': referrer}, - }); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'EUR'); }); it('if userId is available payload must have appropriate params', function () { - const eids = [ - { - source: 'pubcid.org', - uids: [{ - id: 'some-random-id-value', - atype: 1 - }] - }, - { - source: 'adserver.org', - uids: [{ - id: 'some-random-id-value', - atype: 1, - ext: { - rtiPartner: 'TDID' - } - }] - } - ]; - const userIdBidRequests = [ + const schainBidRequests = [ Object.assign({userId: { tdid: '111', id5id: { uid: '222' }, digitrustid: {data: {id: 'DTID', keyv: 4, privacy: {optout: false}, producer: 'ABC', version: 2}} - }, - userIdAsEids: eids}, bidRequests[0]), + }}, bidRequests[0]), bidRequests[1], bidRequests[2] ]; - const request = spec.buildRequests(userIdBidRequests, bidderRequest); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': expectedFullImps.slice(0, -1), - 'tmax': 3000, - 'cur': ['EUR'], - 'source': { - 'ext': { - 'wrapperType': 'Prebid_js', - 'wrapperVersion': '$prebid.version$' - } - }, - 'site': {'page': referrer}, - 'user': {'ext': {'eids': eids}} - }); + const request = spec.buildRequests(schainBidRequests, bidderRequest); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('tdid', '111'); + expect(payload).to.have.property('id5', '222'); + expect(payload).to.have.property('dtid', 'DTID'); }); it('should pass grouped video bid\'s params in payload', function () { const request = spec.buildRequests(bidRequests, bidderRequest); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': expectedFullImps, - 'tmax': 3000, - 'cur': ['EUR'], - 'source': { - 'ext': { - 'wrapperType': 'Prebid_js', - 'wrapperVersion': '$prebid.version$' - } - }, - 'site': {'page': referrer} - }); + const payload = request.data; + expect(payload).to.have.property('protocols', ',,,3|6'); + expect(payload).to.have.property('mimes', ',,,video/mp4|video/mpeg'); + expect(payload).to.have.property('playerSize', ',,,400x300'); + expect(payload).to.have.property('minduration', ',,,5'); + expect(payload).to.have.property('maxduration', ',,,30'); + expect(payload).to.not.have.property('skip'); }); }); describe('buildRequests (multiple media types w/ unsupported video+outstream)', function () { - function parseRequest(url) { - const res = {}; - (url.split('?')[1] || '').split('&').forEach((it) => { - const couple = it.split('='); - res[couple[0]] = decodeURIComponent(couple[1]); - }); - return res; - } const bidderRequest = { - timeout: 3000, refererInfo: { referer: 'https://example.com' } @@ -440,164 +320,33 @@ describe('VisxAdapter', function () { 'mediaTypes': { 'video': { 'context': 'outstream', - 'playerSize': [[400, 300]] + 'playerSize': [400, 300] } }, 'bidId': '39aff3a7169a6a', - 'bidderRequestId': '22edbae2733bf6', + 'bidderRequestId': '22edffe2733bf6', 'auctionId': '1d1a030790a476', } ]; it('should send requst for banner bid', function () { const request = spec.buildRequests([bidRequests[0]], bidderRequest); - const payload = parseRequest(request.url); + const payload = request.data; expect(payload).to.be.an('object'); + expect(payload).to.have.property('u', referrer); + expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903538'); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': [{ - 'id': '39aff3a7169a6a', - 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, - 'ext': {'bidder': {'uid': 903538, 'adslotExists': false}} - }], - 'tmax': 3000, - 'cur': ['EUR'], - 'source': { - 'ext': { - 'wrapperType': 'Prebid_js', - 'wrapperVersion': '$prebid.version$' - } - }, - 'site': {'page': referrer} - }); - }); - }); - - describe('buildRequests (check ad slot exists)', function () { - function parseRequest(url) { - const res = {}; - (url.split('?')[1] || '').split('&').forEach((it) => { - const couple = it.split('='); - res[couple[0]] = decodeURIComponent(couple[1]); - }); - return res; - } - const bidderRequest = { - timeout: 3000, - refererInfo: { - referer: 'https://example.com' - } - }; - const referrer = bidderRequest.refererInfo.referer; - const bidRequests = [ - { - 'bidder': 'visx', - 'params': { - 'uid': 903535 - }, - 'adUnitCode': 'visx-adunit-code-1', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }, - { - 'bidder': 'visx', - 'params': { - 'uid': 903535 - }, - 'adUnitCode': 'visx-adunit-code-2', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - let sandbox; - let documentStub; - - before(function() { - sandbox = sinon.sandbox.create(); - documentStub = sandbox.stub(document, 'getElementById'); - documentStub.withArgs('visx-adunit-code-1').returns({ - id: 'visx-adunit-code-1' - }); - documentStub.withArgs('visx-adunit-element-2').returns({ - id: 'visx-adunit-element-2' - }); - }); - - after(function() { - sandbox.restore(); - }); - - it('should find ad slot by ad unit code as element id', function () { - const request = spec.buildRequests([bidRequests[0]], bidderRequest); - const payload = parseRequest(request.url); - expect(payload).to.be.an('object'); - expect(payload).to.have.property('auids', '903535'); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': [{ - 'id': '30b31c1838de1e', - 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, - 'ext': {'bidder': {'uid': 903535, 'adslotExists': true}} - }], - 'tmax': 3000, - 'cur': ['EUR'], - 'source': { - 'ext': { - 'wrapperType': 'Prebid_js', - 'wrapperVersion': '$prebid.version$' - } - }, - 'site': {'page': referrer} - }); - }); - - it('should find ad slot by ad unit code as adUnitPath', function () { - makeSlot({code: 'visx-adunit-code-2', divId: 'visx-adunit-element-2'}); - - const request = spec.buildRequests([bidRequests[1]], bidderRequest); - const payload = parseRequest(request.url); - expect(payload).to.be.an('object'); - expect(payload).to.have.property('auids', '903535'); - - const postData = request.data; - expect(postData).to.be.an('object'); - expect(postData).to.deep.equal({ - 'id': '22edbae2733bf6', - 'imp': [{ - 'id': '30b31c1838de1e', - 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, - 'ext': {'bidder': {'uid': 903535, 'adslotExists': true}} - }], - 'tmax': 3000, - 'cur': ['EUR'], - 'source': { - 'ext': { - 'wrapperType': 'Prebid_js', - 'wrapperVersion': '$prebid.version$' - } - }, - 'site': {'page': referrer} - }); + expect(payload).to.have.property('sizes', '300x250,300x600'); + expect(payload).to.not.have.property('playerSize'); }); }); describe('interpretResponse', function () { const responses = [ - {'bid': [{'price': 1.15, 'impid': '300bfeb0d71a5b', 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'advertiserDomains': ['some_domain.com'], 'ext': {'prebid': {'targeting': {'hb_visx_product': 'understitial', 'hb_visx_width': 300, 'hb_visx_height': 250}}}}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'impid': '4dff80cc4ee346', 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'impid': '5703af74d0472a', 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0, 'impid': '300bfeb0d7190gf', 'auid': 903537, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'advertiserDomains': ['some_domain.com']}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 903537, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, {'bid': [{'price': 0, 'adm': '
test content 5
', 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, undefined, {'bid': [], 'seat': '1'}, @@ -613,7 +362,7 @@ describe('VisxAdapter', function () { }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], - 'bidId': '300bfeb0d71a5b', + 'bidId': '659423fff799cb', 'bidderRequestId': '5f2009617a7c0a', 'auctionId': '1cbd2feafe5e8b', } @@ -621,7 +370,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests); const expectedResponse = [ { - 'requestId': '300bfeb0d71a5b', + 'requestId': '659423fff799cb', 'cpm': 1.15, 'creativeId': 903535, 'dealId': undefined, @@ -635,18 +384,6 @@ describe('VisxAdapter', function () { 'advertiserDomains': ['some_domain.com'], 'mediaType': 'banner', }, - 'adserverTargeting': { - 'hb_visx_product': 'understitial', - 'hb_visx_width': 300, - 'hb_visx_height': 250, - }, - 'ext': { - 'targeting': { - 'hb_visx_product': 'understitial', - 'hb_visx_width': 300, - 'hb_visx_height': 250, - } - } } ]; @@ -707,18 +444,6 @@ describe('VisxAdapter', function () { 'advertiserDomains': ['some_domain.com'], 'mediaType': 'banner', }, - 'adserverTargeting': { - 'hb_visx_product': 'understitial', - 'hb_visx_width': 300, - 'hb_visx_height': 250, - }, - 'ext': { - 'targeting': { - 'hb_visx_product': 'understitial', - 'hb_visx_width': 300, - 'hb_visx_height': 250, - } - } }, { 'requestId': '4dff80cc4ee346', @@ -767,7 +492,7 @@ describe('VisxAdapter', function () { }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], - 'bidId': '300bfeb0d71a5b', + 'bidId': '659423fff799cb', 'bidderRequestId': '5f2009617a7c0a', 'auctionId': '1cbd2feafe5e8b', } @@ -776,7 +501,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests); const expectedResponse = [ { - 'requestId': '300bfeb0d71a5b', + 'requestId': '659423fff799cb', 'cpm': 1.15, 'creativeId': 903535, 'dealId': undefined, @@ -790,18 +515,6 @@ describe('VisxAdapter', function () { 'advertiserDomains': ['some_domain.com'], 'mediaType': 'banner', }, - 'adserverTargeting': { - 'hb_visx_product': 'understitial', - 'hb_visx_width': 300, - 'hb_visx_height': 250, - }, - 'ext': { - 'targeting': { - 'hb_visx_product': 'understitial', - 'hb_visx_width': 300, - 'hb_visx_height': 250, - } - } } ]; @@ -855,11 +568,11 @@ describe('VisxAdapter', function () { it('complicated case', function () { const fullResponse = [ - {'bid': [{'price': 1.15, 'impid': '2164be6358b9', 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'advertiserDomains': ['some_domain.com']}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'impid': '4e111f1b66e4', 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'impid': '26d6f897b516', 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'impid': '326bde7fbf69', 'adm': '
test content 4
', 'auid': 903535, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'impid': '1751cd90161', 'adm': '
test content 5
', 'auid': 903536, 'h': 600, 'w': 350, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'advertiserDomains': ['some_domain.com']}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 4
', 'auid': 903535, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 5
', 'auid': 903536, 'h': 600, 'w': 350, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, ]; const bidRequests = [ { @@ -1008,8 +721,8 @@ describe('VisxAdapter', function () { it('dublicate uids and sizes in one slot', function () { const fullResponse = [ - {'bid': [{'price': 1.15, 'impid': '5126e301f4be', 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'impid': '57b2ebe70e16', 'adm': '
test content 2
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, ]; const bidRequests = [ { @@ -1088,7 +801,7 @@ describe('VisxAdapter', function () { it('handles video bid', function () { const fullResponse = [ - {'bid': [{'price': 0.5, 'impid': '2164be6358b9', 'adm': '', 'auid': 903537, 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '', 'auid': 903537, 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video'}], 'seat': '1'}, ]; const bidRequests = [ { @@ -1100,7 +813,7 @@ describe('VisxAdapter', function () { 'mediaTypes': { 'video': { 'context': 'instream', - 'playerSize': [[400, 300]], + 'playerSize': [400, 300], 'mimes': ['video/mp4'], 'protocols': [3, 6] } @@ -1137,7 +850,7 @@ describe('VisxAdapter', function () { it('handles multiformat bid response with outstream+banner as banner', function () { const fullResponse = [ - {'bid': [{'price': 0.5, 'impid': '2164be6358b9', 'adm': '', 'auid': 903537, 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '', 'auid': 903537, 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video'}], 'seat': '1'}, ]; const bidRequests = [ { @@ -1149,7 +862,7 @@ describe('VisxAdapter', function () { 'mediaTypes': { 'video': { 'context': 'outstream', - 'playerSize': [[400, 300]], + 'playerSize': [400, 300], 'mimes': ['video/mp4'], 'protocols': [3, 6] } @@ -1195,7 +908,7 @@ describe('VisxAdapter', function () { }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], - 'bidId': '300bfeb0d71a5b', + 'bidId': '659423fff799cb', 'bidderRequestId': '5f2009617a7c0a', 'auctionId': '1cbd2feafe5e8b', } @@ -1205,7 +918,7 @@ describe('VisxAdapter', function () { const winUrl = 'https://t.visx.net/track/win/53245341'; const expectedResponse = [ { - 'requestId': '300bfeb0d71a5b', + 'requestId': '659423fff799cb', 'cpm': 1.15, 'creativeId': 903535, 'dealId': undefined, @@ -1219,31 +932,23 @@ describe('VisxAdapter', function () { 'advertiserDomains': ['some_domain.com'], 'mediaType': 'banner', }, - 'adserverTargeting': { - 'hb_visx_product': 'understitial', - 'hb_visx_width': 300, - 'hb_visx_height': 250, - }, 'ext': { 'events': { 'pending': pendingUrl, 'win': winUrl - }, - 'targeting': { - 'hb_visx_product': 'understitial', - 'hb_visx_width': 300, - 'hb_visx_height': 250, } } } ]; const serverResponse = Object.assign({}, responses[0]); - serverResponse.bid = [Object.assign({}, serverResponse.bid[0])]; - serverResponse.bid[0].ext.prebid = Object.assign({}, serverResponse.bid[0].ext.prebid); - utils.deepSetValue(serverResponse.bid[0], 'ext.prebid.events', { - pending: pendingUrl, - win: winUrl, - }); + serverResponse.bid = [Object.assign({}, {ext: { + prebid: { + events: { + 'pending': pendingUrl, + 'win': winUrl + } + } + }}, serverResponse.bid[0])]; const result = spec.interpretResponse({'body': {'seatbid': [serverResponse]}}, request); expect(result).to.deep.equal(expectedResponse); }); @@ -1272,55 +977,9 @@ describe('VisxAdapter', function () { }); it('onTimeout', function () { - const data = [{ timeout: 3000, adUnitCode: 'adunit-code-1', auctionId: '1cbd2feafe5e8b', bidder: 'visx', bidId: '23423', params: [{ uid: '1' }] }]; - const expectedData = [{ ...data[0], params: [{ uid: 1 }] }]; + const data = { timeout: 3000, bidId: '23423', params: { uid: 1 } }; spec.onTimeout(data); - expect(utils.triggerPixel.calledOnceWith('https://t.visx.net/track/bid_timeout//' + JSON.stringify(expectedData))).to.equal(true); - }); - }); - - describe('user sync', function () { - function parseUrl(url) { - const [, path, querySt] = url.match(/^https?:\/\/[^\/]+(?:\/([^?]+)?)?(?:\?(.+)?)?$/) || []; - const query = {}; - (querySt || '').split('&').forEach((q) => { - var kv = q.split('='); - if (kv[0]) { - query[kv[0]] = decodeURIComponent(kv[1] || ''); - } - }); - return { path, query }; - } - it('should call iframe', function () { - let syncs = spec.getUserSyncs({ - iframeEnabled: true - }); - - expect(Array.isArray(syncs)).to.equal(true); - expect(syncs.length).to.equal(1); - expect(syncs[0]).to.have.property('type', 'iframe'); - expect(syncs[0]).to.have.property('url'); - expect(syncs[0].url).to.be.an('string'); - - const { path, query } = parseUrl(syncs[0].url); - expect(path).to.equal('push_sync'); - expect(query).to.deep.equal({iframe: '1'}); - }); - - it('should call image', function () { - let syncs = spec.getUserSyncs({ - pixelEnabled: true - }); - - expect(Array.isArray(syncs)).to.equal(true); - expect(syncs.length).to.equal(1); - expect(syncs[0]).to.have.property('type', 'image'); - expect(syncs[0]).to.have.property('url'); - expect(syncs[0].url).to.be.an('string'); - - const { path, query } = parseUrl(syncs[0].url); - expect(path).to.equal('push_sync'); - expect(query).to.deep.equal({}); + expect(utils.triggerPixel.calledOnceWith('https://t.visx.net/track/bid_timeout?data=' + JSON.stringify(data))).to.equal(true); }); }); }); diff --git a/test/spec/modules/vrtcalBidAdapter_spec.js b/test/spec/modules/vrtcalBidAdapter_spec.js index 66440130860..a5f2d475a29 100644 --- a/test/spec/modules/vrtcalBidAdapter_spec.js +++ b/test/spec/modules/vrtcalBidAdapter_spec.js @@ -29,7 +29,7 @@ describe('vrtcalBidAdapter', function () { } ]; - let request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests); it('sends bid request to our endpoint via POST', function () { expect(request[0].method).to.equal('POST'); @@ -38,18 +38,6 @@ describe('vrtcalBidAdapter', function () { it('adUnitCode should be sent as prebidAdUnitCode parameters on any requests', function () { expect(request[0].data).to.match(/"prebidAdUnitCode":"adunit0001"/); }); - - it('if the publisher has NOT set a floor via the floors module, zero should be sent as bidfloor parameter on any requests', function () { - expect(request[0].data).to.match(/"bidfloor":0/); - }); - - it('if the publisher has set a floor via the floors module, it should be sent as bidfloor parameter on any requests', function () { - let floorInfo; - bidRequests[0].getFloor = () => floorInfo; - floorInfo = {currency: 'USD', floor: 0.55}; - request = spec.buildRequests(bidRequests); - expect(request[0].data).to.match(/"bidfloor":0.55/); - }); }); describe('interpretResponse', function () { diff --git a/test/spec/modules/weboramaRtdProvider_spec.js b/test/spec/modules/weboramaRtdProvider_spec.js deleted file mode 100644 index 0f0af4efe2f..00000000000 --- a/test/spec/modules/weboramaRtdProvider_spec.js +++ /dev/null @@ -1,998 +0,0 @@ -import { - weboramaSubmodule -} from 'modules/weboramaRtdProvider.js'; -import { - server -} from 'test/mocks/xhr.js'; -import { - storage, - DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY -} from '../../../modules/weboramaRtdProvider.js'; -import { - config -} from 'src/config.js'; -import { - getGlobal -} from 'src/prebidGlobal.js'; -import 'src/prebid.js'; - -const responseHeader = { - 'Content-Type': 'application/json' -}; - -describe('weboramaRtdProvider', function () { - describe('weboramaSubmodule', function () { - it('successfully instantiates and call contextual api', function () { - const moduleConfig = { - params: { - weboCtxConf: { - token: 'foo', - targetURL: 'https://prebid.org', - } - } - }; - - expect(weboramaSubmodule.init(moduleConfig)).to.equal(true); - }); - - it('instantiate without contextual token should fail', function () { - const moduleConfig = { - params: { - weboCtxConf: {} - } - }; - expect(weboramaSubmodule.init(moduleConfig)).to.equal(false); - }); - - it('instantiate with empty weboUserData conf should return true', function () { - const moduleConfig = { - params: { - weboUserDataConf: {} - } - }; - expect(weboramaSubmodule.init(moduleConfig)).to.equal(true); - }); - }); - - describe('Handle Set Targeting', function () { - let sandbox; - - beforeEach(function () { - sandbox = sinon.sandbox.create(); - - storage.removeDataFromLocalStorage('webo_wam2gam_entry'); - - getGlobal().setConfig({ - ortb2: undefined - }); - }); - - afterEach(function () { - sandbox.restore(); - }); - - describe('Add Contextual Data', function () { - it('should set gam targeting and send to bidders by default', function () { - let onDataResponse = {}; - const moduleConfig = { - params: { - weboCtxConf: { - token: 'foo', - targetURL: 'https://prebid.org', - onData: (data, site) => { - onDataResponse = { - data: data, - site: site, - }; - }, - } - } - }; - const data = { - webo_ctx: ['foo', 'bar'], - webo_ds: ['baz'], - }; - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver' - }, { - bidder: 'pubmatic' - }, { - bidder: 'appnexus' - }, { - bidder: 'rubicon' - }, { - bidder: 'other' - }] - }] - }; - - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - let request = server.requests[0]; - - expect(request.method).to.equal('GET'); - expect(request.url).to.equal('https://ctx.weborama.com/api/profile?token=foo&url=https%3A%2F%2Fprebid.org&'); - expect(request.withCredentials).to.be.false; - - request.respond(200, responseHeader, JSON.stringify(data)); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({ - 'adunit1': data, - 'adunit2': data, - }); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(5); - expect(reqBidsConfigObj.adUnits[0].bids[0].params.target).to.equal('webo_ctx=foo;webo_ctx=bar;webo_ds=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[1].params.dctr).to.equal('webo_ctx=foo,bar|webo_ds=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[2].params.keywords).to.deep.equal(data); - expect(reqBidsConfigObj.adUnits[0].bids[3].params).to.deep.equal({ - inventory: data - }); - expect(reqBidsConfigObj.adUnits[0].bids[4].ortb2).to.deep.equal({ - site: { - ext: { - data: data - }, - } - }); - expect(getGlobal().getConfig('ortb2')).to.deep.equal({ - site: { - ext: { - data: data - }, - } - }); - expect(onDataResponse).to.deep.equal({ - data: data, - site: true, - }); - }); - - it('should set gam targeting but not send to bidders with setPrebidTargeting=true/sendToBidders=false', function () { - const moduleConfig = { - params: { - weboCtxConf: { - token: 'foo', - targetURL: 'https://prebid.org', - setPrebidTargeting: true, - sendToBidders: false, - } - } - }; - const data = { - webo_ctx: ['foo', 'bar'], - webo_ds: ['baz'], - }; - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver', - params: { - target: 'foo=bar' - } - }, { - bidder: 'pubmatic', - params: { - dctr: 'foo=bar' - } - }, { - bidder: 'appnexus', - params: { - keywords: { - foo: ['bar'] - } - } - }, { - bidder: 'rubicon', - params: { - inventory: { - foo: 'bar', - }, - visitor: { - baz: 'bam', - } - } - }, { - bidder: 'other', - }] - }] - }; - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - let request = server.requests[0]; - - expect(request.method).to.equal('GET'); - expect(request.url).to.equal('https://ctx.weborama.com/api/profile?token=foo&url=https%3A%2F%2Fprebid.org&'); - expect(request.withCredentials).to.be.false; - - request.respond(200, responseHeader, JSON.stringify(data)); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({ - 'adunit1': data, - 'adunit2': data, - }); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(5); - expect(reqBidsConfigObj.adUnits[0].bids[0].params.target).to.equal('foo=bar'); - expect(reqBidsConfigObj.adUnits[0].bids[1].params.dctr).to.equal('foo=bar'); - expect(reqBidsConfigObj.adUnits[0].bids[2].params.keywords).to.deep.equal({ - foo: ['bar'] - }); - expect(reqBidsConfigObj.adUnits[0].bids[3].params).to.deep.equal({ - inventory: { - foo: 'bar', - }, - visitor: { - baz: 'bam', - } - }); - expect(reqBidsConfigObj.adUnits[0].bids[4].ortb2).to.be.undefined; - expect(getGlobal().getConfig('ortb2')).to.be.undefined; - }); - - it('should set gam targeting but not send to bidders with (submodule override) setPrebidTargeting=true/(global) sendToBidders=false', function () { - let onDataResponse = {}; - const moduleConfig = { - params: { - setPrebidTargeting: false, - sendToBidders: false, - onData: (data, site) => { - onDataResponse = { - data: data, - site: site, - }; - }, - weboCtxConf: { - token: 'foo', - targetURL: 'https://prebid.org', - setPrebidTargeting: true, // submodule parameter will override module parameter - } - } - }; - const data = { - webo_ctx: ['foo', 'bar'], - webo_ds: ['baz'], - }; - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver', - params: { - target: 'foo=bar' - } - }] - }] - }; - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - let request = server.requests[0]; - - expect(request.method).to.equal('GET'); - expect(request.url).to.equal('https://ctx.weborama.com/api/profile?token=foo&url=https%3A%2F%2Fprebid.org&'); - expect(request.withCredentials).to.be.false; - - request.respond(200, responseHeader, JSON.stringify(data)); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({ - 'adunit1': data, - 'adunit2': data, - }); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(1); - expect(getGlobal().getConfig('ortb2')).to.be.undefined; - - expect(onDataResponse).to.deep.equal({ - data: data, - site: true, - }); - }); - - it('should not set gam targeting with setPrebidTargeting=false but send to bidders', function () { - const moduleConfig = { - params: { - weboCtxConf: { - token: 'foo', - targetURL: 'https://prebid.org', - setPrebidTargeting: false, - } - } - }; - const data = { - webo_ctx: ['foo', 'bar'], - webo_ds: ['baz'], - }; - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver', - params: { - target: 'foo=bar' - } - }, { - bidder: 'pubmatic', - params: { - dctr: 'foo=bar' - } - }, { - bidder: 'appnexus', - params: { - keywords: { - foo: ['bar'] - } - } - }, { - bidder: 'rubicon', - params: { - inventory: { - foo: 'bar', - }, - visitor: { - baz: 'bam', - } - } - }, { - bidder: 'other', - }] - }] - } - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - let request = server.requests[0]; - - expect(request.method).to.equal('GET'); - expect(request.url).to.equal('https://ctx.weborama.com/api/profile?token=foo&url=https%3A%2F%2Fprebid.org&'); - expect(request.withCredentials).to.be.false; - - request.respond(200, responseHeader, JSON.stringify(data)); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({}); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(5); - expect(reqBidsConfigObj.adUnits[0].bids[0].params.target).to.equal('foo=bar;webo_ctx=foo;webo_ctx=bar;webo_ds=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[1].params.dctr).to.equal('foo=bar|webo_ctx=foo,bar|webo_ds=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[2].params.keywords).to.deep.equal({ - foo: ['bar'], - webo_ctx: ['foo', 'bar'], - webo_ds: ['baz'], - }); - expect(reqBidsConfigObj.adUnits[0].bids[3].params).to.deep.equal({ - inventory: { - foo: 'bar', - webo_ctx: ['foo', 'bar'], - webo_ds: ['baz'], - }, - visitor: { - baz: 'bam', - } - }); - expect(reqBidsConfigObj.adUnits[0].bids[4].ortb2).to.deep.equal({ - site: { - ext: { - data: data - }, - } - }); - expect(getGlobal().getConfig('ortb2')).to.deep.equal({ - site: { - ext: { - data: data - }, - } - }); - }); - - it('should use default profile in case of api error', function () { - const defaultProfile = { - webo_ctx: ['baz'], - }; - let onDataResponse = {}; - const moduleConfig = { - params: { - weboCtxConf: { - token: 'foo', - targetURL: 'https://prebid.org', - setPrebidTargeting: true, - defaultProfile: defaultProfile, - onData: (data, site) => { - onDataResponse = { - data: data, - site: site, - }; - }, - } - } - }; - - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver' - }, { - bidder: 'pubmatic' - }, { - bidder: 'appnexus' - }, { - bidder: 'rubicon' - }, { - bidder: 'other' - }] - }] - }; - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - let request = server.requests[0]; - - expect(request.method).to.equal('GET'); - expect(request.url).to.equal('https://ctx.weborama.com/api/profile?token=foo&url=https%3A%2F%2Fprebid.org&'); - expect(request.withCredentials).to.be.false; - - request.respond(500, responseHeader); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({ - 'adunit1': defaultProfile, - 'adunit2': defaultProfile, - }); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(5); - expect(reqBidsConfigObj.adUnits[0].bids[0].params.target).to.equal('webo_ctx=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[1].params.dctr).to.equal('webo_ctx=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[2].params.keywords).to.deep.equal(defaultProfile); - expect(reqBidsConfigObj.adUnits[0].bids[3].params).to.deep.equal({ - inventory: defaultProfile - }); - expect(reqBidsConfigObj.adUnits[0].bids[4].ortb2).to.deep.equal({ - site: { - ext: { - data: defaultProfile - }, - } - }); - expect(getGlobal().getConfig('ortb2')).to.deep.equal({ - site: { - ext: { - data: defaultProfile - }, - } - }); - expect(onDataResponse).to.deep.equal({ - data: defaultProfile, - site: true, - }); - }); - }); - - describe('Add user-centric data (WAM2GAM)', function () { - it('should set gam targeting from local storage and send to bidders by default', function () { - let onDataResponse = {}; - const moduleConfig = { - params: { - weboUserDataConf: { - accountID: 12345, - onData: (data, site) => { - onDataResponse = { - data: data, - site: site, - }; - }, - } - } - }; - const data = { - webo_cs: ['foo', 'bar'], - webo_audiences: ['baz'], - }; - - const entry = { - targeting: data, - }; - - sandbox.stub(storage, 'localStorageIsEnabled').returns(true); - sandbox.stub(storage, 'getDataFromLocalStorage') - .withArgs(DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY) - .returns(JSON.stringify(entry)); - - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver' - }, { - bidder: 'pubmatic' - }, { - bidder: 'appnexus' - }, { - bidder: 'rubicon' - }, { - bidder: 'other' - }] - }] - }; - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({ - 'adunit1': data, - 'adunit2': data, - }); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(5); - expect(reqBidsConfigObj.adUnits[0].bids[0].params.target).to.equal('webo_cs=foo;webo_cs=bar;webo_audiences=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[1].params.dctr).to.equal('webo_cs=foo,bar|webo_audiences=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[2].params.keywords).to.deep.equal(data); - expect(reqBidsConfigObj.adUnits[0].bids[3].params).to.deep.equal({ - visitor: data - }); - expect(reqBidsConfigObj.adUnits[0].bids[4].ortb2).to.deep.equal({ - user: { - ext: { - data: data - }, - } - }); - expect(getGlobal().getConfig('ortb2')).to.deep.equal({ - user: { - ext: { - data: data - }, - } - }); - expect(onDataResponse).to.deep.equal({ - data: data, - site: false, - }); - }); - - it('should set gam targeting but not send to bidders with setPrebidTargeting=true/sendToBidders=false', function () { - const moduleConfig = { - params: { - weboUserDataConf: { - setPrebidTargeting: true, - sendToBidders: false - } - } - }; - const data = { - webo_cs: ['foo', 'bar'], - webo_audiences: ['baz'], - }; - - const entry = { - targeting: data, - }; - - sandbox.stub(storage, 'localStorageIsEnabled').returns(true); - sandbox.stub(storage, 'getDataFromLocalStorage') - .withArgs(DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY) - .returns(JSON.stringify(entry)); - - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver', - params: { - target: 'foo=bar' - } - }, { - bidder: 'pubmatic', - params: { - dctr: 'foo=bar' - } - }, { - bidder: 'appnexus', - params: { - keywords: { - foo: ['bar'] - } - } - }, { - bidder: 'rubicon', - params: { - inventory: { - foo: 'bar' - }, - visitor: { - baz: 'bam' - } - } - }, { - bidder: 'other' - }] - }] - }; - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({ - 'adunit1': data, - 'adunit2': data, - }); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(5); - expect(reqBidsConfigObj.adUnits[0].bids[0].params.target).to.equal('foo=bar'); - expect(reqBidsConfigObj.adUnits[0].bids[1].params.dctr).to.equal('foo=bar'); - expect(reqBidsConfigObj.adUnits[0].bids[2].params.keywords).to.deep.equal({ - foo: ['bar'] - }); - expect(reqBidsConfigObj.adUnits[0].bids[3].params).to.deep.equal({ - inventory: { - foo: 'bar' - }, - visitor: { - baz: 'bam' - } - }); - expect(reqBidsConfigObj.adUnits[0].bids[4].ortb2).to.be.undefined; - expect(getGlobal().getConfig('ortb2')).to.be.undefined; - }); - - it('should set gam targeting but not send to bidders with (submodule override) setPrebidTargeting=true/(global) sendToBidders=false', function () { - let onDataResponse = {}; - const moduleConfig = { - params: { - setPrebidTargeting: false, - sendToBidders: false, - onData: (data, site) => { - onDataResponse = { - data: data, - site: site, - }; - }, - weboUserDataConf: { - setPrebidTargeting: true, // submodule parameter will override module parameter - } - } - }; - const data = { - webo_cs: ['foo', 'bar'], - webo_audiences: ['baz'], - }; - - const entry = { - targeting: data, - }; - - sandbox.stub(storage, 'localStorageIsEnabled').returns(true); - sandbox.stub(storage, 'getDataFromLocalStorage') - .withArgs(DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY) - .returns(JSON.stringify(entry)); - - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver', - params: { - target: 'foo=bar' - } - }] - }] - }; - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({ - 'adunit1': data, - 'adunit2': data, - }); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(1); - expect(reqBidsConfigObj.adUnits[0].bids[0].params.target).to.equal('foo=bar'); - expect(getGlobal().getConfig('ortb2')).to.be.undefined; - expect(onDataResponse).to.deep.equal({ - data: data, - site: false, - }); - }); - - it('should not set gam targeting with setPrebidTargeting=false but send to bidders', function () { - const moduleConfig = { - params: { - weboUserDataConf: { - setPrebidTargeting: false, - } - } - }; - const data = { - webo_cs: ['foo', 'bar'], - webo_audiences: ['baz'], - }; - - const entry = { - targeting: data, - }; - - sandbox.stub(storage, 'localStorageIsEnabled').returns(true); - sandbox.stub(storage, 'getDataFromLocalStorage') - .withArgs(DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY) - .returns(JSON.stringify(entry)); - - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver', - params: { - target: 'foo=bar' - } - }, { - bidder: 'pubmatic', - params: { - dctr: 'foo=bar' - } - }, { - bidder: 'appnexus', - params: { - keywords: { - foo: ['bar'] - } - } - }, { - bidder: 'rubicon', - params: { - inventory: { - foo: 'bar', - }, - visitor: { - baz: 'bam', - } - } - }, { - bidder: 'other' - }] - }] - }; - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({}); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(5); - expect(reqBidsConfigObj.adUnits[0].bids[0].params.target).to.equal('foo=bar;webo_cs=foo;webo_cs=bar;webo_audiences=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[1].params.dctr).to.equal('foo=bar|webo_cs=foo,bar|webo_audiences=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[2].params.keywords).to.deep.equal({ - foo: ['bar'], - webo_cs: ['foo', 'bar'], - webo_audiences: ['baz'], - }); - expect(reqBidsConfigObj.adUnits[0].bids[3].params).to.deep.equal({ - inventory: { - foo: 'bar', - }, - visitor: { - baz: 'bam', - webo_cs: ['foo', 'bar'], - webo_audiences: ['baz'], - } - }); - expect(reqBidsConfigObj.adUnits[0].bids[4].ortb2).to.deep.equal({ - user: { - ext: { - data: data - }, - } - }); - expect(getGlobal().getConfig('ortb2')).to.deep.equal({ - user: { - ext: { - data: data - }, - } - }); - }); - - it('should use default profile in case of nothing on local storage', function () { - const defaultProfile = { - webo_audiences: ['baz'] - }; - const moduleConfig = { - params: { - weboUserDataConf: { - setPrebidTargeting: true, - defaultProfile: defaultProfile, - } - } - }; - - sandbox.stub(storage, 'localStorageIsEnabled').returns(true); - - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver' - }, { - bidder: 'pubmatic' - }, { - bidder: 'appnexus' - }, { - bidder: 'rubicon' - }, { - bidder: 'other' - }] - }] - }; - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({ - 'adunit1': defaultProfile, - 'adunit2': defaultProfile, - }); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(5); - expect(reqBidsConfigObj.adUnits[0].bids[0].params.target).to.equal('webo_audiences=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[1].params.dctr).to.equal('webo_audiences=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[2].params.keywords).to.deep.equal(defaultProfile); - expect(reqBidsConfigObj.adUnits[0].bids[3].params).to.deep.equal({ - visitor: defaultProfile - }); - expect(reqBidsConfigObj.adUnits[0].bids[4].ortb2).to.deep.equal({ - user: { - ext: { - data: defaultProfile - }, - } - }); - expect(getGlobal().getConfig('ortb2')).to.deep.equal({ - user: { - ext: { - data: defaultProfile - }, - } - }); - }); - - it('should use default profile if cant read from local storage', function () { - const defaultProfile = { - webo_audiences: ['baz'] - }; - let onDataResponse = {}; - const moduleConfig = { - params: { - weboUserDataConf: { - setPrebidTargeting: true, - defaultProfile: defaultProfile, - onData: (data, site) => { - onDataResponse = { - data: data, - site: site, - }; - }, - } - } - }; - - sandbox.stub(storage, 'localStorageIsEnabled').returns(false); - - const adUnitsCodes = ['adunit1', 'adunit2']; - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'smartadserver' - }, { - bidder: 'pubmatic' - }, { - bidder: 'appnexus' - }, { - bidder: 'rubicon' - }, { - bidder: 'other' - }] - }] - }; - const onDoneSpy = sinon.spy(); - - expect(weboramaSubmodule.init(moduleConfig)).to.be.true; - weboramaSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, moduleConfig); - - expect(onDoneSpy.calledOnce).to.be.true; - - const targeting = weboramaSubmodule.getTargetingData(adUnitsCodes, moduleConfig); - - expect(targeting).to.deep.equal({ - 'adunit1': defaultProfile, - 'adunit2': defaultProfile, - }); - - expect(reqBidsConfigObj.adUnits[0].bids.length).to.equal(5); - expect(reqBidsConfigObj.adUnits[0].bids[0].params.target).to.equal('webo_audiences=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[1].params.dctr).to.equal('webo_audiences=baz'); - expect(reqBidsConfigObj.adUnits[0].bids[2].params.keywords).to.deep.equal(defaultProfile); - expect(reqBidsConfigObj.adUnits[0].bids[3].params).to.deep.equal({ - visitor: defaultProfile - }); - expect(reqBidsConfigObj.adUnits[0].bids[4].ortb2).to.deep.equal({ - user: { - ext: { - data: defaultProfile - }, - } - }); - expect(getGlobal().getConfig('ortb2')).to.deep.equal({ - user: { - ext: { - data: defaultProfile - }, - } - }); - expect(onDataResponse).to.deep.equal({ - data: defaultProfile, - site: false, - }); - }); - }); - }); -}); diff --git a/test/spec/modules/welectBidAdapter_spec.js b/test/spec/modules/welectBidAdapter_spec.js deleted file mode 100644 index 2f2af35eaec..00000000000 --- a/test/spec/modules/welectBidAdapter_spec.js +++ /dev/null @@ -1,211 +0,0 @@ -import { expect } from 'chai'; -import { spec as adapter } from 'modules/welectBidAdapter.js'; - -describe('WelectAdapter', function () { - describe('Check methods existance', function () { - it('exists and is a function', function () { - expect(adapter.isBidRequestValid).to.exist.and.to.be.a('function'); - }); - it('exists and is a function', function () { - expect(adapter.buildRequests).to.exist.and.to.be.a('function'); - }); - it('exists and is a function', function () { - expect(adapter.interpretResponse).to.exist.and.to.be.a('function'); - }); - }); - - describe('Check method isBidRequestValid return', function () { - let bid = { - bidder: 'welect', - params: { - placementId: 'exampleAlias', - domain: 'www.welect.de' - }, - sizes: [[640, 360]], - mediaTypes: { - video: { - context: 'instream' - } - }, - }; - let bid2 = { - bidder: 'welect', - params: { - domain: 'www.welect.de' - }, - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 360] - } - }, - }; - - it('should be true', function () { - expect(adapter.isBidRequestValid(bid)).to.be.true; - }); - - it('should be false because the placementId is missing', function () { - expect(adapter.isBidRequestValid(bid2)).to.be.false; - }); - }); - - describe('Check buildRequests method', function () { - // Bids to be formatted - let bid1 = { - bidder: 'welect', - params: { - placementId: 'exampleAlias' - }, - sizes: [[640, 360]], - mediaTypes: { - video: { - context: 'instream' - } - }, - bidId: 'abdc' - }; - let bid2 = { - bidder: 'welect', - params: { - placementId: 'exampleAlias', - domain: 'www.welect2.de' - }, - sizes: [[640, 360]], - mediaTypes: { - video: { - context: 'instream' - } - }, - bidId: 'abdc', - gdprConsent: { - gdprApplies: 1, - gdprConsent: 'some_string' - } - }; - - let data1 = { - bid_id: 'abdc', - width: 640, - height: 360 - } - - let data2 = { - bid_id: 'abdc', - width: 640, - height: 360, - gdpr_consent: { - gdprApplies: 1, - tcString: 'some_string' - } - } - - // Formatted requets - let request1 = { - method: 'POST', - url: 'https://www.welect.de/api/v2/preflight/exampleAlias', - data: data1, - options: { - contentType: 'application/json', - withCredentials: false, - crossOrigin: true, - } - }; - - let request2 = { - method: 'POST', - url: 'https://www.welect2.de/api/v2/preflight/exampleAlias', - data: data2, - options: { - contentType: 'application/json', - withCredentials: false, - crossOrigin: true, - } - } - - it('defaults to www.welect.de, without gdpr object', function () { - expect(adapter.buildRequests([bid1])).to.deep.equal([request1]); - }) - - it('must return the right formatted requests, with gdpr object', function () { - expect(adapter.buildRequests([bid2])).to.deep.equal([request2]); - }); - }); - - describe('Check interpretResponse method return', function () { - // invalid server response - let unavailableResponse = { - body: { - available: false - } - }; - - let availableResponse = { - body: { - available: true, - bidResponse: { - ad: { - video: 'some vast url' - }, - meta: { - advertiserDomains: [], - }, - cpm: 17, - creativeId: 'svmpreview', - currency: 'EUR', - netRevenue: true, - requestId: 'some bid id', - ttl: 120, - vastUrl: 'some vast url', - height: 640, - width: 320 - } - } - } - // bid Request - let bid = { - data: { - bid_id: 'some bid id', - width: 640, - height: 320, - gdpr_consent: { - gdprApplies: 1, - tcString: 'some_string' - } - }, - method: 'POST', - url: 'https://www.welect.de/api/v2/preflight/exampleAlias', - options: { - contentType: 'application/json', - withCredentials: false, - crossOrigin: true, - } - }; - // Formatted reponse - let result = { - ad: { - video: 'some vast url' - }, - meta: { - advertiserDomains: [] - }, - cpm: 17, - creativeId: 'svmpreview', - currency: 'EUR', - height: 640, - netRevenue: true, - requestId: 'some bid id', - ttl: 120, - vastUrl: 'some vast url', - width: 320 - } - - it('if response reflects unavailability, should be empty', function () { - expect(adapter.interpretResponse(unavailableResponse, bid)).to.deep.equal([]); - }); - - it('if response reflects availability, should equal result', function () { - expect(adapter.interpretResponse(availableResponse, bid)).to.deep.equal([result]) - }) - }); -}); diff --git a/test/spec/modules/widespaceBidAdapter_spec.js b/test/spec/modules/widespaceBidAdapter_spec.js index 0a0af1f1229..af8d505b4f4 100644 --- a/test/spec/modules/widespaceBidAdapter_spec.js +++ b/test/spec/modules/widespaceBidAdapter_spec.js @@ -1,6 +1,6 @@ import {expect} from 'chai'; import {spec, storage} from 'modules/widespaceBidAdapter.js'; -import {includes} from 'src/polyfill.js'; +import includes from 'core-js-pure/features/array/includes.js'; describe('+widespaceAdatperTest', function () { // Dummy bid request diff --git a/test/spec/modules/yahoosspBidAdapter_spec.js b/test/spec/modules/yahoosspBidAdapter_spec.js deleted file mode 100644 index e301218741c..00000000000 --- a/test/spec/modules/yahoosspBidAdapter_spec.js +++ /dev/null @@ -1,1377 +0,0 @@ -import { expect } from 'chai'; -import { config } from 'src/config.js'; -import { BANNER, VIDEO } from 'src/mediaTypes.js'; -import { spec } from 'modules/yahoosspBidAdapter.js'; - -const DEFAULT_BID_ID = '84ab500420319d'; -const DEFAULT_BID_DCN = '2093845709823475'; -const DEFAULT_BID_POS = 'header'; -const DEFAULT_PUBID = 'PubId'; -const DEFAULT_AD_UNIT_CODE = '/19968336/header-bid-tag-1'; -const DEFAULT_AD_UNIT_TYPE = 'banner'; -const DEFAULT_PARAMS_BID_OVERRIDE = {}; -const DEFAULT_VIDEO_CONTEXT = 'instream'; -const ADAPTER_VERSION = '1.0.2'; -const PREBID_VERSION = '$prebid.version$'; -const INTEGRATION_METHOD = 'prebid.js'; - -// Utility functions -const generateBidRequest = ({bidId, pos, adUnitCode, adUnitType, bidOverrideObject, videoContext, pubIdMode}) => { - const bidRequest = { - adUnitCode, - auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', - bidId, - bidderRequestsCount: 1, - bidder: 'yahoossp', - bidderRequestId: '7101db09af0db2', - bidderWinsCount: 0, - mediaTypes: {}, - params: { - bidOverride: bidOverrideObject - }, - src: 'client', - transactionId: '5b17b67d-7704-4732-8cc9-5b1723e9bcf9' - }; - - const bannerObj = { - sizes: [[300, 250], [300, 600]] - }; - - const videoObject = { - context: videoContext, - playerSize: [[300, 250]], - mimes: ['video/mp4', 'application/javascript'], - api: [2] - }; - - if (videoContext === 'outstream') { - bidRequest.renderer = undefined - }; - - if (adUnitType === 'banner' || adUnitType === 'dap-o2' || adUnitType === 'dap-up') { - bidRequest.mediaTypes.banner = bannerObj; - bidRequest.sizes = [[300, 250], [300, 600]]; - } else if (adUnitType === 'video') { - bidRequest.mediaTypes.video = videoObject; - } else if (adUnitType === 'multi-format') { - bidRequest.mediaTypes.banner = bannerObj; - bidRequest.sizes = [[300, 250], [300, 600]]; - bidRequest.mediaTypes.video = videoObject; - } else if (adUnitType === 'native') { - bidRequest.mediaTypes.native = {a: 123, b: 456}; - } - - if (pubIdMode === true) { - bidRequest.params.pubId = DEFAULT_PUBID; - } else { - bidRequest.params.dcn = DEFAULT_BID_DCN; - bidRequest.params.pos = pos || DEFAULT_BID_POS; - }; - - return bidRequest; -} - -let generateBidderRequest = (bidRequestArray, adUnitCode) => { - const bidderRequest = { - adUnitCode: adUnitCode || 'default-adUnitCode', - auctionId: 'd4c83a3b-18e4-4208-b98b-63848449c7aa', - auctionStart: new Date().getTime(), - bidderCode: 'yahoossp', - bidderRequestId: '112f1c7c5d399a', - bids: bidRequestArray, - refererInfo: { - referer: 'https://publisher-test.com', - reachedTop: true, - isAmp: false, - numIframes: 0, - stack: ['https://publisher-test.com'], - }, - gdprConsent: { - consentString: 'BOtmiBKOtmiBKABABAENAFAAAAACeAAA', - vendorData: {}, - gdprApplies: true - }, - start: new Date().getTime(), - timeout: 1000, - }; - - return bidderRequest; -}; - -const generateBuildRequestMock = ({bidId, pos, adUnitCode, adUnitType, bidOverrideObject, videoContext, pubIdMode}) => { - const bidRequestConfig = { - bidId: bidId || DEFAULT_BID_ID, - pos: pos || DEFAULT_BID_POS, - adUnitCode: adUnitCode || DEFAULT_AD_UNIT_CODE, - adUnitType: adUnitType || DEFAULT_AD_UNIT_TYPE, - bidOverrideObject: bidOverrideObject || DEFAULT_PARAMS_BID_OVERRIDE, - videoContext: videoContext || DEFAULT_VIDEO_CONTEXT, - pubIdMode: pubIdMode || false - }; - const bidRequest = generateBidRequest(bidRequestConfig); - const validBidRequests = [bidRequest]; - const bidderRequest = generateBidderRequest(validBidRequests, adUnitCode); - - return { bidRequest, validBidRequests, bidderRequest } -}; - -const generateAdmPayload = (admPayloadType) => { - let ADM_PAYLOAD; - switch (admPayloadType) { - case 'banner': - ADM_PAYLOAD = ''; // banner - break; - case 'video': - ADM_PAYLOAD = ''; // VAST xml - break; - case 'multi-format': - const admPayloads = [ - '', // banner - '' // VAST xml - ] - const random = Math.floor(Math.random() * admPayloads.length); - ADM_PAYLOAD = admPayloads[random] - break; - case 'dap-o2': - ADM_PAYLOAD = ''; // O2 player - break; - case 'dap-up': - ADM_PAYLOAD = ''; // Unified Player - break; - }; - return ADM_PAYLOAD; -}; - -const generateResponseMock = (admPayloadType, vastVersion, videoContext) => { - const bidResponse = { - id: 'fc0c35df-21fb-4f93-9ebd-88759dbe31f9', - impid: '274395c06a24e5', - adm: generateAdmPayload(admPayloadType), - price: 1, - w: 300, - h: 250, - crid: 'ssp-placement-name', - adomain: ['advertiser-domain.com'] - }; - - if (vastVersion === 'vast') { - bidResponse.nurl = 'https://yahoo.com?event=adAttempt'; - }; - - const serverResponse = { - body: { - id: 'fc0c35df-21fb-4f93-9ebd-88759dbe31f9', - seatbid: [{ bid: [ bidResponse ], seat: 13107 }] - } - }; - const { validBidRequests, bidderRequest } = generateBuildRequestMock({adUnitType: admPayloadType, videoContext: videoContext}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - - return {serverResponse, data, bidderRequest}; -} - -// Unit tests -describe('YahooSSP Bid Adapter:', () => { - it('PLACEHOLDER TO PASS GULP', () => { - const obj = {}; - expect(obj).to.be.an('object'); - }); - - describe('Validate basic properties', () => { - it('should define the correct bidder code', () => { - expect(spec.code).to.equal('yahoossp') - }); - - it('should define the correct vendor ID', () => { - expect(spec.gvlid).to.equal(25) - }); - }); - - describe('getUserSyncs()', () => { - const IMAGE_PIXEL_URL = 'http://image-pixel.com/foo/bar?1234&baz=true'; - const IFRAME_ONE_URL = 'http://image-iframe.com/foo/bar?1234&baz=true'; - const IFRAME_TWO_URL = 'http://image-iframe-two.com/foo/bar?1234&baz=true'; - - let serverResponses = []; - beforeEach(() => { - serverResponses[0] = { - body: { - ext: { - pixels: `` - } - } - } - }); - - after(() => { - serverResponses = undefined; - }); - - it('for only iframe enabled syncs', () => { - let syncOptions = { - iframeEnabled: true, - pixelEnabled: false - }; - let pixelsObjects = spec.getUserSyncs(syncOptions, serverResponses); - expect(pixelsObjects.length).to.equal(2); - expect(pixelsObjects).to.deep.equal( - [ - {type: 'iframe', 'url': IFRAME_ONE_URL}, - {type: 'iframe', 'url': IFRAME_TWO_URL} - ] - ) - }); - - it('for only pixel enabled syncs', () => { - let syncOptions = { - iframeEnabled: false, - pixelEnabled: true - }; - let pixelsObjects = spec.getUserSyncs(syncOptions, serverResponses); - expect(pixelsObjects.length).to.equal(1); - expect(pixelsObjects).to.deep.equal( - [ - {type: 'image', 'url': IMAGE_PIXEL_URL} - ] - ) - }); - - it('for both pixel and iframe enabled syncs', () => { - let syncOptions = { - iframeEnabled: true, - pixelEnabled: true - }; - let pixelsObjects = spec.getUserSyncs(syncOptions, serverResponses); - expect(pixelsObjects.length).to.equal(3); - expect(pixelsObjects).to.deep.equal( - [ - {type: 'iframe', 'url': IFRAME_ONE_URL}, - {type: 'image', 'url': IMAGE_PIXEL_URL}, - {type: 'iframe', 'url': IFRAME_TWO_URL} - ] - ) - }); - }); - - // Validate Bid Requests - describe('isBidRequestValid()', () => { - const INVALID_INPUT = [ - {}, - {params: {}}, - {params: {dcn: '2c9d2b50015a5aa95b70a9b0b5b10012'}}, - {params: {dcn: 1234, pos: 'header'}}, - {params: {dcn: '2c9d2b50015a5aa95b70a9b0b5b10012', pos: 1234}}, - {params: {dcn: '2c9d2b50015a5aa95b70a9b0b5b10012', pos: ''}}, - {params: {dcn: '', pos: 'header'}}, - ]; - - INVALID_INPUT.forEach(input => { - it(`should determine that the bid is INVALID for the input ${JSON.stringify(input)}`, () => { - expect(spec.isBidRequestValid(input)).to.be.false; - }); - }); - - it('should determine that the bid is VALID if dcn and pos are present on the params object', () => { - const validBid = { - params: { - dcn: '2c9d2b50015a5aa95b70a9b0b5b10012', - pos: 'header' - } - }; - expect(spec.isBidRequestValid(validBid)).to.be.true; - }); - - it('should mark bid as VALID if bid.params.testing.e2etest = "true" (dcn & pos not required)', () => { - const validBid = { - params: { - dcn: 8888, - pos: 9999, - testing: { - e2etest: true - } - } - }; - expect(spec.isBidRequestValid(validBid)).to.be.true; - }); - - it('should mark bid ad VALID if pubId exists instead of dcn & pos', () => { - const validBid = { - params: { - pubId: DEFAULT_PUBID - } - }; - expect(spec.isBidRequestValid(validBid)).to.be.true; - }); - }); - - describe('Price Floor module support:', () => { - it('should get bidfloor from getFloor method', () => { - const { bidRequest, validBidRequests, bidderRequest } = generateBuildRequestMock({}); - bidRequest.params.bidOverride = {cur: 'EUR'}; - bidRequest.getFloor = (floorObj) => { - return { - floor: bidRequest.floors.values[floorObj.mediaType + '|640x480'], - currency: floorObj.currency, - mediaType: floorObj.mediaType - } - }; - bidRequest.floors = { - currency: 'EUR', - values: { - 'banner|640x480': 5.55 - } - }; - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.cur).to.deep.equal(['EUR']); - expect(data.imp[0].bidfloor).is.a('number'); - expect(data.imp[0].bidfloor).to.equal(5.55); - }); - }); - - describe('Schain module support:', () => { - it('should send Global or Bidder specific schain', function () { - const { bidRequest, validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const globalSchain = { - ver: '1.0', - complete: 1, - nodes: [{ - asi: 'some-platform.com', - sid: '111111', - rid: bidRequest.bidId, - hp: 1 - }] - }; - bidRequest.schain = globalSchain; - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - const schain = data.source.ext.schain; - expect(schain.nodes.length).to.equal(1); - expect(schain).to.equal(globalSchain); - }); - }); - - describe('First party data module - "Site" support (ortb2):', () => { - // Should not allow invalid "site" data types - const INVALID_ORTB2_TYPES = [ null, [], 123, 'unsupportedKeyName', true, false, undefined ]; - INVALID_ORTB2_TYPES.forEach(param => { - const ortb2 = { site: param } - config.setConfig({ortb2}); - it(`should not allow invalid site types to be added to bid-request: ${JSON.stringify(param)}`, () => { - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.site[param]).to.be.undefined; - }); - }); - - // Should add valid "site" params - const VALID_SITE_STRINGS = ['name', 'domain', 'page', 'ref', 'keywords', 'search']; - const VALID_SITE_ARRAYS = ['cat', 'sectioncat', 'pagecat']; - - VALID_SITE_STRINGS.forEach(param => { - it(`should allow supported site keys to be added bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - site: { - [param]: 'something' - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.site[param]).to.exist; - expect(data.site[param]).to.be.a('string'); - expect(data.site[param]).to.be.equal(ortb2.site[param]); - }); - }); - - VALID_SITE_ARRAYS.forEach(param => { - it(`should determine that the ortb2.site Array key is valid and append to the bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - site: { - [param]: ['something'] - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.site[param]).to.exist; - expect(data.site[param]).to.be.a('array'); - expect(data.site[param]).to.be.equal(ortb2.site[param]); - }); - }); - - // Should not allow invalid "site.content" data types - INVALID_ORTB2_TYPES.forEach(param => { - it(`should determine that the ortb2.site.content key is invalid and should not be added to bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - site: { - content: param - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.site.content).to.be.undefined; - }); - }); - - // Should not allow invalid "site.content" keys - it(`should not allow invalid ortb2.site.content object keys to be added to bid-request: {custom object}`, () => { - const ortb2 = { - site: { - content: { - fake: 'news', - unreal: 'param', - counterfit: 'data' - } - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.site.content).to.be.a('object'); - }); - - // Should append valid "site.content" keys - const VALID_CONTENT_STRINGS = ['id', 'title', 'series', 'season', 'genre', 'contentrating', 'language']; - VALID_CONTENT_STRINGS.forEach(param => { - it(`should determine that the ortb2.site String key is valid and append to the bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - site: { - content: { - [param]: 'something' - } - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.site.content[param]).to.exist; - expect(data.site.content[param]).to.be.a('string'); - expect(data.site.content[param]).to.be.equal(ortb2.site.content[param]); - }); - }); - - const VALID_CONTENT_NUMBERS = ['episode', 'prodq', 'context', 'livestream', 'len']; - VALID_CONTENT_NUMBERS.forEach(param => { - it(`should determine that the ortb2.site.content Number key is valid and append to the bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - site: { - content: { - [param]: 1234 - } - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.site.content[param]).to.be.a('number'); - expect(data.site.content[param]).to.be.equal(ortb2.site.content[param]); - }); - }); - - const VALID_CONTENT_ARRAYS = ['cat']; - VALID_CONTENT_ARRAYS.forEach(param => { - it(`should determine that the ortb2.site Array key is valid and append to the bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - site: { - content: { - [param]: ['something', 'something-else'] - } - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.site.content[param]).to.be.a('array'); - expect(data.site.content[param]).to.be.equal(ortb2.site.content[param]); - }); - }); - - const VALID_CONTENT_OBJECTS = ['ext']; - VALID_CONTENT_OBJECTS.forEach(param => { - it(`should determine that the ortb2.site.content Object key is valid and append to the bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - site: { - content: { - [param]: {a: '123', b: '456'} - } - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.site.content[param]).to.be.a('object'); - expect(data.site.content[param]).to.be.equal(ortb2.site.content[param]); - config.setConfig({ortb2: {}}); - }); - }); - }); - - describe('First party data module - "User" support (ortb2):', () => { - // Global ortb2.user validations - // Should not allow invalid "user" data types - const INVALID_ORTB2_TYPES = [ null, [], 'unsupportedKeyName', true, false, undefined ]; - INVALID_ORTB2_TYPES.forEach(param => { - const ortb2 = { user: param } - config.setConfig({ortb2}); - it(`should not allow invalid site types to be added to bid-request: ${JSON.stringify(param)}`, () => { - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.user[param]).to.be.undefined; - }); - }); - - // Should add valid "user" params - const VALID_USER_STRINGS = ['id', 'buyeruid', 'gender', 'keywords', 'customdata']; - VALID_USER_STRINGS.forEach(param => { - it(`should allow supported user string keys to be added bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - user: { - [param]: 'something' - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.user[param]).to.exist; - expect(data.user[param]).to.be.a('string'); - expect(data.user[param]).to.be.equal(ortb2.user[param]); - }); - }); - - const VALID_USER_NUMBERS = ['yob']; - VALID_USER_NUMBERS.forEach(param => { - it(`should allow supported user number keys to be added bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - user: { - [param]: 1982 - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.user[param]).to.exist; - expect(data.user[param]).to.be.a('number'); - expect(data.user[param]).to.be.equal(ortb2.user[param]); - }); - }); - - const VALID_USER_ARRAYS = ['data']; - VALID_USER_ARRAYS.forEach(param => { - it(`should allow supported user Array keys to be added to the bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - user: { - [param]: ['something'] - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.user[param]).to.exist; - expect(data.user[param]).to.be.a('array'); - expect(data.user[param]).to.be.equal(ortb2.user[param]); - }); - }); - - const VALID_USER_OBJECTS = ['ext']; - VALID_USER_OBJECTS.forEach(param => { - it(`should allow supported user extObject keys to be added to the bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - user: { - [param]: {a: '123', b: '456'} - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.user[param]).to.be.a('object'); - expect(data.user[param]).to.be.deep.include({[param]: {a: '123', b: '456'}}); - config.setConfig({ortb2: {}}); - }); - }); - - // Should allow valid user.data && site.content.data - const VALID_USER_DATA_STRINGS = ['id', 'name']; - VALID_USER_DATA_STRINGS.forEach(param => { - it(`should allow supported user.data & site.content.data strings to be added to the bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - user: { - data: [{[param]: 'string'}] - }, - site: { - content: { - data: [{[param]: 'string'}] - } - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.user.data[0][param]).to.exist; - expect(data.user.data[0][param]).to.be.a('string'); - expect(data.user.data[0][param]).to.be.equal(ortb2.user.data[0][param]); - expect(data.site.content.data[0][param]).to.exist; - expect(data.site.content.data[0][param]).to.be.a('string'); - expect(data.site.content.data[0][param]).to.be.equal(ortb2.site.content.data[0][param]); - }); - }); - - const VALID_USER_DATA_ARRAYS = ['segment'] - VALID_USER_DATA_ARRAYS.forEach(param => { - it(`should allow supported user data arrays to be added to the bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - user: { - data: [{[param]: [{id: 1}]}] - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.user.data[0][param]).to.exist; - expect(data.user.data[0][param]).to.be.a('array'); - expect(data.user.data[0][param]).to.be.equal(ortb2.user.data[0][param]); - }); - }); - - const VALID_USER_DATA_OBJECTS = ['ext']; - VALID_USER_DATA_OBJECTS.forEach(param => { - it(`should allow supported user data objects to be added to the bid-request: ${JSON.stringify(param)}`, () => { - const ortb2 = { - user: { - data: [{[param]: {id: 'ext'}}] - } - }; - config.setConfig({ortb2}); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.user.data[0][param]).to.exist; - expect(data.user.data[0][param]).to.be.a('object'); - expect(data.user.data[0][param]).to.be.equal(ortb2.user.data[0][param]); - config.setConfig({ortb2: {}}); - }); - }); - - // adUnit.ortb2Imp.ext.data - it(`should allow adUnit.ortb2Imp.ext.data object to be added to the bid-request`, () => { - let { validBidRequests, bidderRequest } = generateBuildRequestMock({}) - validBidRequests[0].ortb2Imp = { - ext: { - data: { - pbadslot: 'homepage-top-rect', - adUnitSpecificAttribute: '123' - } - } - }; - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.imp[0].ext.data).to.deep.equal(validBidRequests[0].ortb2Imp.ext.data); - }); - // adUnit.ortb2Imp.instl - it(`should allow adUnit.ortb2Imp.instl numeric boolean "1" to be added to the bid-request`, () => { - let { validBidRequests, bidderRequest } = generateBuildRequestMock({}) - validBidRequests[0].ortb2Imp = { - instl: 1 - }; - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.imp[0].instl).to.deep.equal(validBidRequests[0].ortb2Imp.instl); - }); - - it(`should prevent adUnit.ortb2Imp.instl boolean "true" to be added to the bid-request`, () => { - let { validBidRequests, bidderRequest } = generateBuildRequestMock({}) - validBidRequests[0].ortb2Imp = { - instl: true - }; - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.imp[0].instl).to.not.exist; - }); - - it(`should prevent adUnit.ortb2Imp.instl boolean "false" to be added to the bid-request`, () => { - let { validBidRequests, bidderRequest } = generateBuildRequestMock({}) - validBidRequests[0].ortb2Imp = { - instl: false - }; - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.imp[0].instl).to.not.exist; - }); - }); - - describe('e2etest mode support:', () => { - it(`should override DCN & POS when params.testing.e2etest = "true".`, () => { - const { bidRequest, validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const params = { - dcn: '1234', - pos: '5678', - testing: { - e2etest: true - } - } - bidRequest.params = params; - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.site.id).to.be.equal('8a969516017a7a396ec539d97f540011'); - expect(data.imp[0].tagid).to.be.equal('8a969978017a7aaabab4ab0bc01a0009'); - expect(data.imp[0].ext.e2eTestMode).to.be.true; - }); - }); - - describe('GDPR & Consent:', () => { - it('should return request objects that do not send cookies if purpose 1 consent is not provided', () => { - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - bidderRequest.gdprConsent = { - consentString: 'BOtmiBKOtmiBKABABAENAFAAAAACeAAA', - apiVersion: 2, - vendorData: { - purpose: { - consents: { - '1': false - } - } - }, - gdprApplies: true - }; - const options = spec.buildRequests(validBidRequests, bidderRequest)[0].options; - expect(options.withCredentials).to.be.false; - }); - }); - - describe('Endpoint & Impression Request Mode:', () => { - it('should route request to config override endpoint', () => { - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const testOverrideEndpoint = 'http://foo.bar.baz.com/bidderRequest'; - config.setConfig({ - yahoossp: { - endpoint: testOverrideEndpoint - } - }); - const response = spec.buildRequests(validBidRequests, bidderRequest)[0]; - expect(response).to.deep.include( - { - method: 'POST', - url: testOverrideEndpoint - }); - }); - - it('should route request to /bidRequest endpoint when dcn & pos present', () => { - config.setConfig({ - yahoossp: {} - }); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const response = spec.buildRequests(validBidRequests, bidderRequest); - expect(response[0]).to.deep.include({ - method: 'POST', - url: 'https://c2shb.pubgw.yahoo.com/bidRequest' - }); - }); - - it('should route request to /partners endpoint when pubId is present', () => { - const { validBidRequests, bidderRequest } = generateBuildRequestMock({pubIdMode: true}); - const response = spec.buildRequests(validBidRequests, bidderRequest); - expect(response[0]).to.deep.include({ - method: 'POST', - url: 'https://c2shb.pubgw.yahoo.com/admax/bid/partners/PBJS' - }); - }); - - it('should return a single request object for single request mode', () => { - let { bidRequest, validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const BID_ID_2 = '84ab50xxxxx'; - const BID_POS_2 = 'footer'; - const AD_UNIT_CODE_2 = 'test-ad-unit-code-123'; - const { bidRequest: bidRequest2 } = generateBuildRequestMock({bidId: BID_ID_2, pos: BID_POS_2, adUnitCode: AD_UNIT_CODE_2}); - validBidRequests = [bidRequest, bidRequest2]; - bidderRequest.bids = validBidRequests; - - config.setConfig({ - yahoossp: { - singleRequestMode: true - } - }); - - const data = spec.buildRequests(validBidRequests, bidderRequest).data; - expect(data.imp).to.be.an('array').with.lengthOf(2); - - expect(data.imp[0]).to.deep.include({ - id: DEFAULT_BID_ID, - ext: { - pos: DEFAULT_BID_POS, - dfp_ad_unit_code: DEFAULT_AD_UNIT_CODE - } - }); - - expect(data.imp[1]).to.deep.include({ - id: BID_ID_2, - ext: { - pos: BID_POS_2, - dfp_ad_unit_code: AD_UNIT_CODE_2 - } - }); - }); - }); - - describe('Validate request filtering:', () => { - it('should not return request when no bids are present', function () { - let request = spec.buildRequests([]); - expect(request).to.be.undefined; - }); - - it('buildRequests(): should return an array with the correct amount of request objects', () => { - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const response = spec.buildRequests(validBidRequests, bidderRequest).bidderRequest; - expect(response.bids).to.be.an('array').to.have.lengthOf(1); - }); - }); - - describe('Request Headers validation:', () => { - it('should return request objects with the relevant custom headers and content type declaration', () => { - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const options = spec.buildRequests(validBidRequests, bidderRequest).options; - expect(options).to.deep.equal( - { - contentType: 'application/json', - customHeaders: { - 'x-openrtb-version': '2.5' - }, - withCredentials: true - }); - }); - }); - - describe('Request Payload oRTB bid validation:', () => { - it('should generate a valid openRTB bid-request object in the data field', () => { - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest).data; - expect(data.site).to.deep.equal({ - id: bidderRequest.bids[0].params.dcn, - page: bidderRequest.refererInfo.referer - }); - - expect(data.device).to.deep.equal({ - dnt: 0, - ua: navigator.userAgent, - ip: undefined - }); - - expect(data.regs).to.deep.equal({ - ext: { - 'us_privacy': '', - gdpr: 1 - } - }); - - expect(data.source).to.deep.equal({ - ext: { - hb: 1, - adapterver: ADAPTER_VERSION, - prebidver: PREBID_VERSION, - integration: { - name: INTEGRATION_METHOD, - ver: PREBID_VERSION - } - }, - fd: 1 - }); - - expect(data.user).to.deep.equal({ - ext: { - consent: bidderRequest.gdprConsent.consentString, - eids: [] - } - }); - - expect(data.cur).to.deep.equal(['USD']); - }); - - it('should generate a valid openRTB imp.ext object in the bid-request', () => { - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const bid = validBidRequests[0]; - const data = spec.buildRequests(validBidRequests, bidderRequest).data; - expect(data.imp[0].ext).to.deep.equal({ - pos: bid.params.pos, - dfp_ad_unit_code: DEFAULT_AD_UNIT_CODE - }); - }); - - it('should use siteId value as site.id in the outbound bid-request when using "pubId" integration mode', () => { - let { validBidRequests, bidderRequest } = generateBuildRequestMock({pubIdMode: true}); - validBidRequests[0].params.siteId = '1234567'; - const data = spec.buildRequests(validBidRequests, bidderRequest).data; - expect(data.site.id).to.equal('1234567'); - }); - - it('should use placementId value as imp.tagid in the outbound bid-request when using "pubId" integration mode', () => { - let { validBidRequests, bidderRequest } = generateBuildRequestMock({pubIdMode: true}); - validBidRequests[0].params.placementId = 'header-300x250'; - const data = spec.buildRequests(validBidRequests, bidderRequest).data; - expect(data.imp[0].tagid).to.deep.equal('header-300x250'); - }); - }); - - describe('Request Payload oRTB bid.imp validation:', () => { - // Validate Banner imp imp when yahoossp.mode=undefined - it('should generate a valid "Banner" imp object', () => { - config.setConfig({ - yahoossp: {} - }); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.imp[0].video).to.not.exist; - expect(data.imp[0].banner).to.deep.equal({ - mimes: ['text/html', 'text/javascript', 'application/javascript', 'image/jpg'], - format: [{w: 300, h: 250}, {w: 300, h: 600}] - }); - }); - - // Validate Banner imp when yahoossp.mode="banner" - it('should generate a valid "Banner" imp object', () => { - config.setConfig({ - yahoossp: { mode: 'banner' } - }); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.imp[0].video).to.not.exist; - expect(data.imp[0].banner).to.deep.equal({ - mimes: ['text/html', 'text/javascript', 'application/javascript', 'image/jpg'], - format: [{w: 300, h: 250}, {w: 300, h: 600}] - }); - }); - - // Validate Video imp - it('should generate a valid "Video" only imp object', () => { - config.setConfig({ - yahoossp: { mode: 'video' } - }); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({adUnitType: 'video'}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.imp[0].banner).to.not.exist; - expect(data.imp[0].video).to.deep.equal({ - mimes: ['video/mp4', 'application/javascript'], - w: 300, - h: 250, - api: [2], - protocols: [2, 5], - startdelay: 0, - linearity: 1, - maxbitrate: undefined, - maxduration: undefined, - minduration: undefined, - delivery: undefined, - pos: undefined, - playbackmethod: undefined, - rewarded: undefined, - placement: undefined - }); - }); - - // Validate multi-format Video+banner imp - it('should generate a valid multi-format "Video + Banner" imp object', () => { - config.setConfig({ - yahoossp: { mode: 'all' } - }); - const { validBidRequests, bidderRequest } = generateBuildRequestMock({adUnitType: 'multi-format'}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.imp[0].banner).to.deep.equal({ - mimes: ['text/html', 'text/javascript', 'application/javascript', 'image/jpg'], - format: [{w: 300, h: 250}, {w: 300, h: 600}] - }); - expect(data.imp[0].video).to.deep.equal({ - mimes: ['video/mp4', 'application/javascript'], - w: 300, - h: 250, - api: [2], - protocols: [2, 5], - startdelay: 0, - linearity: 1, - maxbitrate: undefined, - maxduration: undefined, - minduration: undefined, - delivery: undefined, - pos: undefined, - playbackmethod: undefined, - rewarded: undefined, - placement: undefined - }); - }); - - // Validate Key-Value Pairs - it('should generate supported String, Number, Array of Strings, Array of Numbers key-value pairs and append to imp.ext.kvs', () => { - let { validBidRequests, bidderRequest } = generateBuildRequestMock({}) - validBidRequests[0].params.kvp = { - key1: 'String', - key2: 123456, - key3: ['String', 'String', 'String'], - key4: [1, 2, 3], - invalidKey1: true, - invalidKey2: null, - invalidKey3: ['string', 1234], - invalidKey4: {a: 1, b: 2}, - invalidKey5: undefined - }; - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - - expect(data.imp[0].ext.kvs).to.deep.equal({ - key1: 'String', - key2: 123456, - key3: ['String', 'String', 'String'], - key4: [1, 2, 3] - }); - }); - }); - - describe('Multiple adUnit validations:', () => { - // Multiple banner adUnits - it('should generate multiple bid-requests for each adUnit - 2 banner only', () => { - config.setConfig({ - yahoossp: { mode: 'banner' } - }); - - const BID_ID_2 = '84ab50xxxxx'; - const BID_POS_2 = 'footer'; - const AD_UNIT_CODE_2 = 'test-ad-unit-code-123'; - const BID_ID_3 = '84ab50yyyyy'; - const BID_POS_3 = 'hero'; - const AD_UNIT_CODE_3 = 'video-ad-unit'; - - let { bidRequest, validBidRequests, bidderRequest } = generateBuildRequestMock({}); // banner - const { bidRequest: bidRequest2 } = generateBuildRequestMock({bidId: BID_ID_2, pos: BID_POS_2, adUnitCode: AD_UNIT_CODE_2}); // banner - const { bidRequest: bidRequest3 } = generateBuildRequestMock({bidId: BID_ID_3, pos: BID_POS_3, adUnitCode: AD_UNIT_CODE_3, adUnitType: 'video'}); // video (should be filtered) - validBidRequests = [bidRequest, bidRequest2, bidRequest3]; - bidderRequest.bids = validBidRequests; - - const response = spec.buildRequests(validBidRequests, bidderRequest) - expect(response).to.be.a('array'); - expect(response.length).to.equal(2); - response.forEach((obj) => { - expect(obj.data.imp[0].video).to.not.exist - expect(obj.data.imp[0].banner).to.deep.equal({ - mimes: ['text/html', 'text/javascript', 'application/javascript', 'image/jpg'], - format: [{w: 300, h: 250}, {w: 300, h: 600}] - }); - }); - }); - - // Multiple video adUnits - it('should generate multiple bid-requests for each adUnit - 2 video only', () => { - config.setConfig({ - yahoossp: { mode: 'video' } - }); - const BID_ID_2 = '84ab50xxxxx'; - const BID_POS_2 = 'footer'; - const AD_UNIT_CODE_2 = 'test-ad-unit-code-123'; - const BID_ID_3 = '84ab50yyyyy'; - const BID_POS_3 = 'hero'; - const AD_UNIT_CODE_3 = 'video-ad-unit'; - - let { bidRequest, validBidRequests, bidderRequest } = generateBuildRequestMock({adUnitType: 'video'}); // video - const { bidRequest: bidRequest2 } = generateBuildRequestMock({bidId: BID_ID_2, pos: BID_POS_2, adUnitCode: AD_UNIT_CODE_2, adUnitType: 'video'}); // video - const { bidRequest: bidRequest3 } = generateBuildRequestMock({bidId: BID_ID_3, pos: BID_POS_3, adUnitCode: AD_UNIT_CODE_3}); // banner (should be filtered) - validBidRequests = [bidRequest, bidRequest2, bidRequest3]; - bidderRequest.bids = validBidRequests; - - const response = spec.buildRequests(validBidRequests, bidderRequest) - expect(response).to.be.a('array'); - expect(response.length).to.equal(2); - response.forEach((obj) => { - expect(obj.data.imp[0].banner).to.not.exist - expect(obj.data.imp[0].video).to.deep.equal({ - mimes: ['video/mp4', 'application/javascript'], - w: 300, - h: 250, - api: [2], - protocols: [2, 5], - startdelay: 0, - linearity: 1, - maxbitrate: undefined, - maxduration: undefined, - minduration: undefined, - delivery: undefined, - pos: undefined, - playbackmethod: undefined, - rewarded: undefined, - placement: undefined - }); - }); - }); - // Mixed adUnits 1-banner, 1-video, 1-native (should filter out native) - it('should generate multiple bid-requests for both "video & banner" adUnits', () => { - config.setConfig({ - yahoossp: { mode: 'all' } - }); - const BID_ID_2 = '84ab50xxxxx'; - const BID_POS_2 = 'footer'; - const AD_UNIT_CODE_2 = 'video-ad-unit'; - const BID_ID_3 = '84ab50yyyyy'; - const BID_POS_3 = 'hero'; - const AD_UNIT_CODE_3 = 'native-ad-unit'; - - let { bidRequest, validBidRequests, bidderRequest } = generateBuildRequestMock({adUnitType: 'banner'}); // banner - const { bidRequest: bidRequest2 } = generateBuildRequestMock({bidId: BID_ID_2, pos: BID_POS_2, adUnitCode: AD_UNIT_CODE_2, adUnitType: 'video'}); // video - const { bidRequest: bidRequest3 } = generateBuildRequestMock({bidId: BID_ID_3, pos: BID_POS_3, adUnitCode: AD_UNIT_CODE_3, adUnitType: 'native'}); // native (should be filtered) - validBidRequests = [bidRequest, bidRequest2, bidRequest3]; - bidderRequest.bids = validBidRequests; - - const response = spec.buildRequests(validBidRequests, bidderRequest); - expect(response).to.be.a('array'); - expect(response.length).to.equal(2); - response.forEach((obj) => { - expect(obj.data.imp[0].native).to.not.exist; - }); - - const data1 = response[0].data; - expect(data1.imp[0].video).to.not.exist; - expect(data1.imp[0].banner).to.deep.equal({ - mimes: ['text/html', 'text/javascript', 'application/javascript', 'image/jpg'], - format: [{w: 300, h: 250}, {w: 300, h: 600}] - }); - - const data2 = response[1].data; - expect(data2.imp[0].banner).to.not.exist; - expect(data2.imp[0].video).to.deep.equal({ - mimes: ['video/mp4', 'application/javascript'], - w: 300, - h: 250, - api: [2], - protocols: [2, 5], - startdelay: 0, - linearity: 1, - maxbitrate: undefined, - maxduration: undefined, - minduration: undefined, - delivery: undefined, - pos: undefined, - playbackmethod: undefined, - rewarded: undefined, - placement: undefined - }); - }); - }); - - describe('Video params firstlook & bidOverride validations:', () => { - it('should first look at params.bidOverride for video placement data', () => { - config.setConfig({ - yahoossp: { mode: 'video' } - }); - const bidOverride = { - imp: { - video: { - mimes: ['video/mp4'], - w: 400, - h: 350, - api: [1], - protocols: [1, 3], - startdelay: 0, - linearity: 1, - maxbitrate: 400000, - maxduration: 3600, - minduration: 1500, - delivery: 1, - pos: 123456, - playbackmethod: 1, - rewarded: 1, - placement: 1 - } - } - } - const { validBidRequests, bidderRequest } = generateBuildRequestMock({adUnitType: 'video', bidOverrideObject: bidOverride}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.imp[0].video).to.deep.equal(bidOverride.imp.video); - }); - - it('should second look at bid.mediaTypes.video for video placement data', () => { - config.setConfig({ - yahoossp: { mode: 'video' } - }); - let { bidRequest, bidderRequest } = generateBuildRequestMock({adUnitType: 'video'}); - bidRequest.mediaTypes.video = { - mimes: ['video/mp4'], - playerSize: [400, 350], - api: [1], - protocols: [1, 3], - startdelay: 0, - linearity: 1, - maxbitrate: 400000, - maxduration: 3600, - minduration: 1500, - delivery: 1, - pos: 123456, - playbackmethod: 1, - placement: 1 - } - const validBidRequests = [bidRequest]; - bidderRequest.bids = validBidRequests; - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.imp[0].video).to.deep.equal({ - mimes: ['video/mp4'], - w: 400, - h: 350, - api: [1], - protocols: [1, 3], - startdelay: 0, - linearity: 1, - maxbitrate: 400000, - maxduration: 3600, - minduration: 1500, - delivery: 1, - pos: 123456, - playbackmethod: 1, - placement: 1, - rewarded: undefined - }); - }); - - it('should use params.bidOverride.device.ip override', () => { - config.setConfig({ - yahoossp: { mode: 'all' } - }); - const bidOverride = { - device: { - ip: '1.2.3.4' - } - } - const { validBidRequests, bidderRequest } = generateBuildRequestMock({adUnitType: 'video', bidOverrideObject: bidOverride}); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - expect(data.device.ip).to.deep.equal(bidOverride.device.ip); - }); - }); - // #endregion buildRequests(): - - describe('interpretResponse()', () => { - describe('for mediaTypes: "banner"', () => { - it('should insert banner payload into response[0].ad', () => { - const { serverResponse, bidderRequest } = generateResponseMock('banner'); - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].ad).to.equal(''); - expect(response[0].mediaType).to.equal('banner'); - }) - }); - - describe('for mediaTypes: "video"', () => { - it('should insert video VPAID payload into vastXml', () => { - const { serverResponse, bidderRequest } = generateResponseMock('video'); - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].ad).to.be.undefined; - expect(response[0].vastXml).to.equal(''); - expect(response[0].mediaType).to.equal('video'); - }) - - it('should insert video VAST win notification into vastUrl', () => { - const { serverResponse, bidderRequest } = generateResponseMock('video', 'vast'); - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].ad).to.be.undefined; - expect(response[0].vastUrl).to.equal('https://yahoo.com?event=adAttempt'); - expect(response[0].vastXml).to.equal(''); - expect(response[0].mediaType).to.equal('video'); - }) - - it('should insert video DAP O2 Player into ad', () => { - const { serverResponse, bidderRequest } = generateResponseMock('dap-o2', 'vpaid'); - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].ad).to.equal(''); - expect(response[0].vastUrl).to.be.undefined; - expect(response[0].vastXml).to.be.undefined; - expect(response[0].mediaType).to.equal('banner'); - }); - - it('should insert video DAP Unified Player into ad', () => { - const { serverResponse, bidderRequest } = generateResponseMock('dap-up', 'vpaid'); - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].ad).to.equal(''); - expect(response[0].vastUrl).to.be.undefined; - expect(response[0].vastXml).to.be.undefined; - expect(response[0].mediaType).to.equal('banner'); - }) - }); - - describe('Support Advertiser domains', () => { - it('should append bid-response adomain to meta.advertiserDomains', () => { - const { serverResponse, bidderRequest } = generateResponseMock('video', 'vpaid'); - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].meta.advertiserDomains).to.be.a('array'); - expect(response[0].meta.advertiserDomains[0]).to.equal('advertiser-domain.com'); - }) - }); - - describe('bid response Ad ID / Creative ID', () => { - it('should use adId if it exists in the bid-response', () => { - const { serverResponse, bidderRequest } = generateResponseMock('banner'); - const adId = 'bid-response-adId'; - serverResponse.body.seatbid[0].bid[0].adId = adId; - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].adId).to.equal(adId); - }); - - it('should use impid if adId does not exist in the bid-response', () => { - const { serverResponse, bidderRequest } = generateResponseMock('banner'); - const impid = '25b6c429c1f52f'; - serverResponse.body.seatbid[0].bid[0].impid = impid; - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].adId).to.equal(impid); - }); - - it('should use crid if adId & impid do not exist in the bid-response', () => { - const { serverResponse, bidderRequest } = generateResponseMock('banner'); - const crid = 'passback-12579'; - serverResponse.body.seatbid[0].bid[0].impid = undefined; - serverResponse.body.seatbid[0].bid[0].crid = crid; - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].adId).to.equal(crid); - }); - }); - - describe('Time To Live (ttl)', () => { - const UNSUPPORTED_TTL_FORMATS = ['string', [1, 2, 3], true, false, null, undefined]; - UNSUPPORTED_TTL_FORMATS.forEach(param => { - it('should not allow unsupported global yahoossp.ttl formats and default to 300', () => { - const { serverResponse, bidderRequest } = generateResponseMock('banner'); - config.setConfig({ - yahoossp: { ttl: param } - }); - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].ttl).to.equal(300); - }); - - it('should not allow unsupported params.ttl formats and default to 300', () => { - const { serverResponse, bidderRequest } = generateResponseMock('banner'); - bidderRequest.bids[0].params.ttl = param; - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].ttl).to.equal(300); - }); - }); - - const UNSUPPORTED_TTL_VALUES = [-1, 3601]; - UNSUPPORTED_TTL_VALUES.forEach(param => { - it('should not allow invalid global yahoossp.ttl values 3600 < ttl < 0 and default to 300', () => { - const { serverResponse, bidderRequest } = generateResponseMock('banner'); - config.setConfig({ - yahoossp: { ttl: param } - }); - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].ttl).to.equal(300); - }); - - it('should not allow invalid params.ttl values 3600 < ttl < 0 and default to 300', () => { - const { serverResponse, bidderRequest } = generateResponseMock('banner'); - bidderRequest.bids[0].params.ttl = param; - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].ttl).to.equal(300); - }); - }); - - it('should give presedence to Gloabl ttl over params.ttl ', () => { - const { serverResponse, bidderRequest } = generateResponseMock('banner'); - config.setConfig({ - yahoossp: { ttl: 500 } - }); - bidderRequest.bids[0].params.ttl = 400; - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].ttl).to.equal(500); - }); - }); - - describe('Aliasing support', () => { - it('should return undefined as the bidder code value', () => { - const { serverResponse, bidderRequest } = generateResponseMock('banner'); - const response = spec.interpretResponse(serverResponse, {bidderRequest}); - expect(response[0].bidderCode).to.be.undefined; - }); - }); - }); -}); diff --git a/test/spec/modules/yandexBidAdapter_spec.js b/test/spec/modules/yandexBidAdapter_spec.js deleted file mode 100644 index 833f883fb7c..00000000000 --- a/test/spec/modules/yandexBidAdapter_spec.js +++ /dev/null @@ -1,166 +0,0 @@ -import {assert, expect} from 'chai'; -import {spec} from 'modules/yandexBidAdapter.js'; -import {parseUrl} from 'src/utils.js'; -import {BANNER} from '../../../src/mediaTypes'; - -describe('Yandex adapter', function () { - function getBidConfig() { - return { - bidder: 'yandex', - params: { - pageId: 123, - impId: 1, - }, - }; - } - - function getBidRequest() { - return { - ...getBidConfig(), - bidId: 'bidid-1', - adUnitCode: 'adUnit-123', - mediaTypes: { - banner: { - sizes: [ - [300, 250], - [300, 600] - ], - }, - }, - }; - } - - describe('isBidRequestValid', function () { - it('should return true when required params found', function () { - const bid = getBidConfig(); - assert(spec.isBidRequestValid(bid)); - }); - - it('should return false when required params not found', function () { - expect(spec.isBidRequestValid({})).to.be.false; - }); - - it('should return false when required params.pageId are not passed', function () { - const bid = getBidConfig(); - delete bid.params.pageId; - - expect(spec.isBidRequestValid(bid)).to.be.false - }); - - it('should return false when required params.impId are not passed', function () { - const bid = getBidConfig(); - delete bid.params.impId; - - expect(spec.isBidRequestValid(bid)).to.be.false - }); - }); - - describe('buildRequests', function () { - const refererUrl = 'https://yandex.ru/secure-ads'; - - const gdprConsent = { - gdprApplies: 1, - consentString: 'concent-string', - apiVersion: 1, - }; - - const bidderRequest = { - refererInfo: { - referer: refererUrl - }, - gdprConsent - }; - - it('creates a valid banner request', function () { - const bannerRequest = getBidRequest(); - bannerRequest.getFloor = () => ({ - currency: 'USD', - // floor: 0.5 - }); - - const requests = spec.buildRequests([bannerRequest], bidderRequest); - - expect(requests).to.have.lengthOf(1); - const request = requests[0]; - - expect(request).to.exist; - const { method, url, data } = request; - - expect(method).to.equal('POST'); - - const parsedRequestUrl = parseUrl(url); - const { search: query } = parsedRequestUrl - - expect(parsedRequestUrl.hostname).to.equal('bs-metadsp.yandex.ru'); - expect(parsedRequestUrl.pathname).to.equal('/metadsp/123'); - - expect(query['imp-id']).to.equal('1'); - expect(query['target-ref']).to.equal('yandex.ru'); - expect(query['ssp-id']).to.equal('10500'); - - expect(query['gdpr']).to.equal('1'); - expect(query['tcf-consent']).to.equal('concent-string'); - - expect(request.data).to.exist; - expect(data.site).to.not.equal(null); - expect(data.site.page).to.equal('yandex.ru'); - - // expect(data.device).to.not.equal(null); - // expect(data.device.w).to.equal(window.innerWidth); - // expect(data.device.h).to.equal(window.innerHeight); - - expect(data.imp).to.have.lengthOf(1); - expect(data.imp[0].banner).to.not.equal(null); - expect(data.imp[0].banner.w).to.equal(300); - expect(data.imp[0].banner.h).to.equal(250); - }); - }); - - describe('response handler', function () { - const bannerRequest = getBidRequest(); - - const bannerResponse = { - body: { - seatbid: [{ - bid: [ - { - impid: '1', - price: 0.3, - crid: 321, - adm: '', - w: 300, - h: 250, - adomain: [ - 'example.com' - ], - adid: 'yabs.123=', - } - ] - }], - cur: 'USD', - }, - }; - - it('handles banner responses', function () { - bannerRequest.bidRequest = { - mediaType: BANNER, - bidId: 'bidid-1', - }; - const result = spec.interpretResponse(bannerResponse, bannerRequest); - - expect(result).to.have.lengthOf(1); - expect(result[0]).to.exist; - - const rtbBid = result[0]; - expect(rtbBid.width).to.equal(300); - expect(rtbBid.height).to.equal(250); - expect(rtbBid.cpm).to.be.within(0.1, 0.5); - expect(rtbBid.ad).to.equal(''); - expect(rtbBid.currency).to.equal('USD'); - expect(rtbBid.netRevenue).to.equal(true); - expect(rtbBid.ttl).to.equal(180); - - expect(rtbBid.meta.advertiserDomains).to.deep.equal(['example.com']); - }); - }); -}); diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index e4d258ecdea..d150646851f 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -1,4 +1,3 @@ -import { config } from 'src/config.js'; import { expect } from 'chai' import { spec } from 'modules/yieldlabBidAdapter.js' import { newBidder } from 'src/adapters/bidderFactory.js' @@ -17,22 +16,7 @@ const REQUEST = { 'extraParam': true, 'foo': 'bar' }, - 'extId': 'abc', - 'iabContent': { - 'id': 'foo_id', - 'episode': '99', - 'title': 'foo_title,bar_title', - 'series': 'foo_series', - 'season': 's1', - 'artist': 'foo bar', - 'genre': 'baz', - 'isrc': 'CC-XXX-YY-NNNNN', - 'url': 'http://foo_url.de', - 'cat': ['cat1', 'cat2,ppp', 'cat3|||//'], - 'context': '7', - 'keywords': ['k1,', 'k2..'], - 'live': '0' - } + 'extId': 'abc' }, 'bidderRequestId': '143346cf0f1731', 'auctionId': '2e41f65424c87c', @@ -73,12 +57,6 @@ const VIDEO_REQUEST = Object.assign({}, REQUEST, { } }) -const NATIVE_REQUEST = Object.assign({}, REQUEST, { - 'mediaTypes': { - 'native': { } - } -}) - const RESPONSE = { advertiser: 'yieldlab', curl: 'https://www.yieldlab.de', @@ -90,42 +68,6 @@ const RESPONSE = { adtype: 'BANNER' } -const NATIVE_RESPONSE = Object.assign({}, RESPONSE, { - 'adtype': 'NATIVE', - 'native': { - 'link': { - 'url': 'https://www.yieldlab.de' - }, - 'assets': [ - { - 'id': 1, - 'title': { - 'text': 'This is a great headline' - } - }, - { - 'id': 2, - 'img': { - 'url': 'https://localhost:8080/yl-logo100x100.jpg', - 'w': 100, - 'h': 100 - } - }, - { - 'id': 3, - 'data': { - 'value': 'Native body value' - } - } - ], - 'imptrackers': [ - 'http://localhost:8080/ve?d=ODE9ZSY2MTI1MjAzNjMzMzYxPXN0JjA0NWUwZDk0NTY5Yi05M2FiLWUwZTQtOWFjNy1hYWY0MzFiZj1kaXQmMj12', - 'http://localhost:8080/md/1111/9efa4e76-2030-4f04-bb9f-322541f8d611?mdata=false&pvid=false&ids=x:1', - 'http://localhost:8080/imp?s=13216&d=2171514&a=12548955&ts=1633363025216&tid=fb134faa-7ca9-4e0e-ba39-b96549d0e540&l=0' - ] - } -}) - const VIDEO_RESPONSE = Object.assign({}, RESPONSE, { 'adtype': 'VIDEO' }) @@ -144,10 +86,6 @@ const REQPARAMS_GDPR = Object.assign({}, REQPARAMS, { consent: 'BN5lERiOMYEdiAKAWXEND1AAAAE6DABACMA' }) -const REQPARAMS_IAB_CONTENT = Object.assign({}, REQPARAMS, { - iab_content: 'id%3Afoo_id%2Cepisode%3A99%2Ctitle%3Afoo_title%252Cbar_title%2Cseries%3Afoo_series%2Cseason%3As1%2Cartist%3Afoo%2520bar%2Cgenre%3Abaz%2Cisrc%3ACC-XXX-YY-NNNNN%2Curl%3Ahttp%253A%252F%252Ffoo_url.de%2Ccat%3Acat1%7Ccat2%252Cppp%7Ccat3%257C%257C%257C%252F%252F%2Ccontext%3A7%2Ckeywords%3Ak1%252C%7Ck2..%2Clive%3A0' -}) - describe('yieldlabBidAdapter', function () { const adapter = newBidder(spec) @@ -201,40 +139,6 @@ describe('yieldlabBidAdapter', function () { expect(request.url).to.include('schain=1.0,1!indirectseller.com,1,1,,,,!indirectseller2.com,2,1,,indirectseller2%20name%20with%20comma%20%2C%20and%20bang%20%21,,') }) - it('passes iab_content string to bid request', function () { - expect(request.url).to.include('iab_content=id%3Afoo_id%2Cepisode%3A99%2Ctitle%3Afoo_title%252Cbar_title%2Cseries%3Afoo_series%2Cseason%3As1%2Cartist%3Afoo%2520bar%2Cgenre%3Abaz%2Cisrc%3ACC-XXX-YY-NNNNN%2Curl%3Ahttp%253A%252F%252Ffoo_url.de%2Ccat%3Acat1%7Ccat2%252Cppp%7Ccat3%257C%257C%257C%252F%252F%2Ccontext%3A7%2Ckeywords%3Ak1%252C%7Ck2..%2Clive%3A0') - }) - - const siteConfig = { - 'ortb2': { - 'site': { - 'content': { - 'id': 'id_from_config' - } - } - } - } - - it('generates iab_content string from bidder params', function () { - config.setConfig(siteConfig); - const request = spec.buildRequests([REQUEST]) - expect(request.url).to.include('iab_content=id%3Afoo_id%2Cepisode%3A99%2Ctitle%3Afoo_title%252Cbar_title%2Cseries%3Afoo_series%2Cseason%3As1%2Cartist%3Afoo%2520bar%2Cgenre%3Abaz%2Cisrc%3ACC-XXX-YY-NNNNN%2Curl%3Ahttp%253A%252F%252Ffoo_url.de%2Ccat%3Acat1%7Ccat2%252Cppp%7Ccat3%257C%257C%257C%252F%252F%2Ccontext%3A7%2Ckeywords%3Ak1%252C%7Ck2..%2Clive%3A0') - config.resetConfig(); - }) - - it('generates iab_content string from first party data if not provided in bidder params', function () { - const requestWithoutIabContent = { - 'params': { - 'adslotId': '1111', - 'supplyId': '2222' - } - } - config.setConfig(siteConfig); - const request = spec.buildRequests([requestWithoutIabContent]) - expect(request.url).to.include('iab_content=id%3Aid_from_config') - config.resetConfig(); - }) - const refererRequest = spec.buildRequests(bidRequests, { refererInfo: { canonicalUrl: undefined, @@ -299,11 +203,6 @@ describe('yieldlabBidAdapter', function () { expect(result[0].ad).to.include('&consent=BN5lERiOMYEdiAKAWXEND1AAAAE6DABACMA') }) - it('should append iab_content to adtag', function () { - const result = spec.interpretResponse({body: [RESPONSE]}, {validBidRequests: [REQUEST], queryParams: REQPARAMS_IAB_CONTENT}) - expect(result[0].ad).to.include('&iab_content=id%3Afoo_id%2Cepisode%3A99%2Ctitle%3Afoo_title%252Cbar_title%2Cseries%3Afoo_series%2Cseason%3As1%2Cartist%3Afoo%2520bar%2Cgenre%3Abaz%2Cisrc%3ACC-XXX-YY-NNNNN%2Curl%3Ahttp%253A%252F%252Ffoo_url.de%2Ccat%3Acat1%7Ccat2%252Cppp%7Ccat3%257C%257C%257C%252F%252F%2Ccontext%3A7%2Ckeywords%3Ak1%252C%7Ck2..%2Clive%3A0') - }) - it('should get correct bid response when passing more than one size', function () { const REQUEST2 = Object.assign({}, REQUEST, { 'sizes': [ @@ -339,45 +238,6 @@ describe('yieldlabBidAdapter', function () { expect(result[0].vastUrl).to.include('&id=abc') }) - it('should add adUrl and native assets when type is Native', function () { - const result = spec.interpretResponse({body: [NATIVE_RESPONSE]}, {validBidRequests: [NATIVE_REQUEST], queryParams: REQPARAMS}) - - expect(result[0].requestId).to.equal('2d925f27f5079f') - expect(result[0].cpm).to.equal(0.01) - expect(result[0].mediaType).to.equal('native') - expect(result[0].adUrl).to.include('https://ad.yieldlab.net/d/1111/2222/?ts=') - expect(result[0].native.title).to.equal('This is a great headline') - expect(result[0].native.body).to.equal('Native body value') - expect(result[0].native.image.url).to.equal('https://localhost:8080/yl-logo100x100.jpg') - expect(result[0].native.image.width).to.equal(100) - expect(result[0].native.image.height).to.equal(100) - expect(result[0].native.clickUrl).to.equal('https://www.yieldlab.de') - expect(result[0].native.impressionTrackers.length).to.equal(3) - }) - - it('should add adUrl and default native assets when type is Native', function () { - const NATIVE_RESPONSE_2 = Object.assign({}, NATIVE_RESPONSE, { - 'native': { - 'link': { - 'url': 'https://www.yieldlab.de' - }, - 'assets': [], - 'imptrackers': [] - } - }) - const result = spec.interpretResponse({body: [NATIVE_RESPONSE_2]}, {validBidRequests: [NATIVE_REQUEST], queryParams: REQPARAMS}) - - expect(result[0].requestId).to.equal('2d925f27f5079f') - expect(result[0].cpm).to.equal(0.01) - expect(result[0].mediaType).to.equal('native') - expect(result[0].adUrl).to.include('https://ad.yieldlab.net/d/1111/2222/?ts=') - expect(result[0].native.title).to.equal('') - expect(result[0].native.body).to.equal('') - expect(result[0].native.image.url).to.equal('') - expect(result[0].native.image.width).to.equal(0) - expect(result[0].native.image.height).to.equal(0) - }) - it('should append gdpr parameters to vastUrl', function () { const result = spec.interpretResponse({body: [VIDEO_RESPONSE]}, {validBidRequests: [VIDEO_REQUEST], queryParams: REQPARAMS_GDPR}) @@ -408,46 +268,5 @@ describe('yieldlabBidAdapter', function () { expect(result[0].ad).to.include('&pvid=43513f11-55a0-4a83-94e5-0ebc08f54a2c') expect(result[0].vastUrl).to.include('&pvid=43513f11-55a0-4a83-94e5-0ebc08f54a2c') }) - - it('should append iab_content to vastUrl', function () { - const result = spec.interpretResponse({body: [VIDEO_RESPONSE]}, {validBidRequests: [VIDEO_REQUEST], queryParams: REQPARAMS_IAB_CONTENT}) - expect(result[0].vastUrl).to.include('&iab_content=id%3Afoo_id%2Cepisode%3A99%2Ctitle%3Afoo_title%252Cbar_title%2Cseries%3Afoo_series%2Cseason%3As1%2Cartist%3Afoo%2520bar%2Cgenre%3Abaz%2Cisrc%3ACC-XXX-YY-NNNNN%2Curl%3Ahttp%253A%252F%252Ffoo_url.de%2Ccat%3Acat1%7Ccat2%252Cppp%7Ccat3%257C%257C%257C%252F%252F%2Ccontext%3A7%2Ckeywords%3Ak1%252C%7Ck2..%2Clive%3A0') - }) }) - - describe('getUserSyncs', function () { - const syncOptions = { - iframeEnabled: true, - pixelEnabled: false - }; - const expectedUrlSnippets = ['https://ad.yieldlab.net/d/6846326/766/2x2?', 'ts=', 'type=h']; - - it('should return user sync as expected', function () { - const bidRequest = { - gdprConsent: { - consentString: 'BN5lERiOMYEdiAKAWXEND1AAAAE6DABACMA', - gdprApplies: true - }, - uspConsent: '1YYY' - }; - const sync = spec.getUserSyncs(syncOptions, [], bidRequest.gdprConsent, bidRequest.uspConsent); - expect(expectedUrlSnippets.every(urlSnippet => sync[0].url.includes(urlSnippet))); - expect(sync[0].url).to.have.string('gdpr=' + Number(bidRequest.gdprConsent.gdprApplies)); - expect(sync[0].url).to.have.string('gdpr_consent=' + bidRequest.gdprConsent.consentString); - // USP consent should be ignored - expect(sync[0].url).not.have.string('usp_consent='); - expect(sync[0].type).to.have.string('iframe'); - }); - - it('should return user sync even without gdprApplies in gdprConsent', function () { - const gdprConsent = { - consentString: 'BN5lERiOMYEdiAKAWXEND1AAAAE6DABACMA' - } - const sync = spec.getUserSyncs(syncOptions, [], gdprConsent, undefined); - expect(expectedUrlSnippets.every(urlSnippet => sync[0].url.includes(urlSnippet))); - expect(sync[0].url).to.have.string('gdpr_consent=' + gdprConsent.consentString); - expect(sync[0].url).not.have.string('gdpr='); - expect(sync[0].type).to.have.string('iframe'); - }); - }); }) diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index f72705a79ac..378c5d89113 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -307,7 +307,7 @@ describe('YieldmoAdapter', function () { }); it('should only shortcut properties rather then completely remove it', () => { - const longString = new Array(8000).join('a'); + const longString = new Array(7516).join('a'); const localWindow = utils.getWindowTop(); const originalTitle = localWindow.document.title; @@ -319,7 +319,7 @@ describe('YieldmoAdapter', function () { refererInfo: { numIframes: 1, reachedTop: true, - title: longString, + referer: longString, }, }) )[0]; @@ -328,37 +328,6 @@ describe('YieldmoAdapter', function () { localWindow.document.title = originalTitle; }); - - it('should add ats_envelope to banner bid request', function() { - const envelope = 'test_envelope'; - const requests = build([mockBannerBid({}, { lr_env: envelope })]); - - expect(requests[0].data.ats_envelope).to.equal(envelope); - }); - - it('should add gpid to the banner bid request', function () { - let bidArray = [mockBannerBid({ - ortb2Imp: { - ext: { data: { pbadslot: '/6355419/Travel/Europe/France/Paris' } }, - } - })]; - let placementInfo = buildAndGetPlacementInfo(bidArray); - expect(placementInfo).to.include('"gpid":"/6355419/Travel/Europe/France/Paris"'); - }); - - it('should add eids to the banner bid request', function () { - const params = { - userId: {pubcid: 'fake_pubcid'}, - fakeUserIdAsEids: [{ - source: 'pubcid.org', - uids: [{ - id: 'fake_pubcid', - atype: 1 - }] - }] - }; - expect(buildAndGetData([mockBannerBid({...params})]).eids).equal(JSON.stringify(params.fakeUserIdAsEids)); - }); }); describe('Instream video:', function () { @@ -470,38 +439,11 @@ describe('YieldmoAdapter', function () { expect(requests[0].data.ats_envelope).to.equal(envelope); }); - it('should add schain if it is in the bidRequest', () => { - const schain = { - ver: '1.0', - complete: 1, - nodes: [{ - asi: 'indirectseller.com', - sid: '00001', - hp: 1 - }], - }; - expect(buildAndGetData([mockVideoBid({schain})]).schain).to.deep.equal(schain); - }); + it('should add ats_envelope to banner bid request', function() { + const envelope = 'test_envelope'; + const requests = build([mockBannerBid({}, { lr_env: envelope })]); - it('should add gpid to the video request', function () { - const ortb2Imp = { - ext: { data: { pbadslot: '/6355419/Travel/Europe/France/Paris' } }, - }; - expect(buildAndGetData([mockVideoBid({ortb2Imp})]).imp[0].ext.gpid).to.be.equal(ortb2Imp.ext.data.pbadslot); - }); - - it('should add eids to the video bid request', function () { - const params = { - userId: {pubcid: 'fake_pubcid'}, - fakeUserIdAsEids: [{ - source: 'pubcid.org', - uids: [{ - id: 'fake_pubcid', - atype: 1 - }] - }] - }; - expect(buildAndGetData([mockVideoBid({...params})]).user.eids).to.eql(params.fakeUserIdAsEids); + expect(requests[0].data.ats_envelope).to.equal(envelope); }); }); }); @@ -511,7 +453,6 @@ describe('YieldmoAdapter', function () { body: [{ callback_id: '21989fdbef550a', cpm: 3.45455, - publisherDealId: 'YMO_123', width: 300, height: 250, ad: '' + @@ -526,7 +467,6 @@ describe('YieldmoAdapter', function () { const newResponse = spec.interpretResponse(mockServerResponse()); expect(newResponse.length).to.be.equal(1); expect(newResponse[0]).to.deep.equal({ - dealId: 'YMO_123', requestId: '21989fdbef550a', cpm: 3.45455, width: 300, @@ -554,7 +494,6 @@ describe('YieldmoAdapter', function () { crid: 'dd65c0a7536aff', impid: '91ea8bba1', price: 1.5, - dealid: 'YMO_456' }, }, ]; @@ -577,7 +516,6 @@ describe('YieldmoAdapter', function () { const newResponse = spec.interpretResponse(response, bidRequest); expect(newResponse.length).to.be.equal(2); expect(newResponse[1]).to.deep.equal({ - dealId: 'YMO_456', cpm: 1.5, creativeId: 'dd65c0a7536aff', currency: 'USD', diff --git a/test/spec/modules/yieldmoSyntheticInventoryModule_spec.js b/test/spec/modules/yieldmoSyntheticInventoryModule_spec.js deleted file mode 100644 index 55b4e7255f7..00000000000 --- a/test/spec/modules/yieldmoSyntheticInventoryModule_spec.js +++ /dev/null @@ -1,89 +0,0 @@ -import { expect } from 'chai'; -import { - init, - MODULE_NAME, - validateConfig -} from 'modules/yieldmoSyntheticInventoryModule'; - -const mockedYmConfig = { - placementId: '123456', - adUnitPath: '/6355419/ad_unit_name_used_in_gam' -}; - -const setGoogletag = () => { - window.googletag = { - cmd: [], - defineSlot: sinon.stub(), - addService: sinon.stub(), - pubads: sinon.stub(), - setTargeting: sinon.stub(), - enableServices: sinon.stub(), - display: sinon.stub(), - }; - window.googletag.defineSlot.returns(window.googletag); - window.googletag.addService.returns(window.googletag); - window.googletag.pubads.returns({getSlots: sinon.stub()}); - return window.googletag; -} - -describe('Yieldmo Synthetic Inventory Module', function() { - let config = Object.assign({}, mockedYmConfig); - let googletagBkp; - - beforeEach(function () { - googletagBkp = window.googletag; - delete window.googletag; - }); - - afterEach(function () { - window.googletag = googletagBkp; - }); - - it('should be enabled with valid required params', function() { - expect(function () { - init(mockedYmConfig); - }).not.to.throw() - }); - - it('should throw an error if placementId is missed', function() { - const {placementId, ...config} = mockedYmConfig; - - expect(function () { - validateConfig(config); - }).throw(`${MODULE_NAME}: placementId required`) - }); - - it('should throw an error if adUnitPath is missed', function() { - const {adUnitPath, ...config} = mockedYmConfig; - - expect(function () { - validateConfig(config); - }).throw(`${MODULE_NAME}: adUnitPath required`) - }); - - it('should add correct googletag.cmd', function() { - const containerName = 'ym_sim_container_' + mockedYmConfig.placementId; - const gtag = setGoogletag(); - - init(mockedYmConfig); - - expect(gtag.cmd.length).to.equal(1); - - gtag.cmd[0](); - - expect(gtag.addService.getCall(0)).to.not.be.null; - expect(gtag.setTargeting.getCall(0)).to.not.be.null; - expect(gtag.setTargeting.getCall(0).args[0]).to.exist.and.to.equal('ym_sim_p_id'); - expect(gtag.setTargeting.getCall(0).args[1]).to.exist.and.to.equal(mockedYmConfig.placementId); - expect(gtag.defineSlot.getCall(0)).to.not.be.null; - expect(gtag.enableServices.getCall(0)).to.not.be.null; - expect(gtag.display.getCall(0)).to.not.be.null; - expect(gtag.display.getCall(0).args[0]).to.exist.and.to.equal(containerName); - expect(gtag.pubads.getCall(0)).to.not.be.null; - - const gamContainerEl = window.document.getElementById(containerName); - expect(gamContainerEl).to.not.be.null; - - gamContainerEl.parentNode.removeChild(gamContainerEl); - }); -}); diff --git a/test/spec/modules/yieldoneBidAdapter_spec.js b/test/spec/modules/yieldoneBidAdapter_spec.js index d452d78e147..4186c5da41a 100644 --- a/test/spec/modules/yieldoneBidAdapter_spec.js +++ b/test/spec/modules/yieldoneBidAdapter_spec.js @@ -7,8 +7,6 @@ const ENDPOINT = 'https://y.one.impact-ad.jp/h_bid'; const USER_SYNC_URL = 'https://y.one.impact-ad.jp/push_sync'; const VIDEO_PLAYER_URL = 'https://img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/dac-video-prebid.min.js'; -const DEFAULT_VIDEO_SIZE = {w: 640, h: 360}; - describe('yieldoneBidAdapter', function() { const adapter = newBidder(spec); @@ -42,7 +40,32 @@ describe('yieldoneBidAdapter', function() { }); describe('buildRequests', function () { - const bidderRequest = { + let bidRequests = [ + { + 'bidder': 'yieldone', + 'params': { + placementId: '36891' + }, + 'adUnitCode': 'adunit-code1', + 'sizes': [[300, 250], [336, 280]], + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }, + { + 'bidder': 'yieldone', + 'params': { + placementId: '47919' + }, + 'adUnitCode': 'adunit-code2', + 'sizes': [[300, 250]], + 'bidId': '382091349b149f"', + 'bidderRequestId': '"1f9c98192de251"', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + } + ]; + + let bidderRequest = { refererInfo: { numIframes: 0, reachedTop: true, @@ -51,354 +74,52 @@ describe('yieldoneBidAdapter', function() { } }; - describe('Basic', function () { - const bidRequests = [ - { - 'bidder': 'yieldone', - 'params': {placementId: '36891'}, - 'adUnitCode': 'adunit-code1', - 'bidId': '23beaa6af6cdde', - 'bidderRequestId': '19c0c1efdf37e7', - 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', - }, - { - 'bidder': 'yieldone', - 'params': {placementId: '47919'}, - 'adUnitCode': 'adunit-code2', - 'bidId': '382091349b149f"', - 'bidderRequestId': '"1f9c98192de251"', - 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', - } - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); + const request = spec.buildRequests(bidRequests, bidderRequest); - it('sends bid request to our endpoint via GET', function () { - expect(request[0].method).to.equal('GET'); - expect(request[1].method).to.equal('GET'); - }); - it('attaches source and version to endpoint URL as query params', function () { - expect(request[0].url).to.equal(ENDPOINT); - expect(request[1].url).to.equal(ENDPOINT); - }); - it('adUnitCode should be sent as uc parameters on any requests', function () { - expect(request[0].data.uc).to.equal('adunit-code1'); - expect(request[1].data.uc).to.equal('adunit-code2'); - }); + it('sends bid request to our endpoint via GET', function () { + expect(request[0].method).to.equal('GET'); + expect(request[1].method).to.equal('GET'); }); - describe('Old Format', function () { - const bidRequests = [ - { - params: {placementId: '0'}, - mediaType: 'banner', - sizes: [[300, 250], [336, 280]], - }, - { - params: {placementId: '1'}, - mediaType: 'banner', - sizes: [[336, 280]], - }, - { - // It doesn't actually exist. - params: {placementId: '2'}, - }, - { - params: {placementId: '3'}, - mediaType: 'video', - sizes: [[1280, 720], [1920, 1080]], - }, - { - params: {placementId: '4'}, - mediaType: 'video', - sizes: [[1920, 1080]], - }, - { - params: {placementId: '5'}, - mediaType: 'video', - }, - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); - - it('parameter sz has more than one size on banner requests', function () { - expect(request[0].data.sz).to.equal('300x250,336x280'); - expect(request[1].data.sz).to.equal('336x280'); - expect(request[2].data.sz).to.equal(''); - expect(request[3].data).to.not.have.property('sz'); - expect(request[4].data).to.not.have.property('sz'); - expect(request[5].data).to.not.have.property('sz'); - }); - - it('width and height should be set as separate parameters on outstream requests', function () { - expect(request[0].data).to.not.have.property('w'); - expect(request[1].data).to.not.have.property('w'); - expect(request[2].data).to.not.have.property('w'); - expect(request[3].data.w).to.equal(1280); - expect(request[3].data.h).to.equal(720); - expect(request[4].data.w).to.equal(1920); - expect(request[4].data.h).to.equal(1080); - expect(request[5].data.w).to.equal(DEFAULT_VIDEO_SIZE.w); - expect(request[5].data.h).to.equal(DEFAULT_VIDEO_SIZE.h); - }); + it('attaches source and version to endpoint URL as query params', function () { + expect(request[0].url).to.equal(ENDPOINT); + expect(request[1].url).to.equal(ENDPOINT); }); - describe('New Format', function () { - const bidRequests = [ - { - params: {placementId: '0'}, - mediaTypes: { - banner: { - sizes: [[300, 250], [336, 280]], - }, - }, - }, - { - params: {placementId: '1'}, - mediaTypes: { - banner: { - sizes: [[336, 280]], - }, - }, - }, - { - // It doesn't actually exist. - params: {placementId: '2'}, - mediaTypes: { - banner: { - }, - }, - }, - { - params: {placementId: '3'}, - mediaTypes: { - video: { - context: 'outstream', - playerSize: [[1280, 720], [1920, 1080]], - }, - }, - }, - { - params: {placementId: '4'}, - mediaTypes: { - video: { - context: 'outstream', - playerSize: [1920, 1080], - }, - }, - }, - { - params: {placementId: '5'}, - mediaTypes: { - video: { - context: 'outstream', - }, - }, - }, - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); - - it('parameter sz has more than one size on banner requests', function () { - expect(request[0].data.sz).to.equal('300x250,336x280'); - expect(request[1].data.sz).to.equal('336x280'); - expect(request[2].data.sz).to.equal(''); - expect(request[3].data).to.not.have.property('sz'); - expect(request[4].data).to.not.have.property('sz'); - expect(request[5].data).to.not.have.property('sz'); - }); - - it('width and height should be set as separate parameters on outstream requests', function () { - expect(request[0].data).to.not.have.property('w'); - expect(request[1].data).to.not.have.property('w'); - expect(request[2].data).to.not.have.property('w'); - expect(request[3].data.w).to.equal(1280); - expect(request[3].data.h).to.equal(720); - expect(request[4].data.w).to.equal(1920); - expect(request[4].data.h).to.equal(1080); - expect(request[5].data.w).to.equal(DEFAULT_VIDEO_SIZE.w); - expect(request[5].data.h).to.equal(DEFAULT_VIDEO_SIZE.h); - }); + it('parameter sz has more than one size on banner requests', function () { + expect(request[0].data.sz).to.equal('300x250,336x280'); + expect(request[1].data.sz).to.equal('300x250'); }); - describe('Multiple Format', function () { - const bidRequests = [ - { - // It will be treated as a banner. - params: { - placementId: '0', - }, - mediaTypes: { - banner: { - sizes: [[300, 250], [336, 280]], - }, - video: { - context: 'outstream', - playerSize: [1920, 1080], - }, - }, - }, - { - // It will be treated as a video. - params: { - placementId: '1', - playerParams: {}, - }, - mediaTypes: { - banner: { - sizes: [[300, 250], [336, 280]], - }, - video: { - context: 'outstream', - playerSize: [1920, 1080], - }, - }, - }, - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); - - it('parameter sz has more than one size on banner requests', function () { - expect(request[0].data.sz).to.equal('300x250,336x280'); - expect(request[1].data).to.not.have.property('sz'); - }); - - it('width and height should be set as separate parameters on outstream requests', function () { - expect(request[0].data).to.not.have.property('w'); - expect(request[1].data.w).to.equal(1920); - expect(request[1].data.h).to.equal(1080); - }); + it('width and height should be set as separate parameters on outstream requests', function () { + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest.mediaTypes = {}; + bidRequest.mediaTypes.video = {context: 'outstream'}; + const request = spec.buildRequests([bidRequest], bidderRequest); + expect(request[0].data.w).to.equal('300'); + expect(request[0].data.h).to.equal('250'); }); - describe('FLUX Format', function () { - const bidRequests = [ - { - // It will be treated as a banner. - params: { - placementId: '0', - }, - mediaTypes: { - banner: { - sizes: [[300, 250], [336, 280]], - }, - video: { - context: 'outstream', - playerSize: [[1, 1]], - }, - }, - }, - { - // It will be treated as a video. - params: { - placementId: '1', - playerParams: {}, - playerSize: [1920, 1080], - }, - mediaTypes: { - banner: { - sizes: [[300, 250], [336, 280]], - }, - video: { - context: 'outstream', - playerSize: [[1, 1]], - }, - }, - }, - { - // It will be treated as a video. - params: { - placementId: '2', - playerParams: {}, - }, - mediaTypes: { - banner: { - sizes: [[300, 250], [336, 280]], - }, - video: { - context: 'outstream', - playerSize: [[1, 1]], - }, - }, - }, - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); - - it('parameter sz has more than one size on banner requests', function () { - expect(request[0].data.sz).to.equal('300x250,336x280'); - expect(request[1].data).to.not.have.property('sz'); - expect(request[2].data).to.not.have.property('sz'); - }); - - it('width and height should be set as separate parameters on outstream requests', function () { - expect(request[0].data).to.not.have.property('w'); - expect(request[1].data.w).to.equal(1920); - expect(request[1].data.h).to.equal(1080); - expect(request[2].data.w).to.equal(DEFAULT_VIDEO_SIZE.w); - expect(request[2].data.h).to.equal(DEFAULT_VIDEO_SIZE.h); - }); + it('adUnitCode should be sent as uc parameters on any requests', function () { + expect(request[0].data.uc).to.equal('adunit-code1'); + expect(request[1].data.uc).to.equal('adunit-code2'); }); - describe('LiveRampID', function () { + describe('userid idl_env should be passed to querystring', function () { + const bid = deepClone([bidRequests[0]]); + it('dont send LiveRampID if undefined', function () { - const bidRequests = [ - { - params: {placementId: '0'}, - }, - { - params: {placementId: '1'}, - userId: {}, - }, - { - params: {placementId: '2'}, - userId: undefined, - }, - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); + bid[0].userId = {}; + const request = spec.buildRequests(bid, bidderRequest); expect(request[0].data).to.not.have.property('lr_env'); - expect(request[1].data).to.not.have.property('lr_env'); - expect(request[2].data).to.not.have.property('lr_env'); }); it('should send LiveRampID if available', function () { - const bidRequests = [ - { - params: {placementId: '0'}, - userId: {idl_env: 'idl_env_sample'}, - }, - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); + bid[0].userId = {idl_env: 'idl_env_sample'}; + const request = spec.buildRequests(bid, bidderRequest); expect(request[0].data.lr_env).to.equal('idl_env_sample'); }); }); - - describe('IMID', function () { - it('dont send IMID if undefined', function () { - const bidRequests = [ - { - params: {placementId: '0'}, - }, - { - params: {placementId: '1'}, - userId: {}, - }, - { - params: {placementId: '2'}, - userId: undefined, - }, - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request[0].data).to.not.have.property('imuid'); - expect(request[1].data).to.not.have.property('imuid'); - expect(request[2].data).to.not.have.property('imuid'); - }); - - it('should send IMID if available', function () { - const bidRequests = [ - { - params: {placementId: '0'}, - userId: {imuid: 'imuid_sample'}, - }, - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request[0].data.imuid).to.equal('imuid_sample'); - }); - }); }); describe('interpretResponse', function () { diff --git a/test/spec/modules/zeotapIdPlusIdSystem_spec.js b/test/spec/modules/zeotapIdPlusIdSystem_spec.js index 6494a7cbfef..9de6fa843bc 100644 --- a/test/spec/modules/zeotapIdPlusIdSystem_spec.js +++ b/test/spec/modules/zeotapIdPlusIdSystem_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import {find} from 'src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; import { config } from 'src/config.js'; import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; import { storage, getStorage, zeotapIdPlusSubmodule } from 'modules/zeotapIdPlusIdSystem.js'; @@ -54,7 +54,7 @@ describe('Zeotap ID System', function() { it('when a stored Zeotap ID exists it is added to bids', function() { let store = getStorage(); expect(getStorageManagerSpy.calledOnce).to.be.true; - sinon.assert.calledWith(getStorageManagerSpy, {gvlid: 301, moduleName: 'zeotapIdPlus'}); + sinon.assert.calledWith(getStorageManagerSpy, 301, 'zeotapIdPlus'); }); }); @@ -162,8 +162,8 @@ describe('Zeotap ID System', function() { ZEOTAP_COOKIE_NAME, ENCODED_ZEOTAP_COOKIE ); - init(config); setSubmoduleRegistry([zeotapIdPlusSubmodule]); + init(config); config.setConfig(getConfigMock()); }); diff --git a/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js b/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js deleted file mode 100644 index 15a1155f378..00000000000 --- a/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js +++ /dev/null @@ -1,427 +0,0 @@ -import zetaAnalyticsAdapter from 'modules/zeta_global_sspAnalyticsAdapter.js'; -import {config} from 'src/config'; -import CONSTANTS from 'src/constants.json'; -import {logError} from '../../../src/utils'; - -let utils = require('src/utils'); -let events = require('src/events'); - -const MOCK = { - STUB: { - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa' - }, - AUCTION_END: { - 'auctionId': '75e394d9-ccce-4978-9238-91e6a1ac88a1', - 'timestamp': 1638441234544, - 'auctionEnd': 1638441234784, - 'auctionStatus': 'completed', - 'adUnits': [ - { - 'code': '/19968336/header-bid-tag-0', - 'mediaTypes': { - 'banner': { - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ] - } - }, - 'bids': [ - { - 'bidder': 'zeta_global_ssp', - 'params': { - 'sid': 111, - 'tags': { - 'shortname': 'prebid_analytics_event_test_shortname', - 'position': 'test_position' - } - } - }, - { - 'bidder': 'appnexus', - 'params': { - 'placementId': 13232385 - } - } - ], - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'transactionId': '6b29369c-0c2e-414e-be1f-5867aec18d83' - } - ], - 'adUnitCodes': [ - '/19968336/header-bid-tag-0' - ], - 'bidderRequests': [ - { - 'bidderCode': 'zeta_global_ssp', - 'auctionId': '75e394d9-ccce-4978-9238-91e6a1ac88a1', - 'bidderRequestId': '1207cb49191887', - 'bids': [ - { - 'bidder': 'zeta_global_ssp', - 'params': { - 'sid': 111, - 'tags': { - 'shortname': 'prebid_analytics_event_test_shortname', - 'position': 'test_position' - } - }, - 'mediaTypes': { - 'banner': { - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ] - } - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'transactionId': '6b29369c-0c2e-414e-be1f-5867aec18d83', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '206be9a13236af', - 'bidderRequestId': '1207cb49191887', - 'auctionId': '75e394d9-ccce-4978-9238-91e6a1ac88a1', - 'src': 'client', - 'bidRequestsCount': 1, - 'bidderRequestsCount': 1, - 'bidderWinsCount': 0 - } - ], - 'auctionStart': 1638441234544, - 'timeout': 400, - 'refererInfo': { - 'referer': 'http://test-zeta-ssp.net:63342/zeta-ssp/ssp/_dev/examples/page_banner.html', - 'reachedTop': true, - 'isAmp': false, - 'numIframes': 0, - 'stack': [ - 'http://test-zeta-ssp.net:63342/zeta-ssp/ssp/_dev/examples/page_banner.html' - ], - 'canonicalUrl': null - }, - 'start': 1638441234547 - }, - { - 'bidderCode': 'appnexus', - 'auctionId': '75e394d9-ccce-4978-9238-91e6a1ac88a1', - 'bidderRequestId': '32b97f0a935422', - 'bids': [ - { - 'bidder': 'appnexus', - 'params': { - 'placementId': 13232385 - }, - 'mediaTypes': { - 'banner': { - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ] - } - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'transactionId': '6b29369c-0c2e-414e-be1f-5867aec18d83', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '41badc0e164c758', - 'bidderRequestId': '32b97f0a935422', - 'auctionId': '75e394d9-ccce-4978-9238-91e6a1ac88a1', - 'src': 'client', - 'bidRequestsCount': 1, - 'bidderRequestsCount': 1, - 'bidderWinsCount': 0 - } - ], - 'auctionStart': 1638441234544, - 'timeout': 400, - 'refererInfo': { - 'referer': 'http://test-zeta-ssp.net:63342/zeta-ssp/ssp/_dev/examples/page_banner.html', - 'reachedTop': true, - 'isAmp': false, - 'numIframes': 0, - 'stack': [ - 'http://test-zeta-ssp.net:63342/zeta-ssp/ssp/_dev/examples/page_banner.html' - ], - 'canonicalUrl': null - }, - 'start': 1638441234550 - } - ], - 'noBids': [ - { - 'bidder': 'appnexus', - 'params': { - 'placementId': 13232385 - }, - 'mediaTypes': { - 'banner': { - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ] - } - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'transactionId': '6b29369c-0c2e-414e-be1f-5867aec18d83', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '41badc0e164c758', - 'bidderRequestId': '32b97f0a935422', - 'auctionId': '75e394d9-ccce-4978-9238-91e6a1ac88a1', - 'src': 'client', - 'bidRequestsCount': 1, - 'bidderRequestsCount': 1, - 'bidderWinsCount': 0 - } - ], - 'bidsReceived': [ - { - 'bidderCode': 'zeta_global_ssp', - 'width': 480, - 'height': 320, - 'statusMessage': 'Bid available', - 'adId': '5759bb3ef7be1e8', - 'requestId': '206be9a13236af', - 'mediaType': 'banner', - 'source': 'client', - 'cpm': 2.258302852806723, - 'currency': 'USD', - 'ad': 'test_ad', - 'ttl': 200, - 'creativeId': '456456456', - 'netRevenue': true, - 'meta': { - 'advertiserDomains': [ - 'viaplay.fi' - ] - }, - 'originalCpm': 2.258302852806723, - 'originalCurrency': 'USD', - 'auctionId': '75e394d9-ccce-4978-9238-91e6a1ac88a1', - 'responseTimestamp': 1638441234670, - 'requestTimestamp': 1638441234547, - 'bidder': 'zeta_global_ssp', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 123, - 'pbLg': '2.00', - 'pbMg': '2.20', - 'pbHg': '2.25', - 'pbAg': '2.25', - 'pbDg': '2.25', - 'pbCg': '', - 'size': '480x320', - 'adserverTargeting': { - 'hb_bidder': 'zeta_global_ssp', - 'hb_adid': '5759bb3ef7be1e8', - 'hb_pb': '2.20', - 'hb_size': '480x320', - 'hb_source': 'client', - 'hb_format': 'banner', - 'hb_adomain': 'viaplay.fi' - } - } - ], - 'winningBids': [], - 'timeout': 400 - }, - AD_RENDER_SUCCEEDED: { - 'doc': { - 'location': { - 'href': 'http://test-zeta-ssp.net:63342/zeta-ssp/ssp/_dev/examples/page_banner.html', - 'protocol': 'http:', - 'host': 'localhost:63342', - 'hostname': 'localhost', - 'port': '63342', - 'pathname': '/zeta-ssp/ssp/_dev/examples/page_banner.html', - 'hash': '', - 'origin': 'http://test-zeta-ssp.net:63342', - 'ancestorOrigins': { - '0': 'http://test-zeta-ssp.net:63342' - } - } - }, - 'bid': { - 'bidderCode': 'zeta_global_ssp', - 'width': 480, - 'height': 320, - 'statusMessage': 'Bid available', - 'adId': '5759bb3ef7be1e8', - 'requestId': '206be9a13236af', - 'mediaType': 'banner', - 'source': 'client', - 'cpm': 2.258302852806723, - 'currency': 'USD', - 'ad': 'test_ad', - 'ttl': 200, - 'creativeId': '456456456', - 'netRevenue': true, - 'meta': { - 'advertiserDomains': [ - 'viaplay.fi' - ] - }, - 'originalCpm': 2.258302852806723, - 'originalCurrency': 'USD', - 'auctionId': '75e394d9-ccce-4978-9238-91e6a1ac88a1', - 'responseTimestamp': 1638441234670, - 'requestTimestamp': 1638441234547, - 'bidder': 'zeta_global_ssp', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 123, - 'pbLg': '2.00', - 'pbMg': '2.20', - 'pbHg': '2.25', - 'pbAg': '2.25', - 'pbDg': '2.25', - 'pbCg': '', - 'size': '480x320', - 'adserverTargeting': { - 'hb_bidder': 'zeta_global_ssp', - 'hb_adid': '5759bb3ef7be1e8', - 'hb_pb': '2.20', - 'hb_size': '480x320', - 'hb_source': 'client', - 'hb_format': 'banner', - 'hb_adomain': 'viaplay.fi' - }, - 'status': 'rendered', - 'params': [ - { - 'sid': 111, - 'tags': { - 'shortname': 'prebid_analytics_event_test_shortname', - 'position': 'test_position' - } - } - ] - }, - 'adId': '5759bb3ef7be1e8' - } -} - -describe('Zeta Global SSP Analytics Adapter', function() { - let sandbox; - let xhr; - let requests; - - beforeEach(function() { - sandbox = sinon.sandbox.create(); - requests = []; - xhr = sandbox.useFakeXMLHttpRequest(); - xhr.onCreate = request => requests.push(request); - sandbox.stub(events, 'getEvents').returns([]); - }); - - afterEach(function () { - sandbox.restore(); - config.resetConfig(); - }); - - it('should require publisherId', function () { - sandbox.stub(utils, 'logError'); - zetaAnalyticsAdapter.enableAnalytics({ - options: {} - }); - expect(utils.logError.called).to.equal(true); - }); - - describe('handle events', function() { - beforeEach(function() { - zetaAnalyticsAdapter.enableAnalytics({ - options: { - sid: 111 - } - }); - }); - - afterEach(function () { - zetaAnalyticsAdapter.disableAnalytics(); - }); - - it('events are sent', function() { - this.timeout(5000); - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.AUCTION_END, MOCK.AUCTION_END); - events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.BID_REQUESTED, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.BID_RESPONSE, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.NO_BID, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.BID_WON, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.BIDDER_DONE, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.BIDDER_ERROR, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.SET_TARGETING, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.BEFORE_REQUEST_BIDS, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.BEFORE_BIDDER_HTTP, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.REQUEST_BIDS, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.ADD_AD_UNITS, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.AD_RENDER_FAILED, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED, MOCK.AD_RENDER_SUCCEEDED); - events.emit(CONSTANTS.EVENTS.TCF2_ENFORCEMENT, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.AUCTION_DEBUG, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.BID_VIEWABLE, MOCK.STUB); - events.emit(CONSTANTS.EVENTS.STALE_RENDER, MOCK.STUB); - - expect(requests.length).to.equal(2); - expect(JSON.parse(requests[0].requestBody)).to.deep.equal(MOCK.AUCTION_END); - expect(JSON.parse(requests[1].requestBody)).to.deep.equal(MOCK.AD_RENDER_SUCCEEDED); - }); - }); -}); diff --git a/test/spec/modules/zeta_global_sspBidAdapter_spec.js b/test/spec/modules/zeta_global_sspBidAdapter_spec.js index 20113a63994..740ea855fca 100644 --- a/test/spec/modules/zeta_global_sspBidAdapter_spec.js +++ b/test/spec/modules/zeta_global_sspBidAdapter_spec.js @@ -1,5 +1,4 @@ import {spec} from '../../../modules/zeta_global_sspBidAdapter.js' -import {BANNER, VIDEO} from '../../../src/mediaTypes'; describe('Zeta Ssp Bid Adapter', function () { const eids = [ @@ -56,36 +55,6 @@ describe('Zeta Ssp Bid Adapter', function () { userIdAsEids: eids }]; - const videoRequest = [{ - bidId: 112233, - auctionId: 667788, - mediaTypes: { - video: { - context: 'instream', - playerSize: [[720, 340]], - mimes: ['video/mp4'], - minduration: 5, - maxduration: 30, - protocols: [2, 3] - } - }, - refererInfo: { - referer: 'http://www.zetaglobal.com/page?param=video' - }, - params: { - placement: 111, - user: { - uid: 222, - buyeruid: 333 - }, - tags: { - someTag: 444, - sid: 'publisherId' - }, - test: 1 - }, - }]; - it('Test the bid validation function', function () { const validBid = spec.isBidRequestValid(bannerRequest[0]); const invalidBid = spec.isBidRequestValid(null); @@ -100,13 +69,6 @@ describe('Zeta Ssp Bid Adapter', function () { expect(payload.user.ext.eids).to.eql(eids); }); - it('Test contains ua and language', function () { - const request = spec.buildRequests(bannerRequest, bannerRequest[0]); - const payload = JSON.parse(request.data); - expect(payload.device.ua).to.not.be.empty; - expect(payload.device.language).to.not.be.empty; - }); - it('Test page and domain in site', function () { const request = spec.buildRequests(bannerRequest, bannerRequest[0]); const payload = JSON.parse(request.data); @@ -151,22 +113,7 @@ describe('Zeta Ssp Bid Adapter', function () { 'https://example2.com' ], h: 150, - w: 200, - ext: { - bidtype: 'video' - } - }, - { - id: 'auctionId3', - impid: 'impId3', - price: 0.2, - adm: '', - crid: 'creativeId3', - adomain: [ - 'https://example3.com' - ], - h: 400, - w: 300 + w: 200 } ] } @@ -182,8 +129,6 @@ describe('Zeta Ssp Bid Adapter', function () { const receivedBid1 = response.body.seatbid[0].bid[0]; expect(bid1).to.not.be.empty; expect(bid1.ad).to.equal(receivedBid1.adm); - expect(bid1.vastXml).to.be.undefined; - expect(bid1.mediaType).to.equal(BANNER); expect(bid1.cpm).to.equal(receivedBid1.price); expect(bid1.height).to.equal(receivedBid1.h); expect(bid1.width).to.equal(receivedBid1.w); @@ -194,25 +139,11 @@ describe('Zeta Ssp Bid Adapter', function () { const receivedBid2 = response.body.seatbid[0].bid[1]; expect(bid2).to.not.be.empty; expect(bid2.ad).to.equal(receivedBid2.adm); - expect(bid2.vastXml).to.equal(receivedBid2.adm); - expect(bid2.mediaType).to.equal(VIDEO); expect(bid2.cpm).to.equal(receivedBid2.price); expect(bid2.height).to.equal(receivedBid2.h); expect(bid2.width).to.equal(receivedBid2.w); expect(bid2.requestId).to.equal(receivedBid2.impid); expect(bid2.meta.advertiserDomains).to.equal(receivedBid2.adomain); - - const bid3 = bidResponse[2]; - const receivedBid3 = response.body.seatbid[0].bid[2]; - expect(bid3).to.not.be.empty; - expect(bid3.ad).to.equal(receivedBid3.adm); - expect(bid3.vastXml).to.equal(receivedBid3.adm); - expect(bid3.mediaType).to.equal(VIDEO); - expect(bid3.cpm).to.equal(receivedBid3.price); - expect(bid3.height).to.equal(receivedBid3.h); - expect(bid3.width).to.equal(receivedBid3.w); - expect(bid3.requestId).to.equal(receivedBid3.impid); - expect(bid3.meta.advertiserDomains).to.equal(receivedBid3.adomain); }); it('Different cases for user syncs', function () { @@ -255,18 +186,4 @@ describe('Zeta Ssp Bid Adapter', function () { expect(payload.user.buyeruid).to.eql(333); expect(payload.user.ext.consent).to.eql('consentString'); }); - - it('Test video object', function () { - const request = spec.buildRequests(videoRequest, videoRequest[0]); - const payload = JSON.parse(request.data); - - expect(payload.imp[0].video.minduration).to.eql(videoRequest[0].mediaTypes.video.minduration); - expect(payload.imp[0].video.maxduration).to.eql(videoRequest[0].mediaTypes.video.maxduration); - expect(payload.imp[0].video.protocols).to.eql(videoRequest[0].mediaTypes.video.protocols); - expect(payload.imp[0].video.mimes).to.eql(videoRequest[0].mediaTypes.video.mimes); - expect(payload.imp[0].video.w).to.eql(720); - expect(payload.imp[0].video.h).to.eql(340); - - expect(payload.imp[0].banner).to.be.undefined; - }); }); diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index 66e11b9a472..0ffef30965b 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -1,19 +1,10 @@ import { expect } from 'chai'; -import { - fireNativeTrackers, - getNativeTargeting, - nativeBidIsValid, - getAssetMessage, - getAllAssetsMessage, - decorateAdUnitsWithNativeParams -} from 'src/native.js'; +import { fireNativeTrackers, getNativeTargeting, nativeBidIsValid, getAssetMessage, getAllAssetsMessage } from 'src/native.js'; import CONSTANTS from 'src/constants.json'; -import {stubAuctionIndex} from '../helpers/indexStub.js'; const utils = require('src/utils'); const bid = { adId: '123', - transactionId: 'au', native: { title: 'Native Creative', body: 'Cool description great stuff', @@ -41,7 +32,6 @@ const bid = { }; const bidWithUndefinedFields = { - transactionId: 'au', native: { title: 'Native Creative', body: undefined, @@ -62,10 +52,6 @@ describe('native.js', function () { let triggerPixelStub; let insertHtmlIntoIframeStub; - function deps(adUnit) { - return { index: stubAuctionIndex({ adUnits: [adUnit] }) }; - } - beforeEach(function () { triggerPixelStub = sinon.stub(utils, 'triggerPixel'); insertHtmlIntoIframeStub = sinon.stub(utils, 'insertHtmlIntoIframe'); @@ -85,8 +71,7 @@ describe('native.js', function () { }); it('sends placeholders for configured assets', function () { - const adUnit = { - transactionId: 'au', + const bidRequest = { nativeParams: { body: { sendId: true }, clickUrl: { sendId: true }, @@ -100,7 +85,7 @@ describe('native.js', function () { } } }; - const targeting = getNativeTargeting(bid, deps(adUnit)); + const targeting = getNativeTargeting(bid, bidRequest); expect(targeting[CONSTANTS.NATIVE_KEYS.title]).to.equal(bid.native.title); expect(targeting[CONSTANTS.NATIVE_KEYS.body]).to.equal('hb_native_body:123'); @@ -110,8 +95,7 @@ describe('native.js', function () { }); it('should only include native targeting keys with values', function () { - const adUnit = { - transactionId: 'au', + const bidRequest = { nativeParams: { body: { sendId: true }, clickUrl: { sendId: true }, @@ -126,7 +110,7 @@ describe('native.js', function () { } }; - const targeting = getNativeTargeting(bidWithUndefinedFields, deps(adUnit)); + const targeting = getNativeTargeting(bidWithUndefinedFields, bidRequest); expect(Object.keys(targeting)).to.deep.equal([ CONSTANTS.NATIVE_KEYS.title, @@ -137,8 +121,7 @@ describe('native.js', function () { }); it('should only include targeting that has sendTargetingKeys set to true', function () { - const adUnit = { - transactionId: 'au', + const bidRequest = { nativeParams: { image: { required: true, @@ -153,7 +136,7 @@ describe('native.js', function () { } }; - const targeting = getNativeTargeting(bid, deps(adUnit)); + const targeting = getNativeTargeting(bid, bidRequest); expect(Object.keys(targeting)).to.deep.equal([ CONSTANTS.NATIVE_KEYS.title @@ -161,8 +144,7 @@ describe('native.js', function () { }); it('should only include targeting if sendTargetingKeys not set to false', function () { - const adUnit = { - transactionId: 'au', + const bidRequest = { nativeParams: { image: { required: true, @@ -199,7 +181,7 @@ describe('native.js', function () { } }; - const targeting = getNativeTargeting(bid, deps(adUnit)); + const targeting = getNativeTargeting(bid, bidRequest); expect(Object.keys(targeting)).to.deep.equal([ CONSTANTS.NATIVE_KEYS.title, @@ -211,8 +193,7 @@ describe('native.js', function () { }); it('should copy over rendererUrl to bid object and include it in targeting', function () { - const adUnit = { - transactionId: 'au', + const bidRequest = { nativeParams: { image: { required: true, @@ -228,7 +209,7 @@ describe('native.js', function () { } }; - const targeting = getNativeTargeting(bid, deps(adUnit)); + const targeting = getNativeTargeting(bid, bidRequest); expect(Object.keys(targeting)).to.deep.equal([ CONSTANTS.NATIVE_KEYS.title, @@ -246,8 +227,7 @@ describe('native.js', function () { }); it('should copy over adTemplate to bid object and include it in targeting', function () { - const adUnit = { - transactionId: 'au', + const bidRequest = { nativeParams: { image: { required: true, @@ -261,7 +241,7 @@ describe('native.js', function () { } }; - const targeting = getNativeTargeting(bid, deps(adUnit)); + const targeting = getNativeTargeting(bid, bidRequest); expect(Object.keys(targeting)).to.deep.equal([ CONSTANTS.NATIVE_KEYS.title, @@ -394,33 +374,35 @@ describe('native.js', function () { }); describe('validate native', function () { - const adUnit = { - transactionId: 'test_adunit', - mediaTypes: { - native: { - title: { - required: true, - }, - body: { - required: true, - }, - image: { - required: true, - sizes: [150, 50], - aspect_ratios: [150, 50] - }, - icon: { - required: true, - sizes: [50, 50] - }, + let bidReq = [{ + bids: [{ + bidderCode: 'test_bidder', + bidId: 'test_bid_id', + mediaTypes: { + native: { + title: { + required: true, + }, + body: { + required: true, + }, + image: { + required: true, + sizes: [150, 50], + aspect_ratios: [150, 50] + }, + icon: { + required: true, + sizes: [50, 50] + }, + } } - } - } + }] + }]; let validBid = { adId: 'abc123', requestId: 'test_bid_id', - transactionId: 'test_adunit', adUnitCode: '123/prebid_native_adunit', bidder: 'test_bidder', native: { @@ -446,7 +428,6 @@ describe('validate native', function () { let noIconDimBid = { adId: 'abc234', requestId: 'test_bid_id', - transactionId: 'test_adunit', adUnitCode: '123/prebid_native_adunit', bidder: 'test_bidder', native: { @@ -468,7 +449,6 @@ describe('validate native', function () { let noImgDimBid = { adId: 'abc345', requestId: 'test_bid_id', - transactionId: 'test_adunit', adUnitCode: '123/prebid_native_adunit', bidder: 'test_bidder', native: { @@ -492,13 +472,11 @@ describe('validate native', function () { afterEach(function () {}); it('should accept bid if no image sizes are defined', function () { - decorateAdUnitsWithNativeParams([adUnit]); - const index = stubAuctionIndex({adUnits: [adUnit]}) - let result = nativeBidIsValid(validBid, {index}); + let result = nativeBidIsValid(validBid, bidReq); expect(result).to.be.true; - result = nativeBidIsValid(noIconDimBid, {index}); + result = nativeBidIsValid(noIconDimBid, bidReq); expect(result).to.be.true; - result = nativeBidIsValid(noImgDimBid, {index}); + result = nativeBidIsValid(noImgDimBid, bidReq); expect(result).to.be.true; }); }); diff --git a/test/spec/renderer_spec.js b/test/spec/renderer_spec.js index 6de06606136..50e21d2cb36 100644 --- a/test/spec/renderer_spec.js +++ b/test/spec/renderer_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { Renderer, executeRenderer } from 'src/Renderer.js'; +import { Renderer } from 'src/Renderer.js'; import * as utils from 'src/utils.js'; import { loadExternalScript } from 'src/adloader.js'; require('test/mocks/adloaderStub.js'); @@ -212,20 +212,5 @@ describe('Renderer', function () { testRenderer.render() expect(loadExternalScript.called).to.be.true; }); - - it('call\'s documentResolver when configured', function () { - const documentResolver = sinon.spy(function(bid, sDoc, tDoc) { - return document; - }); - - let testRenderer = Renderer.install({ - url: 'https://httpbin.org/post', - config: { documentResolver: documentResolver } - }); - - executeRenderer(testRenderer, {}, {}); - - expect(documentResolver.called).to.be.true; - }); }); }); diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js index c4efbddad6d..a3c39a52441 100644 --- a/test/spec/sizeMapping_spec.js +++ b/test/spec/sizeMapping_spec.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { resolveStatus, setSizeConfig, sizeSupported } from 'src/sizeMapping.js'; -import {includes} from 'src/polyfill.js' +import includes from 'core-js-pure/features/array/includes.js'; let utils = require('src/utils'); let deepClone = utils.deepClone; diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 88beaa88a67..f33c9139e5f 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -1,11 +1,5 @@ import { expect } from 'chai'; -import adapterManager, { - gdprDataHandler, - coppaDataHandler, - _partitionBidders, - PARTITIONS, - getS2SBidderSet, _filterBidsForAdUnit -} from 'src/adapterManager.js'; +import adapterManager, { allS2SBidders, clientTestAdapters, gdprDataHandler, coppaDataHandler } from 'src/adapterManager.js'; import { getAdUnits, getServerTestingConfig, @@ -17,9 +11,9 @@ import * as utils from 'src/utils.js'; import { config } from 'src/config.js'; import { registerBidder } from 'src/adapters/bidderFactory.js'; import { setSizeConfig } from 'src/sizeMapping.js'; -import {find, includes} from 'src/polyfill.js'; +import find from 'core-js-pure/features/array/find.js'; +import includes from 'core-js-pure/features/array/includes.js'; import s2sTesting from 'modules/s2sTesting.js'; -import {hook} from '../../../../src/hook.js'; var events = require('../../../../src/events'); const CONFIG = { @@ -93,14 +87,9 @@ describe('adapterManager tests', function () { config.setConfig({s2sConfig: { enabled: false }}); }); - afterEach(() => { - s2sTesting.clientTestBidders.clear(); - }); - describe('callBids', function () { before(function () { config.setConfig({s2sConfig: { enabled: false }}); - hook.ready(); }); beforeEach(function () { @@ -173,7 +162,7 @@ describe('adapterManager tests', function () { 'bidderCode': 'appnexus', 'auctionId': '1863e370099523', 'bidderRequestId': '2946b569352ef2', - 'uniquePbsTid': '34566b569352ef2', + 'tid': '34566b569352ef2', 'bids': [ { 'bidder': 'appnexus', @@ -447,38 +436,6 @@ describe('adapterManager tests', function () { }); }); // end onBidViewable - describe('onBidderError', function () { - const bidder = 'appnexus'; - const appnexusSpec = { onBidderError: sinon.stub() }; - const appnexusAdapter = { - bidder, - getSpec: function() { return appnexusSpec; }, - } - before(function () { - config.setConfig({s2sConfig: { enabled: false }}); - }); - - beforeEach(function () { - adapterManager.bidderRegistry[bidder] = appnexusAdapter; - }); - - afterEach(function () { - delete adapterManager.bidderRegistry[bidder]; - }); - - it('should call spec\'s onBidderError callback when callBidderError is called', function () { - const bidRequests = getBidRequests(); - const bidderRequest = find(bidRequests, bidRequest => bidRequest.bidderCode === bidder); - const xhrErrorMock = { - status: 500, - statusText: 'Internal Server Error' - }; - adapterManager.callBidderError(bidder, xhrErrorMock, bidderRequest); - sinon.assert.calledOnce(appnexusSpec.onBidderError); - sinon.assert.calledWithExactly(appnexusSpec.onBidderError, { error: xhrErrorMock, bidderRequest }); - }); - }); // end onBidderError - describe('S2S tests', function () { beforeEach(function () { config.setConfig({s2sConfig: CONFIG}); @@ -490,7 +447,7 @@ describe('adapterManager tests', function () { 'bidderCode': 'appnexus', 'auctionId': '1863e370099523', 'bidderRequestId': '2946b569352ef2', - 'uniquePbsTid': '34566b569352ef2', + 'tid': '34566b569352ef2', 'timeout': 1000, 'src': 's2s', 'adUnitsS2SCopy': [ @@ -711,11 +668,15 @@ describe('adapterManager tests', function () { prebidServerAdapterMock.callBids.reset(); }); + afterEach(function () { + allS2SBidders.length = 0; + }); + const bidRequests = [{ 'bidderCode': 'appnexus', 'auctionId': '1863e370099523', 'bidderRequestId': '2946b569352ef2', - 'uniquePbsTid': '34566b569352ef2', + 'tid': '34566b569352ef2', 'timeout': 1000, 'src': 's2s', 'adUnitsS2SCopy': [ @@ -851,7 +812,7 @@ describe('adapterManager tests', function () { 'bidderCode': 'pubmatic', 'auctionId': '1863e370099523', 'bidderRequestId': '2946b569352ef2', - 'uniquePbsTid': '2342342342lfi23', + 'tid': '2342342342lfi23', 'timeout': 1000, 'src': 's2s', 'adUnitsS2SCopy': [ @@ -1048,21 +1009,6 @@ describe('adapterManager tests', function () { sinon.assert.calledTwice(prebidServerAdapterMock.callBids); }); - it('should have one tid for ALL s2s bidRequests', function () { - let adUnits = utils.deepClone(getAdUnits()).map(adUnit => { - adUnit.bids = adUnit.bids.filter(bid => includes(['appnexus', 'pubmatic'], bid.bidder)); - return adUnit; - }) - let bidRequests = adapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); - adapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); - sinon.assert.calledTwice(prebidServerAdapterMock.callBids); - const firstBid = prebidServerAdapterMock.callBids.firstCall.args[0]; - const secondBid = prebidServerAdapterMock.callBids.secondCall.args[0]; - - // TIDS should be the same - expect(firstBid.tid).to.equal(secondBid.tid); - }); - it('should fire for simultaneous s2s and client requests', function () { adapterManager.bidderRegistry['adequant'] = adequantAdapterMock; let adUnits = utils.deepClone(getAdUnits()).map(adUnit => { @@ -1311,6 +1257,9 @@ describe('adapterManager tests', function () { } beforeEach(function () { + allS2SBidders.length = 0; + clientTestAdapters.length = 0 + adapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; adapterManager.bidderRegistry['adequant'] = adequantAdapterMock; adapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; @@ -1665,32 +1614,13 @@ describe('adapterManager tests', function () { describe('makeBidRequests', function () { let adUnits; beforeEach(function () { + allS2SBidders.length = 0 adUnits = utils.deepClone(getAdUnits()).map(adUnit => { adUnit.bids = adUnit.bids.filter(bid => includes(['appnexus', 'rubicon'], bid.bidder)); return adUnit; }) }); - it('should add nativeParams to adUnits after BEFORE_REQUEST_BIDS', () => { - function beforeReqBids(adUnits) { - adUnits.forEach(adUnit => { - adUnit.mediaTypes.native = { - type: 'image', - } - }) - } - events.on(CONSTANTS.EVENTS.BEFORE_REQUEST_BIDS, beforeReqBids); - adapterManager.makeBidRequests( - adUnits, - Date.now(), - utils.getUniqueIdentifierStr(), - function callback() {}, - [] - ); - events.off(CONSTANTS.EVENTS.BEFORE_REQUEST_BIDS, beforeReqBids); - expect(adUnits.map((u) => u.nativeParams).some(i => i == null)).to.be.false; - }); - it('should make separate bidder request objects for each bidder', () => { adUnits = [utils.deepClone(getAdUnits()[0])]; @@ -1735,15 +1665,14 @@ describe('adapterManager tests', function () { }); describe('sizeMapping', function () { - let sandbox; beforeEach(function () { - sandbox = sinon.sandbox.create(); - // always have matchMedia return true for us - sandbox.stub(utils.getWindowTop(), 'matchMedia').callsFake(() => ({matches: true})); + allS2SBidders.length = 0; + clientTestAdapters.length = 0; + sinon.stub(window, 'matchMedia').callsFake(() => ({matches: true})); }); afterEach(function () { - sandbox.restore(); + matchMedia.restore(); config.resetConfig(); setSizeConfig([]); }); @@ -1913,7 +1842,7 @@ describe('adapterManager tests', function () { ['visitor-uk', 'desktop'] ); - // only one adUnit and one bid from that adUnit should make it through the applied labels above + // only one adUnit and one bid from that adUnit should make it through the applied labels above expect(bidRequests.length).to.equal(1); expect(bidRequests[0].bidderCode).to.equal('rubicon'); expect(bidRequests[0].bids.length).to.equal(1); @@ -1997,6 +1926,7 @@ describe('adapterManager tests', function () { describe('s2sTesting - testServerOnly', () => { beforeEach(() => { config.setConfig({ s2sConfig: getServerTestingConfig(CONFIG) }); + allS2SBidders.length = 0 s2sTesting.bidSource = {}; }); @@ -2127,6 +2057,7 @@ describe('adapterManager tests', function () { afterEach(() => { config.resetConfig() + allS2SBidders.length = 0; s2sTesting.bidSource = {}; }); @@ -2306,102 +2237,4 @@ describe('adapterManager tests', function () { ); }); }); - - describe('getS2SBidderSet', () => { - it('should always return the "null" bidder', () => { - expect([...getS2SBidderSet({bidders: []})]).to.eql([null]); - }); - - it('should not consider disabled s2s adapters', () => { - const actual = getS2SBidderSet([{enabled: false, bidders: ['A', 'B']}, {enabled: true, bidders: ['C']}]); - expect([...actual]).to.include.members(['C']); - expect([...actual]).not.to.include.members(['A', 'B']); - }); - - it('should accept both single config objects and an array of them', () => { - const conf = {enabled: true, bidders: ['A', 'B']}; - expect(getS2SBidderSet(conf)).to.eql(getS2SBidderSet([conf])); - }); - }); - - describe('separation of client and server bidders', () => { - let s2sBidders, getS2SBidders; - beforeEach(() => { - s2sBidders = null; - getS2SBidders = sinon.stub(); - getS2SBidders.callsFake(() => s2sBidders); - }) - - describe('partitionBidders', () => { - let adUnits; - - beforeEach(() => { - adUnits = [{ - bids: [{ - bidder: 'A' - }, { - bidder: 'B' - }] - }, { - bids: [{ - bidder: 'A', - }, { - bidder: 'C' - }] - }]; - }); - - function partition(adUnits, s2sConfigs) { - return _partitionBidders(adUnits, s2sConfigs, {getS2SBidders}) - } - - Object.entries({ - 'all client': { - s2s: [], - expected: { - [PARTITIONS.CLIENT]: ['A', 'B', 'C'], - [PARTITIONS.SERVER]: [] - } - }, - 'all server': { - s2s: ['A', 'B', 'C'], - expected: { - [PARTITIONS.CLIENT]: [], - [PARTITIONS.SERVER]: ['A', 'B', 'C'] - } - }, - 'mixed': { - s2s: ['B', 'C'], - expected: { - [PARTITIONS.CLIENT]: ['A'], - [PARTITIONS.SERVER]: ['B', 'C'] - } - } - }).forEach(([test, {s2s, expected}]) => { - it(`should partition ${test} requests`, () => { - s2sBidders = new Set(s2s); - const s2sConfig = {}; - expect(partition(adUnits, s2sConfig)).to.eql(expected); - sinon.assert.calledWith(getS2SBidders, sinon.match.same(s2sConfig)); - }); - }); - }); - - describe('filterBidsForAdUnit', () => { - function filterBids(bids, s2sConfig) { - return _filterBidsForAdUnit(bids, s2sConfig, {getS2SBidders}); - } - it('should not filter any bids when s2sConfig == null', () => { - const bids = ['untouched', 'data']; - expect(filterBids(bids)).to.eql(bids); - }); - - it('should remove bids that have bidder not present in s2sConfig', () => { - s2sBidders = new Set('A', 'B'); - const s2sConfig = {}; - expect(filterBids(['A', 'C', 'D'].map((code) => ({bidder: code})), s2sConfig)).to.eql([{bidder: 'A'}]); - sinon.assert.calledWith(getS2SBidders, sinon.match.same(s2sConfig)); - }) - }); - }); }); diff --git a/test/spec/unit/core/auctionIndex_spec.js b/test/spec/unit/core/auctionIndex_spec.js deleted file mode 100644 index f00e2cd281f..00000000000 --- a/test/spec/unit/core/auctionIndex_spec.js +++ /dev/null @@ -1,129 +0,0 @@ -import {AuctionIndex} from '../../../../src/auctionIndex.js'; - -describe('auction index', () => { - let index, auctions; - - function mockAuction(id, adUnits, bidderRequests) { - return { - getAuctionId() { return id }, - getAdUnits() { return adUnits; }, - getBidRequests() { return bidderRequests; } - } - } - - beforeEach(() => { - auctions = []; - index = new AuctionIndex(() => auctions); - }) - - describe('getAuction', () => { - beforeEach(() => { - auctions = [mockAuction('a1'), mockAuction('a2')]; - }); - - it('should find auctions by auctionId', () => { - expect(index.getAuction({auctionId: 'a1'})).to.equal(auctions[0]); - }); - - it('should return undef if auction is missing', () => { - expect(index.getAuction({auctionId: 'missing'})).to.be.undefined; - }); - - it('should return undef if no auctionId is provided', () => { - expect(index.getAuction({})).to.be.undefined; - }); - }); - - describe('getAdUnit', () => { - let adUnits; - - beforeEach(() => { - adUnits = [{transactionId: 'au1'}, {transactionId: 'au2'}]; - auctions = [ - mockAuction('a1', [adUnits[0], {}]), - mockAuction('a2', [adUnits[1]]) - ]; - }); - - it('should find adUnits by transactionId', () => { - expect(index.getAdUnit({transactionId: 'au2'})).to.equal(adUnits[1]); - }); - - it('should return undefined if adunit is missing', () => { - expect(index.getAdUnit({transactionId: 'missing'})).to.be.undefined; - }); - - it('should return undefined if no transactionId is provided', () => { - expect(index.getAdUnit({})).to.be.undefined; - }); - }); - - describe('getBidRequest', () => { - let bidRequests; - beforeEach(() => { - bidRequests = [{bidId: 'b1'}, {bidId: 'b2'}]; - auctions = [ - mockAuction('a1', [], [{bids: [bidRequests[0], {}]}]), - mockAuction('a2', [], [{bids: [bidRequests[1]]}]) - ] - }); - - it('should find bidRequests by requestId', () => { - expect(index.getBidRequest({requestId: 'b2'})).to.equal(bidRequests[1]); - }); - - it('should return undef if bidRequest is missing', () => { - expect(index.getBidRequest({requestId: 'missing'})).to.be.undefined; - }); - - it('should return undef if no requestId is provided', () => { - expect(index.getBidRequest({})).to.be.undefined; - }); - }); - - describe('getMediaTypes', () => { - let bidderRequests, mediaTypes, adUnits; - - beforeEach(() => { - mediaTypes = [{mockMT: '1'}, {mockMT: '2'}, {mockMT: '3'}, {mockMT: '4'}] - adUnits = [ - {transactionId: 'au1', mediaTypes: mediaTypes[0]}, - {transactionId: 'au2', mediaTypes: mediaTypes[1]} - ] - bidderRequests = [ - {bidderRequestId: 'ber1', bids: [{bidId: 'b1', mediaTypes: mediaTypes[2], transactionId: 'au1'}, {}]}, - {bidderRequestId: 'ber2', bids: [{bidId: 'b2', mediaTypes: mediaTypes[3], transactionId: 'au2'}]} - ] - auctions = [ - mockAuction('a1', [adUnits[0]], [bidderRequests[0], {}]), - mockAuction('a2', [adUnits[1]], [bidderRequests[1]]) - ] - }); - - it('should find mediaTypes by transactionId', () => { - expect(index.getMediaTypes({transactionId: 'au2'})).to.equal(mediaTypes[1]); - }); - - it('should find mediaTypes by requestId', () => { - expect(index.getMediaTypes({requestId: 'b1'})).to.equal(mediaTypes[2]); - }); - - it('should give precedence to request.mediaTypes over adUnit.mediaTypes', () => { - expect(index.getMediaTypes({requestId: 'b2', transactionId: 'au2'})).to.equal(mediaTypes[3]); - }); - - it('should return undef if requestId and transactionId do not match', () => { - expect(index.getMediaTypes({requestId: 'b1', transactionId: 'au2'})).to.be.undefined; - }); - - it('should return undef if no params are provided', () => { - expect(index.getMediaTypes({})).to.be.undefined; - }); - - ['requestId', 'transactionId'].forEach(param => { - it(`should return undef if ${param} is missing`, () => { - expect(index.getMediaTypes({[param]: 'missing'})).to.be.undefined; - }); - }) - }); -}); diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 20a545a51d4..a7e8a0d7871 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -6,12 +6,6 @@ import { userSync } from 'src/userSync.js' import * as utils from 'src/utils.js'; import { config } from 'src/config.js'; import { server } from 'test/mocks/xhr.js'; -import CONSTANTS from 'src/constants.json'; -import * as events from 'src/events.js'; -import {hook} from '../../../../src/hook.js'; -import {auctionManager} from '../../../../src/auctionManager.js'; -import {stubAuctionIndex} from '../../../helpers/indexStub.js'; -import { bidderSettings } from '../../../../src/bidderSettings.js'; const CODE = 'sampleBidder'; const MOCK_BIDS_REQUEST = { @@ -47,10 +41,6 @@ describe('bidders created by newBidder', function () { let addBidResponseStub; let doneStub; - before(() => { - hook.ready(); - }); - beforeEach(function () { spec = { code: CODE, @@ -67,22 +57,17 @@ describe('bidders created by newBidder', function () { describe('when the ajax response is irrelevant', function () { let ajaxStub; let getConfigSpy; - let aliasRegistryStub, aliasRegistry; beforeEach(function () { ajaxStub = sinon.stub(ajax, 'ajax'); addBidResponseStub.reset(); getConfigSpy = sinon.spy(config, 'getConfig'); doneStub.reset(); - aliasRegistry = {}; - aliasRegistryStub = sinon.stub(adapterManager, 'aliasRegistry'); - aliasRegistryStub.get(() => aliasRegistry); }); afterEach(function () { ajaxStub.restore(); getConfigSpy.restore(); - aliasRegistryStub.restore(); }); it('should let registerSyncs run with invalid alias and aliasSync enabled', function () { @@ -129,7 +114,6 @@ describe('bidders created by newBidder', function () { }); spec.code = 'aliasBidder'; const bidder = newBidder(spec); - aliasRegistry = {[spec.code]: CODE}; bidder.callBids({ bids: [] }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(getConfigSpy.withArgs('userSync.filterSettings').calledOnce).to.equal(false); }); @@ -330,28 +314,6 @@ describe('bidders created by newBidder', function () { expect(addBidResponseStub.callCount).to.equal(0); }); - - it('should emit BEFORE_BIDDER_HTTP events before network requests', function () { - const bidder = newBidder(spec); - const req = { - method: 'POST', - url: 'test.url.com', - data: { arg: 2 } - }; - - spec.isBidRequestValid.returns(true); - spec.buildRequests.returns([req, req]); - - const eventEmitterSpy = sinon.spy(events, 'emit'); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(ajaxStub.calledTwice).to.equal(true); - expect(eventEmitterSpy.getCalls() - .filter(call => call.args[0] === CONSTANTS.EVENTS.BEFORE_BIDDER_HTTP) - ).to.length(2); - - eventEmitterSpy.restore(); - }); }); describe('when the ajax call succeeds', function () { @@ -562,55 +524,21 @@ describe('bidders created by newBidder', function () { expect(logErrorSpy.calledOnce).to.equal(true); }); - - it('should require requestId from interpretResponse', () => { - const bidder = newBidder(spec); - const bid = { - 'ad': 'creative', - 'cpm': '1.99', - 'creativeId': 'some-id', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 360 - }; - spec.isBidRequestValid.returns(true); - spec.buildRequests.returns({ - method: 'POST', - url: 'test.url.com', - data: {} - }); - spec.getUserSyncs.returns([]); - spec.interpretResponse.returns(bid); - - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(addBidResponseStub.called).to.be.false; - }); }); describe('when the ajax call fails', function () { let ajaxStub; - let callBidderErrorStub; - let eventEmitterStub; - let xhrErrorMock = { - status: 500, - statusText: 'Internal Server Error' - }; beforeEach(function () { ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) { - callbacks.error('ajax call failed.', xhrErrorMock); + callbacks.error('ajax call failed.'); }); - callBidderErrorStub = sinon.stub(adapterManager, 'callBidderError'); - eventEmitterStub = sinon.stub(events, 'emit'); addBidResponseStub.reset(); doneStub.reset(); }); afterEach(function () { ajaxStub.restore(); - callBidderErrorStub.restore(); - eventEmitterStub.restore(); }); it('should not spec.interpretResponse()', function () { @@ -628,14 +556,6 @@ describe('bidders created by newBidder', function () { expect(spec.interpretResponse.called).to.equal(false); expect(doneStub.calledOnce).to.equal(true); - expect(callBidderErrorStub.calledOnce).to.equal(true); - expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE); - expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock); - expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST); - sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, { - error: xhrErrorMock, - bidderRequest: MOCK_BIDS_REQUEST - }); }); it('should not add bids for each adunit code into the auction', function () { @@ -654,40 +574,6 @@ describe('bidders created by newBidder', function () { expect(addBidResponseStub.callCount).to.equal(0); expect(doneStub.calledOnce).to.equal(true); - expect(callBidderErrorStub.calledOnce).to.equal(true); - expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE); - expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock); - expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST); - sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, { - error: xhrErrorMock, - bidderRequest: MOCK_BIDS_REQUEST - }); - }); - - it('should call spec.getUserSyncs() with no responses', function () { - const bidder = newBidder(spec); - - spec.isBidRequestValid.returns(true); - spec.buildRequests.returns({ - method: 'POST', - url: 'test.url.com', - data: {} - }); - spec.getUserSyncs.returns([]); - - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(spec.getUserSyncs.calledOnce).to.equal(true); - expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal([]); - expect(doneStub.calledOnce).to.equal(true); - expect(callBidderErrorStub.calledOnce).to.equal(true); - expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE); - expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock); - expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST); - sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, { - error: xhrErrorMock, - bidderRequest: MOCK_BIDS_REQUEST - }); }); it('should call spec.getUserSyncs() with no responses', function () { @@ -706,14 +592,6 @@ describe('bidders created by newBidder', function () { expect(spec.getUserSyncs.calledOnce).to.equal(true); expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal([]); expect(doneStub.calledOnce).to.equal(true); - expect(callBidderErrorStub.calledOnce).to.equal(true); - expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE); - expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock); - expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST); - sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, { - error: xhrErrorMock, - bidderRequest: MOCK_BIDS_REQUEST - }); }); }); }); @@ -821,7 +699,7 @@ describe('registerBidder', function () { describe('validate bid response: ', function () { let spec; - let indexStub, adUnits, bidderRequests; + let bidder; let addBidResponseStub; let doneStub; let ajaxStub; @@ -862,34 +740,25 @@ describe('validate bid response: ', function () { callbacks.success('response body', { getResponseHeader: fakeResponse }); }); logErrorSpy = sinon.spy(utils, 'logError'); - indexStub = sinon.stub(auctionManager, 'index'); - adUnits = []; - bidderRequests = []; - indexStub.get(() => stubAuctionIndex({adUnits: adUnits, bidderRequests: bidderRequests})) }); afterEach(function () { ajaxStub.restore(); logErrorSpy.restore(); - indexStub.restore; }); it('should add native bids that do have required assets', function () { - adUnits = [{ - transactionId: 'au', - nativeParams: { - title: {'required': true}, - } - }] let bidRequest = { bids: [{ bidId: '1', auctionId: 'first-bid-id', adUnitCode: 'mock/placement', - transactionId: 'au', params: { param: 5 }, + nativeParams: { + title: {'required': true}, + }, mediaType: 'native', }] }; @@ -916,24 +785,21 @@ describe('validate bid response: ', function () { }); it('should not add native bids that do not have required assets', function () { - adUnits = [{ - transactionId: 'au', - nativeParams: { - title: {'required': true}, - }, - }]; let bidRequest = { bids: [{ bidId: '1', auctionId: 'first-bid-id', adUnitCode: 'mock/placement', - transactionId: 'au', params: { param: 5 }, + nativeParams: { + title: {'required': true}, + }, mediaType: 'native', }] }; + let bids1 = Object.assign({}, bids[0], { @@ -955,21 +821,17 @@ describe('validate bid response: ', function () { }); it('should add bid when renderer is present on outstream bids', function () { - adUnits = [{ - transactionId: 'au', - mediaTypes: { - video: {context: 'outstream'} - } - }] let bidRequest = { bids: [{ bidId: '1', auctionId: 'first-bid-id', - transactionId: 'au', adUnitCode: 'mock/placement', params: { param: 5 }, + mediaTypes: { + video: {context: 'outstream'} + } }] }; @@ -1005,7 +867,7 @@ describe('validate bid response: ', function () { sizes: [[300, 250]], }] }; - bidderRequests = [bidRequest]; + let bids1 = Object.assign({}, bids[0], { @@ -1023,142 +885,6 @@ describe('validate bid response: ', function () { expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); expect(logErrorSpy.callCount).to.equal(0); }); - - describe(' Check for alternateBiddersList ', function() { - let bidRequest; - let bids1; - let logWarnSpy; - let bidderSettingStub, aliasRegistryStub; - let aliasRegistry; - - beforeEach(function () { - bidRequest = { - bids: [{ - bidId: '1', - bidder: CODE, - auctionId: 'first-bid-id', - adUnitCode: 'mock/placement', - transactionId: 'au', - }] - }; - - bids1 = Object.assign({}, - bids[0], - { - bidderCode: 'validAlternateBidder', - adapterCode: 'knownAdapter1' - } - ); - logWarnSpy = sinon.spy(utils, 'logWarn'); - bidderSettingStub = sinon.stub(bidderSettings, 'get'); - aliasRegistry = {}; - aliasRegistryStub = sinon.stub(adapterManager, 'aliasRegistry'); - aliasRegistryStub.get(() => aliasRegistry); - }); - - afterEach(function () { - logWarnSpy.restore(); - bidderSettingStub.restore(); - aliasRegistryStub.restore(); - }); - - it('should log warning when bidder is unknown and allowAlternateBidderCodes flag is false', function () { - bidderSettingStub.returns(false); - - const bidder = newBidder(spec); - spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(addBidResponseStub.calledOnce).to.equal(false); - expect(logWarnSpy.callCount).to.equal(1); - }); - - it('should accept the bid, when allowAlternateBidderCodes flag is undefined (default should be true)', function () { - bidderSettingStub.returns(undefined); - - const bidder = newBidder(spec); - spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(addBidResponseStub.calledOnce).to.equal(true); - expect(logWarnSpy.callCount).to.equal(0); - expect(logErrorSpy.callCount).to.equal(0); - }); - - it('should log warning when the particular bidder is not specified in allowedAlternateBidderCodes and allowAlternateBidderCodes flag is true', function () { - bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true); - bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns(['invalidAlternateBidder02']); - - const bidder = newBidder(spec); - spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(addBidResponseStub.calledOnce).to.equal(false); - expect(logWarnSpy.callCount).to.equal(1); - }); - - it('should accept the bid, when allowedAlternateBidderCodes is empty and allowAlternateBidderCodes flag is true', function () { - bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true); - bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns(); - - const bidder = newBidder(spec); - spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(addBidResponseStub.calledOnce).to.equal(true); - expect(logWarnSpy.callCount).to.equal(0); - expect(logErrorSpy.callCount).to.equal(0); - }); - - it('should accept the bid, when allowedAlternateBidderCodes is marked as * and allowAlternateBidderCodes flag is true', function () { - bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true); - bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns(['*']); - - const bidder = newBidder(spec); - spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(addBidResponseStub.calledOnce).to.equal(true); - expect(logWarnSpy.callCount).to.equal(0); - expect(logErrorSpy.callCount).to.equal(0); - }); - - it('should accept the bid, when allowedAlternateBidderCodes contains bidder name and allowAlternateBidderCodes flag is true', function () { - bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true); - bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns(['validAlternateBidder']); - - const bidder = newBidder(spec); - spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(addBidResponseStub.calledOnce).to.equal(true); - expect(logWarnSpy.callCount).to.equal(0); - expect(logErrorSpy.callCount).to.equal(0); - }); - - it('should not accept the bid, when bidder is an alias but bidderSetting is missing for the bidder. It should fallback to standard setting and reject the bid', function () { - bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(false); - aliasRegistry = {'validAlternateBidder': CODE}; - - const bidder = newBidder(spec); - spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(addBidResponseStub.calledOnce).to.equal(false); - expect(logWarnSpy.callCount).to.equal(1); - }); - - it('should not accept the bid, when bidderSetting is missing for the bidder. It should fallback to standard setting and reject the bid', function () { - bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(false); - - const bidder = newBidder(spec); - spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - - expect(addBidResponseStub.calledOnce).to.equal(false); - expect(logWarnSpy.callCount).to.equal(1); - }); - }) }); describe('preload mapping url hook', function() { diff --git a/test/spec/unit/core/bidderSettings_spec.js b/test/spec/unit/core/bidderSettings_spec.js deleted file mode 100644 index ece18040d1e..00000000000 --- a/test/spec/unit/core/bidderSettings_spec.js +++ /dev/null @@ -1,123 +0,0 @@ -import {bidderSettings, ScopedSettings} from '../../../../src/bidderSettings.js'; -import {expect} from 'chai'; -import * as prebidGlobal from '../../../../src/prebidGlobal'; -import sinon from 'sinon'; - -describe('ScopedSettings', () => { - let data; - let settings; - - beforeEach(() => { - settings = new ScopedSettings(() => data, 'fallback'); - }); - - describe('get', () => { - it('should retrieve setting from scope', () => { - data = { - scope: {key: 'value'} - }; - expect(settings.get('scope', 'key')).to.equal('value'); - }); - - it('should fallback to fallback scope', () => { - data = { - fallback: { - key: 'value' - } - }; - expect(settings.get('scope', 'key')).to.equal('value'); - }); - - it('should retrieve from default scope if scope is null', () => { - data = { - fallback: { - key: 'value' - } - }; - - expect(settings.get(null, 'key')).to.equal('value'); - }); - - it('should not fall back if own setting has a falsy value', () => { - data = { - scope: { - key: false, - }, - fallback: { - key: true - } - } - expect(settings.get('scope', 'key')).to.equal(false); - }) - }); - - describe('getOwn', () => { - it('should not fall back to default scope', () => { - data = { - fallback: { - key: 'value' - } - }; - expect(settings.getOwn('missing', 'key')).to.be.undefined; - }); - - it('should use default if scope is null', () => { - data = { - fallback: { - key: 'value' - } - }; - expect(settings.getOwn(null, 'key')).to.equal('value'); - }); - }); - - describe('getScopes', () => { - it('should return all top-level keys except the default scope', () => { - data = { - fallback: {}, - scope1: {}, - scope2: {}, - }; - expect(settings.getScopes()).to.have.members(['scope1', 'scope2']); - }); - }); - - describe('settingsFor', () => { - it('should merge with default scope', () => { - data = { - fallback: { - dkey: 'value' - }, - scope: { - skey: 'value' - } - } - expect(settings.settingsFor('scope')).to.eql({ - dkey: 'value', - skey: 'value' - }) - }) - }); -}); - -describe('bidderSettings', () => { - let sandbox; - beforeEach(() => { - sandbox = sinon.sandbox.create(); - sandbox.stub(prebidGlobal, 'getGlobal').returns({ - bidderSettings: { - scope: { - key: 'value' - } - } - }); - }) - - afterEach(() => { - sandbox.restore(); - }) - - it('should fetch data from getGlobal().bidderSettings', () => { - expect(bidderSettings.get('scope', 'key')).to.equal('value'); - }) -}); diff --git a/test/spec/unit/core/consentHandler_spec.js b/test/spec/unit/core/consentHandler_spec.js deleted file mode 100644 index 082ff34f90c..00000000000 --- a/test/spec/unit/core/consentHandler_spec.js +++ /dev/null @@ -1,59 +0,0 @@ -import {ConsentHandler} from '../../../../src/consentHandler.js'; - -describe('Consent data handler', () => { - let handler; - beforeEach(() => { - handler = new ConsentHandler(); - }) - - it('should be disabled, return null data on init', () => { - expect(handler.enabled).to.be.false; - expect(handler.getConsentData()).to.equal(null); - }) - - it('should resolve promise to null when disabled', () => { - return handler.promise.then((data) => { - expect(data).to.equal(null); - }); - }); - - it('should return data after setConsentData', () => { - const data = {consent: 'string'}; - handler.enable(); - handler.setConsentData(data); - expect(handler.getConsentData()).to.equal(data); - }); - - it('should resolve .promise to data after setConsentData', (done) => { - let actual = null; - const data = {consent: 'string'}; - handler.enable(); - handler.promise.then((d) => actual = d); - setTimeout(() => { - expect(actual).to.equal(null); - handler.setConsentData(data); - setTimeout(() => { - expect(actual).to.equal(data); - done(); - }) - }) - }); - - it('should resolve .promise to new data if setConsentData is called a second time', (done) => { - let actual = null; - const d1 = {data: '1'}; - const d2 = {data: '2'}; - handler.enable(); - handler.promise.then((d) => actual = d); - handler.setConsentData(d1); - setTimeout(() => { - expect(actual).to.equal(d1); - handler.setConsentData(d2); - handler.promise.then((d) => actual = d); - setTimeout(() => { - expect(actual).to.equal(d2); - done(); - }) - }) - }); -}) diff --git a/test/spec/unit/core/storageManager_spec.js b/test/spec/unit/core/storageManager_spec.js index 74a3b3b023f..5bb766217f5 100644 --- a/test/spec/unit/core/storageManager_spec.js +++ b/test/spec/unit/core/storageManager_spec.js @@ -1,19 +1,8 @@ -import { - resetData, - getCoreStorageManager, - storageCallbacks, - getStorageManager, - newStorageManager -} from 'src/storageManager.js'; +import { resetData, getCoreStorageManager, storageCallbacks, getStorageManager } from 'src/storageManager.js'; import { config } from 'src/config.js'; import * as utils from 'src/utils.js'; -import {hook} from '../../../../src/hook.js'; describe('storage manager', function() { - before(() => { - hook.ready(); - }); - beforeEach(function() { resetData(); }); @@ -106,62 +95,4 @@ describe('storage manager', function() { expect(localStorage.getItem('unrelated')).to.be.eq('dummy'); }); }); - - describe('when bidderSettings.allowStorage is defined', () => { - const DENIED_BIDDER = 'denied-bidder'; - const DENY_KEY = 'storageAllowed'; - - const COOKIE = 'test-cookie'; - const LS_KEY = 'test-localstorage'; - - function mockBidderSettings() { - return { - get(bidder, key) { - if (bidder === DENIED_BIDDER && key === DENY_KEY) { - return false; - } else { - return undefined; - } - } - } - } - - Object.entries({ - disallowed: [DENIED_BIDDER, false], - allowed: ['allowed-bidder', true] - }).forEach(([test, [bidderCode, shouldWork]]) => { - describe(`for ${test} bidders`, () => { - let mgr; - - beforeEach(() => { - mgr = newStorageManager({bidderCode: bidderCode}, {bidderSettings: mockBidderSettings()}); - }) - - afterEach(() => { - mgr.setCookie(COOKIE, 'delete', new Date().toUTCString()); - mgr.removeDataFromLocalStorage(LS_KEY); - }) - - const testDesc = (desc) => `should ${shouldWork ? '' : 'not'} ${desc}`; - - it(testDesc('allow cookies'), () => { - mgr.setCookie(COOKIE, 'value'); - expect(mgr.getCookie(COOKIE)).to.equal(shouldWork ? 'value' : null); - }); - - it(testDesc('allow localStorage'), () => { - mgr.setDataInLocalStorage(LS_KEY, 'value'); - expect(mgr.getDataFromLocalStorage(LS_KEY)).to.equal(shouldWork ? 'value' : null); - }); - - it(testDesc('report localStorage as available'), () => { - expect(mgr.hasLocalStorage()).to.equal(shouldWork); - }); - - it(testDesc('report cookies as available'), () => { - expect(mgr.cookiesAreEnabled()).to.equal(shouldWork); - }); - }); - }); - }) }); diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 53aa3b90fa8..f83bd2f6635 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -5,7 +5,6 @@ import { createBidReceived } from 'test/fixtures/fixtures.js'; import CONSTANTS from 'src/constants.json'; import { auctionManager } from 'src/auctionManager.js'; import * as utils from 'src/utils.js'; -import {deepClone} from 'src/utils.js'; const bid1 = { 'bidderCode': 'rubicon', @@ -228,8 +227,6 @@ describe('targeting tests', function () { let sandbox; let enableSendAllBids = false; let useBidCache; - let bidCacheFilterFunction; - let undef; beforeEach(function() { sandbox = sinon.sandbox.create(); @@ -244,16 +241,12 @@ describe('targeting tests', function () { if (key === 'useBidCache') { return useBidCache; } - if (key === 'bidCacheFilterFunction') { - return bidCacheFilterFunction; - } return origGetConfig.apply(config, arguments); }); }); afterEach(function () { sandbox.restore(); - bidCacheFilterFunction = undef; }); describe('getAllTargeting', function () { @@ -316,10 +309,10 @@ describe('targeting tests', function () { ['string', '2.3', '2.3'], ['number', 2.3, '2.3'], ['boolean', true, 'true'], - ['string-separated', '2.3, 4.5', '2.3,4.5'], - ['array-of-string', ['2.3', '4.5'], '2.3,4.5'], - ['array-of-number', [2.3, 4.5], '2.3,4.5'], - ['array-of-boolean', [true, false], 'true,false'] + ['string-separated', '2.3,4.5', '2.3, 4.5'], + ['array-of-string', ['2.3', '4.5'], '2.3, 4.5'], + ['array-of-number', [2.3, 4.5], '2.3, 4.5'], + ['array-of-boolean', [true, false], 'true, false'] ]; pairs.forEach(([type, value, result]) => { it(`accepts ${type}`, function() { @@ -468,50 +461,6 @@ describe('targeting tests', function () { }); }); - describe('targetingControls.allowZeroCpmBids', function () { - let bid4; - let bidderSettingsStorage; - - before(function() { - bidderSettingsStorage = $$PREBID_GLOBAL$$.bidderSettings; - }); - - beforeEach(function () { - bid4 = utils.deepClone(bid1); - bid4.adserverTargeting = { - hb_pb: '0.0', - hb_adid: '567891011', - hb_bidder: 'appnexus', - }; - bid4.bidder = bid4.bidderCode = 'appnexus'; - bid4.cpm = 0; - bidsReceived = [bid4]; - }); - - after(function() { - bidsReceived = [bid1, bid2, bid3]; - $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsStorage; - }) - - it('targeting should not include a 0 cpm by default', function() { - bid4.adserverTargeting = {}; - const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); - expect(targeting['/123456/header-bid-tag-0']).to.deep.equal({}); - }); - - it('targeting should allow a 0 cpm with targetingControls.allowZeroCpmBids set to true', function () { - $$PREBID_GLOBAL$$.bidderSettings = { - standard: { - allowZeroCpmBids: true - } - }; - - const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); - expect(targeting['/123456/header-bid-tag-0']).to.include.all.keys('hb_pb', 'hb_bidder', 'hb_adid', 'hb_bidder_appnexus', 'hb_adid_appnexus', 'hb_pb_appnexus'); - expect(targeting['/123456/header-bid-tag-0']['hb_pb']).to.equal('0.0') - }); - }); - describe('targetingControls.allowTargetingKeys', function () { let bid4; @@ -552,77 +501,6 @@ describe('targeting tests', function () { }); }); - describe('targetingControls.addTargetingKeys', function () { - let winningBid = null; - - beforeEach(function () { - bidsReceived = [bid1, bid2, nativeBid1, nativeBid2].map(deepClone); - bidsReceived.forEach((bid) => { - bid.adserverTargeting[CONSTANTS.TARGETING_KEYS.SOURCE] = 'test-source'; - bid.adUnitCode = 'adunit'; - if (winningBid == null || bid.cpm > winningBid.cpm) { - winningBid = bid; - } - }); - enableSendAllBids = true; - }); - - const expandKey = function (key) { - const keys = new Set(); - if (winningBid.adserverTargeting[key] != null) { - keys.add(key); - } - bidsReceived - .filter((bid) => bid.adserverTargeting[key] != null) - .map((bid) => bid.bidderCode) - .forEach((code) => keys.add(`${key}_${code}`.substr(0, 20))); - return new Array(...keys); - } - - const targetingResult = function () { - return targetingInstance.getAllTargeting(['adunit'])['adunit']; - } - - it('should include added keys', function () { - config.setConfig({ - targetingControls: { - addTargetingKeys: ['SOURCE'] - } - }); - expect(targetingResult()).to.include.all.keys(...expandKey(CONSTANTS.TARGETING_KEYS.SOURCE)); - }); - - it('should keep default and native keys', function() { - config.setConfig({ - targetingControls: { - addTargetingKeys: ['SOURCE'] - } - }); - const defaultKeys = new Set(Object.values(CONSTANTS.DEFAULT_TARGETING_KEYS)); - Object.values(CONSTANTS.NATIVE_KEYS).forEach((k) => defaultKeys.add(k)); - - const expectedKeys = new Set(); - bidsReceived - .map((bid) => Object.keys(bid.adserverTargeting)) - .reduce((left, right) => left.concat(right), []) - .filter((key) => defaultKeys.has(key)) - .map(expandKey) - .reduce((left, right) => left.concat(right), []) - .forEach((k) => expectedKeys.add(k)); - expect(targetingResult()).to.include.all.keys(...expectedKeys); - }); - - it('should not be allowed together with allowTargetingKeys', function () { - config.setConfig({ - targetingControls: { - allowTargetingKeys: [CONSTANTS.TARGETING_KEYS.BIDDER], - addTargetingKeys: [CONSTANTS.TARGETING_KEYS.SOURCE] - } - }); - expect(targetingResult).to.throw(); - }); - }); - describe('targetingControls.allowSendAllBidsTargetingKeys', function () { let bid4; @@ -907,93 +785,6 @@ describe('targeting tests', function () { expect(bids[0].adId).to.equal('adid-2'); }); - it('should use bidCacheFilterFunction', function() { - auctionManagerStub.returns([ - createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', mediaType: 'banner'}), - createBidReceived({bidder: 'appnexus', cpm: 5, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-2', mediaType: 'banner'}), - createBidReceived({bidder: 'appnexus', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-3', mediaType: 'banner'}), - createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4', mediaType: 'banner'}), - createBidReceived({bidder: 'appnexus', cpm: 27, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-2', adId: 'adid-5', mediaType: 'video'}), - createBidReceived({bidder: 'appnexus', cpm: 25, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-2', adId: 'adid-6', mediaType: 'video'}), - createBidReceived({bidder: 'appnexus', cpm: 26, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-3', adId: 'adid-7', mediaType: 'video'}), - createBidReceived({bidder: 'appnexus', cpm: 28, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-3', adId: 'adid-8', mediaType: 'video'}), - ]); - - let adUnitCodes = ['code-0', 'code-1', 'code-2', 'code-3']; - targetingInstance.setLatestAuctionForAdUnit('code-0', 2); - targetingInstance.setLatestAuctionForAdUnit('code-1', 2); - targetingInstance.setLatestAuctionForAdUnit('code-2', 2); - targetingInstance.setLatestAuctionForAdUnit('code-3', 2); - - // Bid Caching On, No Filter Function - useBidCache = true; - bidCacheFilterFunction = undef; - let bids = targetingInstance.getWinningBids(adUnitCodes); - - expect(bids.length).to.equal(4); - expect(bids[0].adId).to.equal('adid-1'); - expect(bids[1].adId).to.equal('adid-4'); - expect(bids[2].adId).to.equal('adid-5'); - expect(bids[3].adId).to.equal('adid-8'); - - // Bid Caching Off, No Filter Function - useBidCache = false; - bidCacheFilterFunction = undef; - bids = targetingInstance.getWinningBids(adUnitCodes); - - expect(bids.length).to.equal(4); - expect(bids[0].adId).to.equal('adid-2'); - expect(bids[1].adId).to.equal('adid-4'); - expect(bids[2].adId).to.equal('adid-6'); - expect(bids[3].adId).to.equal('adid-8'); - - // Bid Caching On AGAIN, No Filter Function (should be same as first time) - useBidCache = true; - bidCacheFilterFunction = undef; - bids = targetingInstance.getWinningBids(adUnitCodes); - - expect(bids.length).to.equal(4); - expect(bids[0].adId).to.equal('adid-1'); - expect(bids[1].adId).to.equal('adid-4'); - expect(bids[2].adId).to.equal('adid-5'); - expect(bids[3].adId).to.equal('adid-8'); - - // Bid Caching On, with Filter Function to Exclude video - useBidCache = true; - let bcffCalled = 0; - bidCacheFilterFunction = bid => { - bcffCalled++; - return bid.mediaType !== 'video'; - } - bids = targetingInstance.getWinningBids(adUnitCodes); - - expect(bids.length).to.equal(4); - expect(bids[0].adId).to.equal('adid-1'); - expect(bids[1].adId).to.equal('adid-4'); - expect(bids[2].adId).to.equal('adid-6'); - expect(bids[3].adId).to.equal('adid-8'); - // filter function should have been called for each cached bid (4 times) - expect(bcffCalled).to.equal(4); - - // Bid Caching Off, with Filter Function to Exclude video - // - should not use cached bids or call the filter function - useBidCache = false; - bcffCalled = 0; - bidCacheFilterFunction = bid => { - bcffCalled++; - return bid.mediaType !== 'video'; - } - bids = targetingInstance.getWinningBids(adUnitCodes); - - expect(bids.length).to.equal(4); - expect(bids[0].adId).to.equal('adid-2'); - expect(bids[1].adId).to.equal('adid-4'); - expect(bids[2].adId).to.equal('adid-6'); - expect(bids[3].adId).to.equal('adid-8'); - // filter function should not have been called - expect(bcffCalled).to.equal(0); - }); - it('should not use rendered bid to get winning bid', function () { let bidsReceived = [ createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'rendered'}), diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 6a7c79fe49d..199ce699dc8 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -15,10 +15,7 @@ import * as ajaxLib from 'src/ajax.js'; import * as auctionModule from 'src/auction.js'; import { registerBidder } from 'src/adapters/bidderFactory.js'; import { _sendAdToCreative } from 'src/secureCreatives.js'; -import {find} from 'src/polyfill.js'; -import {synchronizePromise} from '../../helpers/syncPromise.js'; -import 'src/prebid.js'; -import {hook} from '../../../src/hook.js'; +import find from 'core-js-pure/features/array/find.js'; var assert = require('chai').assert; var expect = require('chai').expect; @@ -78,10 +75,6 @@ var Slot = function Slot(elementId, pathId) { clearTargeting: function clearTargeting() { this.targeting = {}; return this; - }, - - updateTargetingFromMap: function updateTargetingFromMap(targetingMap) { - Object.keys(targetingMap).forEach(key => this.setTargeting(key, targetingMap[key])) } }; slot.spySetTargeting = sinon.spy(slot, 'setTargeting'); @@ -101,6 +94,7 @@ var createSlotArrayScenario2 = function createSlotArrayScenario2() { var slot1 = new Slot(config.adUnitElementIDs[0], config.adUnitCodes[0]); slot1.setTargeting('pos1', '750x350'); var slot2 = new Slot(config.adUnitElementIDs[1], config.adUnitCodes[0]); + slot2.setTargeting('gender', ['male', 'female']); return [ slot1, slot2 @@ -193,22 +187,13 @@ window.apntag = { } describe('Unit: Prebid Module', function () { - let bidExpiryStub, promiseSandbox; - - before(() => { - hook.ready(); - $$PREBID_GLOBAL$$.requestBids.getHooks().remove(); - }); - + let bidExpiryStub; beforeEach(function () { - promiseSandbox = sinon.createSandbox(); - synchronizePromise(promiseSandbox); bidExpiryStub = sinon.stub(filters, 'isBidNotExpired').callsFake(() => true); configObj.setConfig({ useBidCache: true }); }); afterEach(function() { - promiseSandbox.restore(); $$PREBID_GLOBAL$$.adUnits = []; bidExpiryStub.restore(); configObj.setConfig({ useBidCache: false }); @@ -434,7 +419,6 @@ describe('Unit: Prebid Module', function () { let bid; let auction; let ajaxStub; - let indexStub; let cbTimeout = 3000; let targeting; @@ -500,8 +484,7 @@ describe('Unit: Prebid Module', function () { ], 'bidId': '4d0a6829338a07', 'bidderRequestId': '331f3cf3f1d9c8', - 'auctionId': '20882439e3238c', - 'transactionId': 'trdiv-gpt-ad-1460505748561-0', + 'auctionId': '20882439e3238c' } ], 'auctionStart': 1505250713622, @@ -519,7 +502,6 @@ describe('Unit: Prebid Module', function () { let auctionManagerInstance = newAuctionManager(); targeting = newTargeting(auctionManagerInstance); let adUnits = [{ - transactionId: 'trdiv-gpt-ad-1460505748561-0', code: 'div-gpt-ad-1460505748561-0', sizes: [[300, 250], [300, 600]], bids: [{ @@ -531,8 +513,6 @@ describe('Unit: Prebid Module', function () { }]; let adUnitCodes = ['div-gpt-ad-1460505748561-0']; auction = auctionManagerInstance.createAuction({adUnits, adUnitCodes}); - indexStub = sinon.stub(auctionManager, 'index'); - indexStub.get(() => auctionManagerInstance.index); ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(function() { return function(url, callback) { const fakeResponse = sinon.stub(); @@ -544,7 +524,6 @@ describe('Unit: Prebid Module', function () { afterEach(function () { ajaxStub.restore(); - indexStub.restore(); }); it('should get correct ' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + ' when using bid.cpm is between 0 to 5', function() { @@ -584,7 +563,6 @@ describe('Unit: Prebid Module', function () { let cbTimeout = 3000; let auctionManagerInstance; let targeting; - let indexStub; const bannerResponse = { 'version': '0.0.1', @@ -663,7 +641,6 @@ describe('Unit: Prebid Module', function () { } const adUnit = { - transactionId: `tr${code}`, code: code, sizes: [[300, 250], [300, 600]], bids: [{ @@ -676,22 +653,22 @@ describe('Unit: Prebid Module', function () { let _mediaTypes = {}; if (mediaTypes.indexOf('banner') !== -1) { - Object.assign(_mediaTypes, { + _mediaTypes['banner'] = { 'banner': {} - }); + }; } if (mediaTypes.indexOf('video') !== -1) { - Object.assign(_mediaTypes, { + _mediaTypes['video'] = { 'video': { context: 'instream', playerSize: [300, 250] } - }); + }; } if (mediaTypes.indexOf('native') !== -1) { - Object.assign(_mediaTypes, { + _mediaTypes['native'] = { 'native': {} - }); + }; } if (Object.keys(_mediaTypes).length > 0) { @@ -753,41 +730,35 @@ describe('Unit: Prebid Module', function () { before(function () { currentPriceBucket = configObj.getConfig('priceGranularity'); - sinon.stub(adapterManager, 'makeBidRequests').callsFake(() => { - const br = { - 'bidderCode': 'appnexus', - 'auctionId': '20882439e3238c', - 'bidderRequestId': '331f3cf3f1d9c8', - 'bids': [ - { - 'bidder': 'appnexus', - 'params': { - 'placementId': '10433394' - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': 'trdiv-gpt-ad-1460505748561-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] + sinon.stub(adapterManager, 'makeBidRequests').callsFake(() => ([{ + 'bidderCode': 'appnexus', + 'auctionId': '20882439e3238c', + 'bidderRequestId': '331f3cf3f1d9c8', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'sizes': [ + [ + 300, + 250 ], - 'bidId': '4d0a6829338a07', - 'bidderRequestId': '331f3cf3f1d9c8', - 'auctionId': '20882439e3238c' - } - ], - 'auctionStart': 1505250713622, - 'timeout': 3000 - }; - const au = auction.getAdUnits().find((au) => au.transactionId === br.bids[0].transactionId); - br.bids[0].mediaTypes = Object.assign({}, au.mediaTypes); - return [br]; - }); + [ + 300, + 600 + ] + ], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }])); }); after(function () { @@ -795,14 +766,8 @@ describe('Unit: Prebid Module', function () { adapterManager.makeBidRequests.restore(); }) - beforeEach(() => { - indexStub = sinon.stub(auctionManager, 'index'); - indexStub.get(() => auctionManagerInstance.index); - }); - afterEach(function () { ajaxStub.restore(); - indexStub.restore(); }); it('should get correct ' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + ' with cpm between 0 - 5', function() { @@ -893,9 +858,6 @@ describe('Unit: Prebid Module', function () { it('should set googletag targeting keys after calling setTargetingForGPTAsync function', function () { var slots = createSlotArrayScenario2(); - - // explicitly setting some PBJS key value pairs to verify whether these are removed befor new keys are set - window.googletag.pubads().setSlots(slots); $$PREBID_GLOBAL$$.setTargetingForGPTAsync([config.adUnitCodes[0]]); @@ -903,7 +865,7 @@ describe('Unit: Prebid Module', function () { // googletag's targeting structure // googletag setTargeting will override old value if invoked with same key - let targeting = []; + const targeting = []; slots[1].getTargetingKeys().map(function (key) { const value = slots[1].getTargeting(key); targeting.push([key, value]); @@ -921,39 +883,6 @@ describe('Unit: Prebid Module', function () { invokedTargeting.push([key, value]); }); assert.deepEqual(targeting, invokedTargeting, 'google tag targeting options not matching'); - - // resetPresetTargeting: initiate a new auction with no winning bids, now old targeting should be removed - - resetAuction(); - auction.getBidsReceived = function() { return [] }; - - var slots = createSlotArrayScenario2(); - window.googletag.pubads().setSlots(slots); - - $$PREBID_GLOBAL$$.setTargetingForGPTAsync([config.adUnitCodes[0]]); - - targeting = []; - slots[1].getTargetingKeys().map(function (key) { - const value = slots[1].getTargeting(key); - targeting.push([key, value]); - }); - - invokedTargetingMap = {}; - slots[1].spySetTargeting.args.map(function (entry) { - invokedTargetingMap[entry[0]] = entry[1]; - }); - - var invokedTargeting = []; - - Object.getOwnPropertyNames(invokedTargetingMap).map(function (key) { - const value = Array.isArray(invokedTargetingMap[key]) ? invokedTargetingMap[key] : [invokedTargetingMap[key]]; // values are always returned as array in googletag - invokedTargeting.push([key, value]); - }); - assert.deepEqual(targeting, invokedTargeting, 'google tag targeting options not matching'); - targeting.forEach(function(e) { - // here e[0] is key and e[1] is value in array that should be [null] as we are un-setting prebid keys in resetPresetTargeting - assert.deepEqual(e[1], [null], 'resetPresetTargeting: the value of the key ' + e[0] + ' should be [null]'); - }); }); it('should set googletag targeting keys to specific slot with customSlotMatching', function () { @@ -1034,7 +963,12 @@ describe('Unit: Prebid Module', function () { adUnitCode: config.adUnitCodes[0], }; - _sendAdToCreative(mockAdObject, sinon.stub()); + const event = { + source: { postMessage: sinon.stub() }, + origin: 'origin.sf.com' + }; + + _sendAdToCreative(mockAdObject, event); expect(slots[0].spyGetSlotElementId.called).to.equal(false); expect(slots[1].spyGetSlotElementId.called).to.equal(true); @@ -1162,15 +1096,13 @@ describe('Unit: Prebid Module', function () { height: 0 } }, - getElementsByTagName: sinon.stub(), - querySelector: sinon.stub() + getElementsByTagName: sinon.stub() }; elStub = { insertBefore: sinon.stub() }; doc.getElementsByTagName.returns([elStub]); - doc.querySelector.returns(elStub); spyLogError = sinon.spy(utils, 'logError'); spyLogMessage = sinon.spy(utils, 'logMessage'); @@ -1627,7 +1559,6 @@ describe('Unit: Prebid Module', function () { let auctionArgs; beforeEach(function () { - auctionArgs = null; adUnitsBackup = auction.getAdUnits auctionManagerStub = sinon.stub(auctionManager, 'createAuction').callsFake(function() { auctionArgs = arguments[0]; @@ -1882,39 +1813,11 @@ describe('Unit: Prebid Module', function () { pos: 2 } } - }, - { - code: 'test6', - bids: [], - sizes: [300, 250], - mediaTypes: { - banner: { - sizes: [300, 250], - pos: 0 - } - } }]; $$PREBID_GLOBAL$$.requestBids({ adUnits: adUnit }); expect(auctionArgs.adUnits[0].mediaTypes.banner.pos).to.equal(2); - expect(auctionArgs.adUnits[1].mediaTypes.banner.pos).to.equal(0); - }); - - it(`should allow no bids if 'ortb2Imp' is specified`, () => { - const adUnit = { - code: 'test', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - ortb2Imp: {} - }; - $$PREBID_GLOBAL$$.requestBids({ - adUnits: [adUnit] - }); - sinon.assert.match(auctionArgs.adUnits[0], adUnit); }); }); @@ -2051,7 +1954,7 @@ describe('Unit: Prebid Module', function () { }); expect(auctionArgs.adUnits.length).to.equal(1); expect(auctionArgs.adUnits[1]).to.not.exist; - assert.ok(logErrorSpy.calledWith("adUnit.code 'bad-ad-unit-2' has no 'adUnit.bids' and no 'adUnit.ortb2Imp'. Removing adUnit from auction")); + assert.ok(logErrorSpy.calledWith("Detected adUnit.code 'bad-ad-unit-2' did not have 'adUnit.bids' defined or 'adUnit.bids' is not an array. Removing adUnit from auction.")); }); }); }); diff --git a/test/spec/unit/secureCreatives_spec.js b/test/spec/unit/secureCreatives_spec.js index e3dc21ffd92..eca00e8c8fa 100644 --- a/test/spec/unit/secureCreatives_spec.js +++ b/test/spec/unit/secureCreatives_spec.js @@ -1,60 +1,20 @@ import { - _sendAdToCreative, getReplier, receiveMessage + _sendAdToCreative, receiveMessage } from 'src/secureCreatives.js'; -import * as secureCreatives from 'src/secureCreatives.js'; import * as utils from 'src/utils.js'; import {getAdUnits, getBidRequests, getBidResponses} from 'test/fixtures/fixtures.js'; import {auctionManager} from 'src/auctionManager.js'; import * as auctionModule from 'src/auction.js'; import * as native from 'src/native.js'; import {fireNativeTrackers, getAllAssetsMessage} from 'src/native.js'; -import * as events from 'src/events.js'; +import events from 'src/events.js'; import { config as configObj } from 'src/config.js'; -import 'src/prebid.js'; import { expect } from 'chai'; var CONSTANTS = require('src/constants.json'); describe('secureCreatives', () => { - function makeEvent(ev) { - return Object.assign({origin: 'mock-origin', ports: []}, ev) - } - - describe('getReplier', () => { - it('should use source.postMessage if no MessagePort is available', () => { - const ev = { - ports: [], - source: { - postMessage: sinon.spy() - }, - origin: 'mock-origin' - }; - getReplier(ev)('test'); - sinon.assert.calledWith(ev.source.postMessage, JSON.stringify('test')); - }); - - it('should use MesagePort.postMessage if available', () => { - const ev = { - ports: [{ - postMessage: sinon.spy() - }] - } - getReplier(ev)('test'); - sinon.assert.calledWith(ev.ports[0].postMessage, JSON.stringify('test')); - }); - - it('should throw if origin is null and no MessagePort is available', () => { - const ev = { - origin: null, - ports: [], - postMessage: sinon.spy() - } - const reply = getReplier(ev); - expect(() => reply('test')).to.throw(); - }); - }); - describe('_sendAdToCreative', () => { beforeEach(function () { sinon.stub(utils, 'logError'); @@ -80,10 +40,14 @@ describe('secureCreatives', () => { cpm: '1.00', adUnitCode: 'some_dom_id' }; - const reply = sinon.spy(); - _sendAdToCreative(mockAdObject, reply); - expect(reply.args[0][0].ad).to.equal(''); - expect(reply.args[0][0].adUrl).to.equal('http://creative.prebid.org/1.00'); + const event = { + source: { postMessage: sinon.stub() }, + origin: 'origin.sf.com' + }; + + _sendAdToCreative(mockAdObject, event); + expect(JSON.parse(event.source.postMessage.args[0][0]).ad).to.equal(''); + expect(JSON.parse(event.source.postMessage.args[0][0]).adUrl).to.equal('http://creative.prebid.org/1.00'); window.googletag = oldVal; window.apntag = oldapntag; }); @@ -152,7 +116,7 @@ describe('secureCreatives', () => { beforeEach(function() { spyAddWinningBid = sinon.spy(auctionManager, 'addWinningBid'); spyLogWarn = sinon.spy(utils, 'logWarn'); - stubFireNativeTrackers = sinon.stub(native, 'fireNativeTrackers').callsFake(message => { return message.action; }); + stubFireNativeTrackers = sinon.stub(native, 'fireNativeTrackers'); stubGetAllAssetsMessage = sinon.stub(native, 'getAllAssetsMessage'); stubEmit = sinon.stub(events, 'emit'); }); @@ -177,9 +141,9 @@ describe('secureCreatives', () => { message: 'Prebid Request' }; - const ev = makeEvent({ - data: JSON.stringify(data), - }); + const ev = { + data: JSON.stringify(data) + }; receiveMessage(ev); @@ -204,9 +168,9 @@ describe('secureCreatives', () => { message: 'Prebid Request' }; - const ev = makeEvent({ + const ev = { data: JSON.stringify(data) - }); + }; receiveMessage(ev); @@ -245,9 +209,9 @@ describe('secureCreatives', () => { message: 'Prebid Request' }; - const ev = makeEvent({ + const ev = { data: JSON.stringify(data) - }); + }; receiveMessage(ev); @@ -273,38 +237,6 @@ describe('secureCreatives', () => { configObj.setConfig({'auctionOptions': {}}); }); - - it('should emit AD_RENDER_FAILED if requested missing adId', () => { - const ev = makeEvent({ - data: JSON.stringify({ - message: 'Prebid Request', - adId: 'missing' - }) - }); - receiveMessage(ev); - sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.AD_RENDER_FAILED, sinon.match({ - reason: CONSTANTS.AD_RENDER_FAILED_REASON.CANNOT_FIND_AD, - adId: 'missing' - })); - }); - - it('should emit AD_RENDER_FAILED if creative can\'t be sent to rendering frame', () => { - pushBidResponseToAuction({}); - const ev = makeEvent({ - source: { - postMessage: sinon.stub().callsFake(() => { throw new Error(); }) - }, - data: JSON.stringify({ - message: 'Prebid Request', - adId: bidId - }) - }); - receiveMessage(ev) - sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.AD_RENDER_FAILED, sinon.match({ - reason: CONSTANTS.AD_RENDER_FAILED_REASON.EXCEPTION, - adId: bidId - })); - }); }); describe('Prebid Native', function() { @@ -317,13 +249,13 @@ describe('secureCreatives', () => { action: 'allAssetRequest' }; - const ev = makeEvent({ + const ev = { data: JSON.stringify(data), source: { postMessage: sinon.stub() }, origin: 'any origin' - }); + }; receiveMessage(ev); @@ -331,9 +263,10 @@ describe('secureCreatives', () => { sinon.assert.calledOnce(stubGetAllAssetsMessage); sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse); sinon.assert.calledOnce(ev.source.postMessage); - sinon.assert.notCalled(stubFireNativeTrackers); - sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON); - sinon.assert.notCalled(spyAddWinningBid); + sinon.assert.calledOnce(stubFireNativeTrackers); + sinon.assert.calledWith(stubFireNativeTrackers, data, adResponse); + sinon.assert.calledOnce(spyAddWinningBid); + sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse); sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER); }); @@ -346,13 +279,13 @@ describe('secureCreatives', () => { action: 'allAssetRequest' }; - const ev = makeEvent({ + const ev = { data: JSON.stringify(data), source: { postMessage: sinon.stub() }, origin: 'any origin' - }); + }; receiveMessage(ev); @@ -360,11 +293,14 @@ describe('secureCreatives', () => { sinon.assert.calledOnce(stubGetAllAssetsMessage); sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse); sinon.assert.calledOnce(ev.source.postMessage); - sinon.assert.notCalled(stubFireNativeTrackers); - sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON); - sinon.assert.notCalled(spyAddWinningBid); + sinon.assert.calledOnce(stubFireNativeTrackers); + sinon.assert.calledWith(stubFireNativeTrackers, data, adResponse); + sinon.assert.calledOnce(spyAddWinningBid); + sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse); sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER); + expect(adResponse).to.have.property('status', CONSTANTS.BID_STATUS.RENDERED); + resetHistories(ev.source.postMessage); receiveMessage(ev); @@ -373,9 +309,10 @@ describe('secureCreatives', () => { sinon.assert.calledOnce(stubGetAllAssetsMessage); sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse); sinon.assert.calledOnce(ev.source.postMessage); - sinon.assert.notCalled(stubFireNativeTrackers); - sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON); - sinon.assert.notCalled(spyAddWinningBid); + sinon.assert.calledOnce(stubFireNativeTrackers); + sinon.assert.calledWith(stubFireNativeTrackers, data, adResponse); + sinon.assert.calledOnce(spyAddWinningBid); + sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse); sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER); }); @@ -390,13 +327,13 @@ describe('secureCreatives', () => { action: 'allAssetRequest' }; - const ev = makeEvent({ + const ev = { data: JSON.stringify(data), source: { postMessage: sinon.stub() }, origin: 'any origin' - }); + }; receiveMessage(ev); @@ -404,11 +341,14 @@ describe('secureCreatives', () => { sinon.assert.calledOnce(stubGetAllAssetsMessage); sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse); sinon.assert.calledOnce(ev.source.postMessage); - sinon.assert.notCalled(stubFireNativeTrackers); - sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON); - sinon.assert.notCalled(spyAddWinningBid); + sinon.assert.calledOnce(stubFireNativeTrackers); + sinon.assert.calledWith(stubFireNativeTrackers, data, adResponse); + sinon.assert.calledOnce(spyAddWinningBid); + sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse); sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER); + expect(adResponse).to.have.property('status', CONSTANTS.BID_STATUS.RENDERED); + resetHistories(ev.source.postMessage); receiveMessage(ev); @@ -417,101 +357,13 @@ describe('secureCreatives', () => { sinon.assert.calledOnce(stubGetAllAssetsMessage); sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse); sinon.assert.calledOnce(ev.source.postMessage); - sinon.assert.notCalled(stubFireNativeTrackers); - sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON); - sinon.assert.notCalled(spyAddWinningBid); - sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER); - - configObj.setConfig({'auctionOptions': {}}); - }); - - it('Prebid native should fire trackers', function () { - pushBidResponseToAuction({}); - - const data = { - adId: bidId, - message: 'Prebid Native', - action: 'click', - }; - - const ev = makeEvent({ - data: JSON.stringify(data), - source: { - postMessage: sinon.stub() - }, - origin: 'any origin' - }); - - receiveMessage(ev); - - sinon.assert.neverCalledWith(spyLogWarn, warning); - sinon.assert.calledOnce(stubFireNativeTrackers); - sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON); - sinon.assert.notCalled(spyAddWinningBid); - - resetHistories(ev.source.postMessage); - - delete data.action; - ev.data = JSON.stringify(data); - receiveMessage(ev); - - sinon.assert.neverCalledWith(spyLogWarn, warning); sinon.assert.calledOnce(stubFireNativeTrackers); - sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse); + sinon.assert.calledWith(stubFireNativeTrackers, data, adResponse); sinon.assert.calledOnce(spyAddWinningBid); + sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse); + sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER); - expect(adResponse).to.have.property('status', CONSTANTS.BID_STATUS.RENDERED); - }); - }); - - describe('Prebid Event', () => { - Object.entries({ - 'unrendered': [false, (bid) => { delete bid.status; }], - 'rendered': [true, (bid) => { bid.status = CONSTANTS.BID_STATUS.RENDERED }] - }).forEach(([test, [shouldEmit, prepBid]]) => { - describe(`for ${test} bids`, () => { - beforeEach(() => { - prepBid(adResponse); - pushBidResponseToAuction(adResponse); - }); - - it(`should${shouldEmit ? ' ' : ' not '}emit AD_RENDER_FAILED`, () => { - const event = makeEvent({ - data: JSON.stringify({ - message: 'Prebid Event', - event: CONSTANTS.EVENTS.AD_RENDER_FAILED, - adId: bidId, - info: { - reason: 'Fail reason', - message: 'Fail message', - }, - }) - }); - receiveMessage(event); - expect(stubEmit.calledWith(CONSTANTS.EVENTS.AD_RENDER_FAILED, { - adId: bidId, - bid: adResponse, - reason: 'Fail reason', - message: 'Fail message' - })).to.equal(shouldEmit); - }); - - it(`should${shouldEmit ? ' ' : ' not '}emit AD_RENDER_SUCCEEDED`, () => { - const event = makeEvent({ - data: JSON.stringify({ - message: 'Prebid Event', - event: CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED, - adId: bidId, - }) - }); - receiveMessage(event); - expect(stubEmit.calledWith(CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED, { - adId: bidId, - bid: adResponse, - doc: null - })).to.equal(shouldEmit); - }); - }); + configObj.setConfig({'auctionOptions': {}}); }); }); }); diff --git a/test/spec/userSync_spec.js b/test/spec/userSync_spec.js index 910ffe7b2d6..55b613ce929 100644 --- a/test/spec/userSync_spec.js +++ b/test/spec/userSync_spec.js @@ -401,33 +401,6 @@ describe('user sync', function () { expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); }); - it('should not fire image pixel for a bidder if iframe pixel is fired for same bidder', function() { - const userSync = newUserSync({ - config: config.getConfig('userSync'), - browserSupportsCookies: true - }); - - config.setConfig({ - userSync: { - filterSettings: { - iframe: { - bidders: ['bidderXYZ'], - filter: 'include' - } - } - } - }); - // we are registering iframe and image sync for bidderXYZ and we expect image sync not to execute. - userSync.registerSync('image', 'testBidder', 'http://testBidder.example.com/image'); - userSync.registerSync('iframe', 'bidderXYZ', 'http://bidderXYZ.example.com/iframe'); - userSync.registerSync('image', 'bidderXYZ', 'http://bidderXYZ.example.com/image'); - userSync.syncUsers(); - expect(triggerPixelStub.getCall(0)).to.not.be.null; - expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://testBidder.example.com/image'); - expect(triggerPixelStub.callCount).to.equal(1); // should not be 2 for 2 registered image syncs - expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://bidderXYZ.example.com/iframe'); - }); - it('should override default image syncs if setConfig used image filter', function () { const userSync = newUserSync({ config: config.getConfig('userSync'), @@ -475,9 +448,8 @@ describe('user sync', function () { userSync.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); userSync.registerSync('iframe', 'bidderXYZ', 'http://example.com/iframe-blocked'); userSync.syncUsers(); - // expect(triggerPixelStub.getCall(0)).to.not.be.null; - expect(triggerPixelStub.getCall(0)).to.be.null;// image sync will not execute as iframe sync has executed for same bidder - // expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com'); + expect(triggerPixelStub.getCall(0)).to.not.be.null; + expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com'); expect(triggerPixelStub.getCall(1)).to.be.null; expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); expect(insertUserSyncIframeStub.getCall(1)).to.be.null; diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 50a95b079c9..6494ead78e7 100644 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -2,7 +2,6 @@ import { getAdServerTargeting } from 'test/fixtures/fixtures.js'; import { expect } from 'chai'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils.js'; -import {deepEqual, waitForElementToLoad} from 'src/utils.js'; var assert = require('assert'); @@ -1178,13 +1177,6 @@ describe('Utils', function () { } expect(utils.deepEqual(obj1, obj2)).to.equal(false); }); - it('should check types if {matchTypes: true}', () => { - function Typed(obj) { - Object.assign(this, obj); - } - const obj = {key: 'value'}; - expect(deepEqual({outer: obj}, {outer: new Typed(obj)}, {checkTypes: true})).to.be.false; - }); describe('cyrb53Hash', function() { it('should return the same hash for the same string', function() { @@ -1206,41 +1198,4 @@ describe('Utils', function () { }); }); }); - - describe('waitForElementToLoad', () => { - let element; - let callbacks; - - function callback() { - callbacks++; - } - - function delay(delay = 0) { - return new Promise((resolve) => { - window.setTimeout(resolve, delay); - }) - } - - beforeEach(() => { - callbacks = 0; - element = window.document.createElement('div'); - }); - - it('should respect timeout if set', () => { - waitForElementToLoad(element, 50).then(callback); - return delay(60).then(() => { - expect(callbacks).to.equal(1); - }); - }); - - ['load', 'error'].forEach((event) => { - it(`should complete on '${event} event'`, () => { - waitForElementToLoad(element).then(callback); - element.dispatchEvent(new Event(event)); - return delay().then(() => { - expect(callbacks).to.equal(1); - }) - }); - }); - }); }); diff --git a/test/spec/videoCache_spec.js b/test/spec/videoCache_spec.js index 34e9bed04b6..554db3ebe4e 100644 --- a/test/spec/videoCache_spec.js +++ b/test/spec/videoCache_spec.js @@ -2,8 +2,6 @@ import chai from 'chai'; import { getCacheUrl, store } from 'src/videoCache.js'; import { config } from 'src/config.js'; import { server } from 'test/mocks/xhr.js'; -import {auctionManager} from '../../src/auctionManager.js'; -import {AuctionIndex} from '../../src/auctionIndex.js'; const should = chai.should(); @@ -34,6 +32,23 @@ function getMockBid(bidder, auctionId, bidderRequestId) { }; } +function getMockBidRequest(bidder = 'appnexus', auctionId = '173afb6d132ba3', bidderRequestId = '3d1063078dfcc8') { + return { + 'bidderCode': bidder, + 'auctionId': auctionId, + 'bidderRequestId': bidderRequestId, + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'bids': [getMockBid(bidder, auctionId, bidderRequestId)], + 'auctionStart': 1510852447530, + 'timeout': 5000, + 'src': 's2s', + 'doneCbCallCount': 0, + 'refererInfo': { + 'referer': 'http://mytestpage.com' + } + } +} + describe('The video cache', function () { function assertError(callbackSpy) { callbackSpy.calledOnce.should.equal(true); @@ -225,7 +240,7 @@ describe('The video cache', function () { JSON.parse(request.requestBody).should.deep.equal(payload); }); - it('should include additional params in request payload should config.cache.vasttrack be true - with timestamp', () => { + it('should include additional params in request payload should config.cache.vasttrack be true and bidderRequest argument was defined', () => { config.setConfig({ cache: { url: 'https://prebid.adnxs.com/pbc/v1/cache', @@ -254,21 +269,7 @@ describe('The video cache', function () { auctionId: '1234-56789-abcde' }]; - const stub = sinon.stub(auctionManager, 'index'); - stub.get(() => new AuctionIndex(() => [{ - getAuctionId() { - return '1234-56789-abcde'; - }, - getAuctionStart() { - return 1510852447530; - } - }])) - try { - store(bids, function () { }); - } finally { - stub.restore(); - } - + store(bids, function () { }, getMockBidRequest()); const request = server.requests[0]; request.method.should.equal('POST'); request.url.should.equal('https://prebid.adnxs.com/pbc/v1/cache'); diff --git a/test/spec/video_spec.js b/test/spec/video_spec.js index 61621c7ec42..3ce8ba081da 100644 --- a/test/spec/video_spec.js +++ b/test/spec/video_spec.js @@ -1,103 +1,113 @@ import { isValidVideoBid } from 'src/video.js'; -import {hook} from '../../src/hook.js'; -import {stubAuctionIndex} from '../helpers/indexStub.js'; describe('video.js', function () { - before(() => { - hook.ready(); - }); - it('validates valid instream bids', function () { const bid = { adId: '456xyz', vastUrl: 'http://www.example.com/vastUrl', - transactionId: 'au' + requestId: '123abc' }; - const adUnits = [{ - transactionId: 'au', - mediaTypes: { - video: {context: 'instream'} - } + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'instream' } + } + }] }]; - const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})}); + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.equal(true); }); it('catches invalid instream bids', function () { const bid = { - transactionId: 'au' + requestId: '123abc' }; - const adUnits = [{ - transactionId: 'au', - mediaTypes: { - video: {context: 'instream'} - } + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'instream' } + } + }] }]; - const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})}); + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.equal(false); }); it('catches invalid bids when prebid-cache is disabled', function () { - const adUnits = [{ - transactionId: 'au', - bidder: 'vastOnlyVideoBidder', - mediaTypes: {video: {}}, + const bidRequests = [{ + bids: [{ + bidder: 'vastOnlyVideoBidder', + mediaTypes: { video: {} }, + }] }]; - const valid = isValidVideoBid({ transactionId: 'au', vastXml: 'vast' }, {index: stubAuctionIndex({adUnits})}); + const valid = isValidVideoBid({ vastXml: 'vast' }, bidRequests); expect(valid).to.equal(false); }); it('validates valid outstream bids', function () { const bid = { - transactionId: 'au', + requestId: '123abc', renderer: { url: 'render.url', render: () => true, } }; - const adUnits = [{ - transactionId: 'au', - mediaTypes: { - video: {context: 'outstream'} - } + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'outstream' } + } + }] }]; - const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})}); + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.equal(true); }); it('validates valid outstream bids with a publisher defined renderer', function () { const bid = { - transactionId: 'au', + requestId: '123abc', }; - const adUnits = [{ - transactionId: 'au', - mediaTypes: { - video: { - context: 'outstream', + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { + context: 'outstream', + renderer: { + url: 'render.url', + render: () => true, + } + } } - }, - renderer: { - url: 'render.url', - render: () => true, - } + }] }]; - const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})}); + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.equal(true); }); it('catches invalid outstream bids', function () { const bid = { - transactionId: 'au', + requestId: '123abc' }; - const adUnits = [{ - transactionId: 'au', - mediaTypes: { - video: {context: 'outstream'} - } + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'outstream' } + } + }] }]; - const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})}); + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.equal(false); }); }); diff --git a/test/test_deps.js b/test/test_deps.js deleted file mode 100644 index 8b8c9fd3a0f..00000000000 --- a/test/test_deps.js +++ /dev/null @@ -1,9 +0,0 @@ -window.process = { - env: { - NODE_ENV: 'production' - } -}; - -require('test/helpers/prebidGlobal.js'); -require('test/mocks/adloaderStub.js'); -require('test/mocks/xhr.js'); diff --git a/test/test_index.js b/test/test_index.js index 883f4d0590c..53d75e36176 100644 --- a/test/test_index.js +++ b/test/test_index.js @@ -1,4 +1,6 @@ -require('./test_deps.js'); +require('test/helpers/prebidGlobal.js'); +require('test/mocks/adloaderStub.js'); +require('test/mocks/xhr.js'); var testsContext = require.context('.', true, /_spec$/); testsContext.keys().forEach(testsContext); diff --git a/wdio.conf.js b/wdio.conf.js index 4f14d4c7a6d..c9aaa3f160d 100644 --- a/wdio.conf.js +++ b/wdio.conf.js @@ -1,34 +1,36 @@ -const browsers = Object.fromEntries( - Object.entries(require('./browsers.json')) - .filter(([k, v]) => { - // run only on latest; exclude Safari - // (Webdriver's `browser.url(...)` times out on Safari if the page loads a video; does it wait for playback to complete?) - return v.browser_version === 'latest' && v.browser !== 'safari' - }) -); +const browsers = require('./browsers.json'); function getCapabilities() { function getPlatform(os) { const platformMap = { 'Windows': 'WINDOWS', - 'OS X': 'OS X', + 'OS X': 'MAC', } return platformMap[os]; } + // only IE 11, Chrome 80 & Firefox 73 run as part of functional tests + // rest of the browsers are discarded. + delete browsers['bs_chrome_79_windows_10']; + delete browsers['bs_firefox_72_windows_10']; + delete browsers['bs_safari_11_mac_catalina']; + delete browsers['bs_safari_12_mac_mojave']; + // disable all edge browsers due to wdio bug for switchToFrame: https://github.com/webdriverio/webdriverio/issues/3880 + delete browsers['bs_edge_18_windows_10']; + delete browsers['bs_edge_17_windows_10']; + let capabilities = [] - Object.values(browsers).forEach(browser => { + Object.keys(browsers).forEach(key => { + let browser = browsers[key]; capabilities.push({ browserName: browser.browser, - browserVersion: browser.browser_version, - 'bstack:options': { - os: getPlatform(browser.os), - osVersion: browser.os_version, - networkLogs: true, - consoleLogs: 'verbose', - buildName: `Prebidjs E2E (${browser.browser} ${browser.browser_version}) ${new Date().toLocaleString()}` - }, - acceptInsecureCerts: true, + os: getPlatform(browser.os), + os_version: browser.os_version, + browser_version: browser.browser_version, + acceptSslCerts: true, + 'browserstack.networkLogs': true, + 'browserstack.console': 'verbose', + build: 'Prebidjs E2E ' + new Date().toLocaleString() }); }); return capabilities; @@ -36,12 +38,7 @@ function getCapabilities() { exports.config = { specs: [ - './test/spec/e2e/**/*.spec.js', - ], - exclude: [ - // TODO: decipher original intent for "longform" tests - // they all appear to be almost exact copies - './test/spec/e2e/longform/**/*' + './test/spec/e2e/**/*.spec.js' ], services: [ ['browserstack', { @@ -52,7 +49,7 @@ exports.config = { key: process.env.BROWSERSTACK_ACCESS_KEY, maxInstances: 5, // Do not increase this, since we have only 5 parallel tests in browserstack account capabilities: getCapabilities(), - logLevel: 'info', // put option here: info | trace | debug | warn| error | silent + logLevel: 'silent', // put option here: info | trace | debug | warn| error | silent bail: 0, waitforTimeout: 60000, // Default timeout for all waitFor* commands. connectionRetryTimeout: 60000, // Default timeout in milliseconds for request if Selenium Grid doesn't send response @@ -64,5 +61,5 @@ exports.config = { compilers: ['js:babel-register'], }, // if you see error, update this to spec reporter and logLevel above to get detailed report. - reporters: ['spec'] + reporters: ['concise'] } diff --git a/webpack.conf.js b/webpack.conf.js index 5269f5300f5..a738a2a0868 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -2,11 +2,19 @@ var prebid = require('./package.json'); var path = require('path'); var webpack = require('webpack'); var helpers = require('./gulpHelpers.js'); +var RequireEnsureWithoutJsonp = require('./plugins/RequireEnsureWithoutJsonp.js'); var { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); var argv = require('yargs').argv; +var allowedModules = require('./allowedModules.js'); + +// list of module names to never include in the common bundle chunk +var neverBundle = [ + 'AnalyticsAdapter.js' +]; var plugins = [ - new webpack.EnvironmentPlugin({'LiveConnectMode': null}) + new RequireEnsureWithoutJsonp(), + new webpack.EnvironmentPlugin(['LiveConnectMode']) ]; if (argv.analyze) { @@ -15,8 +23,27 @@ if (argv.analyze) { ) } +plugins.push( // this plugin must be last so it can be easily removed for karma unit tests + new webpack.optimize.CommonsChunkPlugin({ + name: 'prebid', + filename: 'prebid-core.js', + minChunks: function(module) { + return ( + ( + module.context && module.context.startsWith(path.resolve('./src')) && + !(module.resource && neverBundle.some(name => module.resource.includes(name))) + ) || + ( + module.resource && (allowedModules.src.concat(['core-js'])).some( + name => module.resource.includes(path.resolve('./node_modules/' + name)) + ) + ) + ); + } + }) +); + module.exports = { - mode: 'production', devtool: 'source-map', resolve: { modules: [ @@ -24,26 +51,8 @@ module.exports = { 'node_modules' ], }, - entry: (() => { - const entry = { - 'prebid-core': { - import: './src/prebid.js' - } - }; - const selectedModules = new Set(helpers.getArgModules()); - Object.entries(helpers.getModules()).forEach(([fn, mod]) => { - if (selectedModules.size === 0 || selectedModules.has(mod)) { - entry[mod] = { - import: fn, - dependOn: 'prebid-core' - } - } - }); - return entry; - })(), output: { - chunkLoadingGlobal: prebid.globalVarName + 'Chunk', - chunkLoading: 'jsonp', + jsonpFunction: prebid.globalVarName + 'Chunk' }, module: { rules: [ @@ -68,9 +77,5 @@ module.exports = { } ] }, - optimization: { - usedExports: true, - sideEffects: true, - }, plugins };